Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file MSAbstractLaneChangeModel.h
15 : /// @author Daniel Krajzewicz
16 : /// @author Friedemann Wesner
17 : /// @author Sascha Krieg
18 : /// @author Michael Behrisch
19 : /// @author Jakob Erdmann
20 : /// @author Leonhard Luecken
21 : /// @date Fri, 29.04.2005
22 : ///
23 : // Interface for lane-change models
24 : /****************************************************************************/
25 : #pragma once
26 : #include <config.h>
27 :
28 : #include <microsim/MSGlobals.h>
29 : #include <microsim/MSLeaderInfo.h>
30 : #include <microsim/MSVehicle.h>
31 :
32 :
33 : // ===========================================================================
34 : // class declarations
35 : // ===========================================================================
36 : class MSLane;
37 : class SUMOSAXAttributes;
38 :
39 :
40 : // ===========================================================================
41 : // class definitions
42 : // ===========================================================================
43 : /**
44 : * @class MSAbstractLaneChangeModel
45 : * @brief Interface for lane-change models
46 : */
47 : class MSAbstractLaneChangeModel {
48 : public:
49 :
50 : /** @class MSLCMessager
51 : * @brief A class responsible for exchanging messages between cars involved in lane-change interaction
52 : */
53 : class MSLCMessager {
54 : public:
55 : /** @brief Constructor
56 : * @param[in] leader The leader on the informed vehicle's lane
57 : * @param[in] neighLead The leader on the lane the vehicle want to change to
58 : * @param[in] neighFollow The follower on the lane the vehicle want to change to
59 : */
60 : MSLCMessager(MSVehicle* leader, MSVehicle* neighLead, MSVehicle* neighFollow)
61 234853342 : : myLeader(leader), myNeighLeader(neighLead),
62 234853342 : myNeighFollower(neighFollow) { }
63 :
64 :
65 : /// @brief Destructor
66 234853342 : ~MSLCMessager() { }
67 :
68 :
69 : /** @brief Informs the leader on the same lane
70 : * @param[in] info The information to pass
71 : * @param[in] sender The sending vehicle (the lane changing vehicle)
72 : * @return Something!?
73 : */
74 : void* informLeader(void* info, MSVehicle* sender) {
75 : assert(myLeader != 0);
76 : return myLeader->getLaneChangeModel().inform(info, sender);
77 : }
78 :
79 :
80 : /** @brief Informs the leader on the desired lane
81 : * @param[in] info The information to pass
82 : * @param[in] sender The sending vehicle (the lane changing vehicle)
83 : * @return Something!?
84 : */
85 2305717 : void* informNeighLeader(void* info, MSVehicle* sender) {
86 : assert(myNeighLeader != 0);
87 2305717 : return myNeighLeader->getLaneChangeModel().inform(info, sender);
88 : }
89 :
90 :
91 : /** @brief Informs the follower on the desired lane
92 : * @param[in] info The information to pass
93 : * @param[in] sender The sending vehicle (the lane changing vehicle)
94 : * @return Something!?
95 : */
96 1979950 : void* informNeighFollower(void* info, MSVehicle* sender) {
97 : assert(myNeighFollower != 0);
98 1979950 : return myNeighFollower->getLaneChangeModel().inform(info, sender);
99 : }
100 :
101 :
102 : private:
103 : /// @brief The leader on the informed vehicle's lane
104 : MSVehicle* myLeader;
105 : /// @brief The leader on the lane the vehicle want to change to
106 : MSVehicle* myNeighLeader;
107 : /// @brief The follower on the lane the vehicle want to change to
108 : MSVehicle* myNeighFollower;
109 :
110 : };
111 :
112 : struct StateAndDist {
113 : // @brief LaneChangeAction flags
114 : int state;
115 : // @brief Lateral distance to be completed in the next step
116 : double latDist;
117 : // @brief Full lateral distance required for the completion of the envisioned maneuver
118 : double maneuverDist;
119 : // @brief direction that was checked
120 : int dir;
121 :
122 237312537 : StateAndDist(int _state, double _latDist, double _targetDist, int _dir) :
123 237312537 : state(_state),
124 237312537 : latDist(_latDist),
125 237312537 : maneuverDist(_targetDist),
126 237312537 : dir(_dir) {}
127 :
128 : bool sameDirection(const StateAndDist& other) const {
129 4199245 : return latDist * other.latDist > 0;
130 : }
131 : };
132 :
133 : /// @brief init global model parameters
134 : void static initGlobalOptions(const OptionsCont& oc);
135 :
136 : /** @brief Factory method for instantiating new lane changing models
137 : * @param[in] lcm The type of model to build
138 : * @param[in] vehicle The vehicle for which this model shall be built
139 : */
140 : static MSAbstractLaneChangeModel* build(LaneChangeModel lcm, MSVehicle& vehicle);
141 :
142 : /** @brief Returns the model's ID;
143 : * @return The model's ID
144 : */
145 : virtual LaneChangeModel getModelID() const = 0;
146 :
147 : /** @brief Informs the vehicle that it is about to be moved on an adjacent lane.
148 : * The method can be used to re-evaluate the state of the vehicle and potentially abort the lane change.
149 : * By default, if the method is not overridden by the lane change model implementation, nothing is altered and the vehicle will perform the lane change.
150 : * @param veh the lane changing vehicle
151 : * @param state current lane change state
152 : * @return the blocked status of the vehicle. If the vehicle should perform the lane change, the method should return 0, corresponding to non-blocked.
153 : * Otherwise the method should return a non-zero state, corresponding to the type of blockage.
154 : */
155 730993 : virtual int checkChangeBeforeCommitting(const MSVehicle* veh, int state) const {
156 : UNUSED_PARAMETER(veh);
157 : UNUSED_PARAMETER(state);
158 730993 : return 0;
159 : }
160 :
161 : /** @brief Save the state of the laneChangeModel
162 : * @param[in] out The OutputDevice to write the information into
163 : */
164 : virtual void saveState(OutputDevice& out) const;
165 :
166 : /** @brief Loads the state of the laneChangeModel from the given attributes
167 : * @param[in] attrs XML attributes describing the current state
168 : */
169 : virtual void loadState(const SUMOSAXAttributes& attrs);
170 :
171 : /// @brief whether lanechange-output is active
172 : static bool haveLCOutput() {
173 6233858 : return myLCOutput;
174 : }
175 :
176 : /// @brief whether start of maneuvers shall be recorede
177 : static bool outputLCStarted() {
178 435595 : return myLCStartedOutput;
179 : }
180 :
181 : /// @brief whether start of maneuvers shall be recorede
182 : static bool outputLCEnded() {
183 147413 : return myLCEndedOutput;
184 : }
185 :
186 : /** @brief Constructor
187 : * @param[in] v The vehicle this lane-changer belongs to
188 : * @param[in] model The type of lane change model
189 : */
190 : MSAbstractLaneChangeModel(MSVehicle& v, const LaneChangeModel model);
191 :
192 : /// @brief Destructor
193 : virtual ~MSAbstractLaneChangeModel();
194 :
195 : inline int getOwnState() const {
196 841259717 : return myOwnState;
197 : }
198 :
199 : inline int getPrevState() const {
200 : /// at the time of this call myPreviousState already holds the new value
201 79974537 : return myPreviousState2;
202 : }
203 :
204 : virtual void setOwnState(const int state);
205 :
206 : /// @brief Updates the remaining distance for the current maneuver while it is continued within non-action steps (only used by sublane model)
207 : void setManeuverDist(const double dist);
208 : /// @brief Returns the remaining unblocked distance for the current maneuver. (only used by sublane model)
209 : double getManeuverDist() const;
210 : double getPreviousManeuverDist() const;
211 :
212 : /// @brief Updates the value of safe lateral distances (in SL2015) during maneuver continuation in non-action steps
213 : virtual void updateSafeLatDist(const double travelledLatDist);
214 :
215 : const std::pair<int, int>& getSavedState(const int dir) const {
216 16067 : if (dir == -1) {
217 5482 : return mySavedStateRight;
218 10585 : } else if (dir == 0) {
219 5103 : return mySavedStateCenter;
220 : } else {
221 5482 : return mySavedStateLeft;
222 : }
223 : }
224 :
225 : void saveLCState(const int dir, int stateWithoutTraCI, const int state) {
226 363115417 : int canceledStrategic = getCanceledState(dir);
227 : // avoid conflicting directions
228 353853191 : if ((canceledStrategic & LCA_WANTS_LANECHANGE_OR_STAY) != 0) {
229 : stateWithoutTraCI = canceledStrategic;
230 : }
231 : const auto pair = std::make_pair(stateWithoutTraCI, state);
232 349222078 : if (dir == -1) {
233 : mySavedStateRight = pair;
234 220721261 : } else if (dir == 0) {
235 : mySavedStateCenter = pair;
236 : } else {
237 : mySavedStateLeft = pair;
238 : }
239 : }
240 :
241 : /// @brief Saves the lane change relevant vehicles, which are currently on neighboring lanes in the given direction
242 : /// (as detected in wantsChangeSublane()). -> SL2015 case
243 : void saveNeighbors(const int dir, const MSLeaderDistanceInfo& followers, const MSLeaderDistanceInfo& leaders);
244 :
245 : /// @brief Saves the lane change relevant vehicles, which are currently on neighboring lanes in the given direction
246 : /// (as detected in wantsChange()). -> LC2013 case
247 : void saveNeighbors(const int dir, const std::pair<MSVehicle* const, double>& follower, const std::pair<MSVehicle* const, double>& leader);
248 :
249 : /// @brief Clear info on neighboring vehicle from previous step
250 : void clearNeighbors();
251 :
252 : /// @brief Returns the neighboring, lc-relevant followers for the last step in the requested direction
253 : const std::shared_ptr<MSLeaderDistanceInfo> getFollowers(const int dir);
254 :
255 : /// @brief Returns the neighboring, lc-relevant leaders for the last step in the requested direction
256 : const std::shared_ptr<MSLeaderDistanceInfo> getLeaders(const int dir);
257 :
258 : int& getCanceledState(const int dir) {
259 815519595 : if (dir == -1) {
260 306407585 : return myCanceledStateRight;
261 509112010 : } else if (dir == 0) {
262 165557245 : return myCanceledStateCenter;
263 : } else {
264 343554765 : return myCanceledStateLeft;
265 : }
266 : }
267 :
268 : /// @return whether this vehicle is blocked from performing a strategic change
269 : bool isStrategicBlocked() const;
270 :
271 : void setFollowerGaps(CLeaderDist follower, double secGap);
272 : void setLeaderGaps(CLeaderDist, double secGap);
273 : void setOrigLeaderGaps(CLeaderDist, double secGap);
274 : void setFollowerGaps(const MSLeaderDistanceInfo& vehicles);
275 : void setLeaderGaps(const MSLeaderDistanceInfo& vehicles);
276 : void setOrigLeaderGaps(const MSLeaderDistanceInfo& vehicles);
277 :
278 : virtual void prepareStep();
279 :
280 : /** @brief Called to examine whether the vehicle wants to change
281 : * using the given laneOffset.
282 : * This method gets the information about the surrounding vehicles
283 : * and whether another lane may be more preferable */
284 0 : virtual int wantsChange(
285 : int laneOffset,
286 : MSAbstractLaneChangeModel::MSLCMessager& msgPass, int blocked,
287 : const std::pair<MSVehicle*, double>& leader,
288 : const std::pair<MSVehicle*, double>& follower,
289 : const std::pair<MSVehicle*, double>& neighLead,
290 : const std::pair<MSVehicle*, double>& neighFollow,
291 : const MSLane& neighLane,
292 : const std::vector<MSVehicle::LaneQ>& preb,
293 : MSVehicle** lastBlocked,
294 : MSVehicle** firstBlocked) {
295 : UNUSED_PARAMETER(laneOffset);
296 : UNUSED_PARAMETER(&msgPass);
297 : UNUSED_PARAMETER(blocked);
298 : UNUSED_PARAMETER(&leader);
299 : UNUSED_PARAMETER(&follower);
300 : UNUSED_PARAMETER(&neighLead);
301 : UNUSED_PARAMETER(&neighFollow);
302 : UNUSED_PARAMETER(&neighLane);
303 : UNUSED_PARAMETER(&preb);
304 : UNUSED_PARAMETER(lastBlocked);
305 : UNUSED_PARAMETER(firstBlocked);
306 0 : throw ProcessError("Method not implemented by model " + toString(myModel));
307 : };
308 :
309 0 : virtual int wantsChangeSublane(
310 : int laneOffset,
311 : LaneChangeAction alternatives,
312 : const MSLeaderDistanceInfo& leaders,
313 : const MSLeaderDistanceInfo& followers,
314 : const MSLeaderDistanceInfo& blockers,
315 : const MSLeaderDistanceInfo& neighLeaders,
316 : const MSLeaderDistanceInfo& neighFollowers,
317 : const MSLeaderDistanceInfo& neighBlockers,
318 : const MSLane& neighLane,
319 : const std::vector<MSVehicle::LaneQ>& preb,
320 : MSVehicle** lastBlocked,
321 : MSVehicle** firstBlocked,
322 : double& latDist, double& targetDistLat, int& blocked) {
323 : UNUSED_PARAMETER(laneOffset);
324 : UNUSED_PARAMETER(alternatives);
325 : UNUSED_PARAMETER(&leaders);
326 : UNUSED_PARAMETER(&followers);
327 : UNUSED_PARAMETER(&blockers);
328 : UNUSED_PARAMETER(&neighLeaders);
329 : UNUSED_PARAMETER(&neighFollowers);
330 : UNUSED_PARAMETER(&neighBlockers);
331 : UNUSED_PARAMETER(&neighLane);
332 : UNUSED_PARAMETER(&preb);
333 : UNUSED_PARAMETER(lastBlocked);
334 : UNUSED_PARAMETER(firstBlocked);
335 : UNUSED_PARAMETER(latDist);
336 : UNUSED_PARAMETER(targetDistLat);
337 : UNUSED_PARAMETER(blocked);
338 0 : throw ProcessError("Method not implemented by model " + toString(myModel));
339 : }
340 :
341 : /// @brief update expected speeds for each sublane of the current edge
342 0 : virtual void updateExpectedSublaneSpeeds(const MSLeaderDistanceInfo& ahead, int sublaneOffset, int laneIndex) {
343 : UNUSED_PARAMETER(&ahead);
344 : UNUSED_PARAMETER(sublaneOffset);
345 : UNUSED_PARAMETER(laneIndex);
346 0 : throw ProcessError("Method not implemented by model " + toString(myModel));
347 : }
348 :
349 : /// @brief decide in which direction to move in case both directions are desirable
350 0 : virtual StateAndDist decideDirection(StateAndDist sd1, StateAndDist sd2) const {
351 : UNUSED_PARAMETER(sd1);
352 : UNUSED_PARAMETER(sd2);
353 0 : throw ProcessError("Method not implemented by model " + toString(myModel));
354 : }
355 :
356 : virtual void* inform(void* info, MSVehicle* sender) = 0;
357 :
358 : /** @brief Called to adapt the speed in order to allow a lane change.
359 : * It uses information on LC-related desired speed-changes from
360 : * the call to wantsChange() at the end of the previous simulation step
361 : *
362 : * It is guaranteed that min<=wanted<=max, but the implementation needs
363 : * to make sure that the return value is between min and max.
364 : *
365 : * @param min The minimum resulting speed
366 : * @param wanted The aspired speed of the car following model
367 : * @param max The maximum resulting speed
368 : * @param cfModel The model used
369 : * @return the new speed of the vehicle as proposed by the lane changer
370 : */
371 : virtual double patchSpeed(const double min, const double wanted, const double max,
372 : const MSCFModel& cfModel) = 0;
373 :
374 : /* @brief called once when the primary lane of the vehicle changes (updates
375 : * the custom variables of each child implementation */
376 : virtual void changed() = 0;
377 :
378 : /* @brief called once when the vehicle moves to a new lane in an "irregular" way (i.e. by teleporting)
379 : * resets custom variables of each child implementation */
380 0 : virtual void resetState() {};
381 :
382 : /// @brief return factor for modifying the safety constraints of the car-following model
383 0 : virtual double getSafetyFactor() const {
384 0 : return 1.0;
385 : }
386 :
387 : /// @brief return factor for modifying the safety constraints for opposite-diretction overtaking of the car-following model
388 0 : virtual double getOppositeSafetyFactor() const {
389 0 : return 1.0;
390 : }
391 :
392 : /// @brief whether the current vehicles shall be debugged
393 0 : virtual bool debugVehicle() const {
394 0 : return false;
395 : }
396 :
397 : /// @brief called when a vehicle changes between lanes in opposite directions
398 : void changedToOpposite();
399 :
400 : void unchanged() {
401 352496542 : if (myLastLaneChangeOffset > 0) {
402 56063018 : myLastLaneChangeOffset += DELTA_T;
403 296433524 : } else if (myLastLaneChangeOffset < 0) {
404 38141215 : myLastLaneChangeOffset -= DELTA_T;
405 : }
406 : }
407 :
408 : /** @brief Returns the lane the vehicle's shadow is on during continuous/sublane lane change
409 : * @return The vehicle's shadow lane
410 : */
411 : MSLane* getShadowLane() const {
412 11919816136 : return myShadowLane;
413 : }
414 :
415 : /// @brief return the shadow lane for the given lane
416 : MSLane* getShadowLane(const MSLane* lane) const;
417 :
418 : /// @brief return the shadow lane for the given lane and lateral offset
419 : MSLane* getShadowLane(const MSLane* lane, double posLat) const;
420 :
421 : const std::vector<MSLane*>& getShadowFurtherLanes() const {
422 : return myShadowFurtherLanes;
423 : }
424 :
425 : const std::vector<double>& getShadowFurtherLanesPosLat() const {
426 : return myShadowFurtherLanesPosLat;
427 : }
428 :
429 : /** @brief Returns the lane the vehicle has committed to enter during a sublane lane change
430 : * @return The vehicle's target lane.
431 : */
432 : MSLane* getTargetLane() const {
433 4483085675 : return myTargetLane;
434 : }
435 :
436 : const std::vector<MSLane*>& getFurtherTargetLanes() const {
437 4 : return myFurtherTargetLanes;
438 : }
439 :
440 : inline SUMOTime getLastLaneChangeOffset() const {
441 24539 : return myLastLaneChangeOffset;
442 : }
443 :
444 :
445 : /// @brief return whether the vehicle passed the midpoint of a continuous lane change maneuver
446 : inline bool pastMidpoint() const {
447 579396 : return myLaneChangeCompletion >= 0.5;
448 : }
449 :
450 : /// @brief Compute the remaining time until LC completion
451 : SUMOTime remainingTime() const;
452 :
453 : /// @brief Calculates the maximal time needed to complete a lane change maneuver
454 : /// if lcMaxSpeedLatFactor and lcMaxSpeedStanding are set and the vehicle breaks not harder than decel.
455 : /// LC when the vehicle starts breaking now. If lcMaxSpeedStanding==0 the completion may be impossible,
456 : /// @param[in] speed Current longitudinal speed of the changing vehicle.
457 : /// @param[in] remainingManeuverDist dist which is still to be covered until LC is completed
458 : /// @param[in] decel Maximal assumed deceleration rate applied during the LC.
459 : /// @return maximal LC duration (or -1) if it is possible that it can't be completed.
460 : /// @note 1) For the calculation it is assumed that the vehicle starts breaking with decel (>=0) immediately.
461 : /// If lcMaxSpeedStanding==0 the completion may be impossible, and -1 is returned.
462 : /// 2) In case that no maxSpeedLat is used to control lane changing, this is only called prior to a lane change,
463 : /// and the duration is MSGlobals::gLaneChangeDuration.
464 : virtual double estimateLCDuration(const double speed, const double remainingManeuverDist, const double decel, bool urgent) const;
465 :
466 : /// @brief return true if the vehicle currently performs a lane change maneuver
467 : inline bool isChangingLanes() const {
468 3867834511 : return myLaneChangeCompletion < (1 - NUMERICAL_EPS);
469 : }
470 :
471 : /// @brief Get the current lane change completion ratio
472 : inline double getLaneChangeCompletion() const {
473 190992 : return myLaneChangeCompletion;
474 : }
475 :
476 : /// @brief return the direction of the current lane change maneuver
477 : inline int getLaneChangeDirection() const {
478 827620 : return myLaneChangeDirection;
479 : }
480 :
481 : /// @brief return the direction in which the current shadow lane lies
482 : int getShadowDirection() const;
483 :
484 : /// @brief return the angle offset during a continuous change maneuver
485 : double calcAngleOffset();
486 :
487 : /// @brief return the angle offset resulting from lane change and sigma
488 : inline double getAngleOffset() const {
489 671112891 : return myAngleOffset;
490 : }
491 :
492 : /// @brief set the angle offset resulting from lane change and sigma
493 : inline void setAngleOffset(const double angleOffset) {
494 : myAngleOffset = angleOffset;
495 : }
496 :
497 : /// @brief set the angle offset of the previous time step
498 : inline void setPreviousAngleOffset(const double angleOffset) {
499 671112891 : myPreviousAngleOffset = angleOffset;
500 : }
501 :
502 : /// @brief reset the flag whether a vehicle already moved to false
503 : inline bool alreadyChanged() const {
504 353972341 : return myAlreadyChanged;
505 : }
506 :
507 : /// @brief reset the flag whether a vehicle already moved to false
508 : void resetChanged() {
509 603822217 : myAlreadyChanged = false;
510 603822217 : }
511 :
512 : /// @brief start the lane change maneuver and return whether it continues
513 : bool startLaneChangeManeuver(MSLane* source, MSLane* target, int direction);
514 :
515 : /// @brief Control for resetting the memorized values for LC relevant gaps until the LC output is triggered in the case of continuous LC.
516 : void memorizeGapsAtLCInit();
517 : void clearGapsAtLCInit();
518 :
519 : /* @brief continue the lane change maneuver and return whether the midpoint
520 : * was passed in this step
521 : */
522 : bool updateCompletion();
523 :
524 : /* @brief update lane change shadow after the vehicle moved to a new lane */
525 : void updateShadowLane();
526 :
527 : /* @brief update lane change reservations after the vehicle moved to a new lane
528 : * @note The shadow lane should always be updated before updating the target lane. */
529 : MSLane* updateTargetLane();
530 :
531 : /* @brief Determines the lane which the vehicle intends to enter during its current action step.
532 : * targetDir is set to the offset of the returned lane with respect to the vehicle'a current lane. */
533 : MSLane* determineTargetLane(int& targetDir) const;
534 :
535 : /* @brief finish the lane change maneuver
536 : */
537 : void endLaneChangeManeuver(const MSMoveReminder::Notification reason = MSMoveReminder::NOTIFICATION_LANE_CHANGE);
538 :
539 : /* @brief clean up all references to the shadow vehicle
540 : */
541 : void cleanupShadowLane();
542 :
543 : /* @brief clean up all references to the vehicle on its target lanes
544 : */
545 : void cleanupTargetLane();
546 :
547 : /// @brief reserve space at the end of the lane to avoid dead locks
548 0 : virtual bool saveBlockerLength(double /* length */, double /* foeLeftSpace */) {
549 0 : return true;
550 : }
551 :
552 : void setShadowPartialOccupator(MSLane* lane) {
553 : myPartiallyOccupatedByShadow.push_back(lane);
554 : }
555 :
556 : void setNoShadowPartialOccupator(MSLane* lane) {
557 0 : myNoPartiallyOccupatedByShadow.push_back(lane);
558 : }
559 :
560 : /// @brief called once when the vehicles primary lane changes
561 : void primaryLaneChanged(MSLane* source, MSLane* target, int direction);
562 :
563 : /// @brief called once the vehicle ends a lane change manoeuvre (non-instant)
564 : void laneChangeOutput(const std::string& tag, MSLane* source, MSLane* target, int direction, double maneuverDist = 0);
565 :
566 : /// @brief whether the current change completes the manoeuvre
567 0 : virtual bool sublaneChangeCompleted(const double latDist) const {
568 : UNUSED_PARAMETER(latDist);
569 0 : throw ProcessError("Method not implemented by model " + toString(myModel));
570 : }
571 :
572 : /// @brief set approach information for the shadow vehicle
573 : void setShadowApproachingInformation(MSLink* link) const;
574 : void removeShadowApproachingInformation() const;
575 :
576 : bool isOpposite() const {
577 44997835867 : return myAmOpposite;
578 : }
579 :
580 : /// brief return lane index that treats opposite lanes like normal lanes to the left of the forward lanes
581 : int getNormalizedLaneIndex();
582 :
583 : double getCommittedSpeed() const {
584 10154261 : return myCommittedSpeed;
585 : }
586 :
587 : /// @brief return the lateral speed of the current lane change maneuver
588 0 : double getSpeedLat() const {
589 527699126 : return mySpeedLat;
590 : }
591 :
592 : /* @brief reset the angle (in case no lane changing happens in this step
593 : * and the maneuver was finished in the previous step) */
594 : virtual void resetSpeedLat();
595 :
596 : /// @brief return the lateral speed of the current lane change maneuver
597 : double getAccelerationLat() const {
598 55339 : return myAccelerationLat;
599 : }
600 :
601 : double getStrategicLookahead() const {
602 15051862 : return myStrategicLookahead;
603 : }
604 :
605 : /// @brief set the lateral speed and update lateral acceleraton
606 : void setSpeedLat(double speedLat);
607 :
608 : /// @brief decides the next lateral speed depending on the remaining lane change distance to be covered
609 : /// and updates maneuverDist according to lateral safety constraints.
610 : virtual double computeSpeedLat(double latDist, double& maneuverDist, bool urgent) const;
611 :
612 : /// @brief Returns a deceleration value which is used for the estimation of the duration of a lane change.
613 : /// @note Effective only for continuous lane-changing when using attributes myMaxSpeedLatFactor and myMaxSpeedLatStanding. See #3771
614 : virtual double getAssumedDecelForLaneChangeDuration() const;
615 :
616 : /// @brief try to retrieve the given parameter from this laneChangeModel. Throw exception for unsupported key
617 0 : virtual std::string getParameter(const std::string& key) const {
618 0 : throw InvalidArgument("Parameter '" + key + "' is not supported for laneChangeModel of type '" + toString(myModel) + "'");
619 : }
620 :
621 : /// @brief try to set the given parameter for this laneChangeModel. Throw exception for unsupported key
622 0 : virtual void setParameter(const std::string& key, const std::string& value) {
623 : UNUSED_PARAMETER(value);
624 0 : throw InvalidArgument("Setting parameter '" + key + "' is not supported for laneChangeModel of type '" + toString(myModel) + "'");
625 : }
626 :
627 : /* @brief reserve extra space for unseen blockers when more than one lane change is required
628 : * @param[in] bestLaneOffset The offset to the best lane
629 : * @param[in] neighExtraDist the additional distance that can be driven on the neighboring lane (after a single lane change)
630 : */
631 : virtual double getExtraReservation(int bestLaneOffset, double neighExtraDist = 0) const;
632 :
633 : /// @brief Check for commands issued for the vehicle via TraCI and apply the appropriate state changes
634 : /// For the sublane case, this includes setting a new maneuver distance if appropriate.
635 : void checkTraCICommands();
636 :
637 : /// @brief get vehicle position relative to the forward direction lane
638 : double getForwardPos() const;
639 :
640 : bool hasBlueLight() const {
641 452024496 : return myHaveBlueLight;
642 : }
643 :
644 0 : virtual LatAlignmentDefinition getDesiredAlignment() const {
645 97111699 : return myVehicle.getVehicleType().getPreferredLateralAlignment();
646 : }
647 :
648 : /// @brief return speed for helping a vehicle that is blocked from changing
649 : double getCooperativeHelpSpeed(const MSLane* lane, double distToLaneEnd) const;
650 :
651 : static const double NO_NEIGHBOR;
652 : static const double UNDEFINED_LOOKAHEAD;
653 :
654 : protected:
655 : virtual bool congested(const MSVehicle* const neighLeader);
656 :
657 : virtual bool predInteraction(const std::pair<MSVehicle*, double>& leader);
658 :
659 : virtual bool avoidOvertakeRight() const;
660 :
661 : /// @brief whether the influencer cancels the given request
662 : bool cancelRequest(int state, int laneOffset);
663 :
664 : /// @brief return the max of maxSpeedLat and lcMaxSpeedLatStanding
665 : double getMaxSpeedLat2() const;
666 :
667 : /** @brief Takes a vSafe (speed advice for speed in the next simulation step), converts it into an acceleration
668 : * and stores it into myLCAccelerationAdvices.
669 : * @note This construction was introduced to deal with action step lengths,
670 : * where operation on the speed in the next sim step had to be replaced by acceleration
671 : * throughout the next action step.
672 : */
673 : void addLCSpeedAdvice(const double vSafe, bool ownAdvice = true);
674 :
675 :
676 : protected:
677 : /// @brief The vehicle this lane-changer belongs to
678 : MSVehicle& myVehicle;
679 :
680 : /// @brief The current state of the vehicle
681 : int myOwnState;
682 : /// @brief lane changing state from the previous simulation step
683 : int myPreviousState;
684 : /// @brief lane changing state from step before the previous simulation step
685 : int myPreviousState2;
686 :
687 : std::pair<int, int> mySavedStateRight;
688 : std::pair<int, int> mySavedStateCenter;
689 : std::pair<int, int> mySavedStateLeft;
690 : int myCanceledStateRight;
691 : int myCanceledStateCenter;
692 : int myCanceledStateLeft;
693 :
694 : /// @brief Cached info on lc-relevant neighboring vehicles
695 : /// @{
696 : std::shared_ptr<MSLeaderDistanceInfo> myLeftFollowers;
697 : std::shared_ptr<MSLeaderDistanceInfo> myLeftLeaders;
698 : std::shared_ptr<MSLeaderDistanceInfo> myRightFollowers;
699 : std::shared_ptr<MSLeaderDistanceInfo> myRightLeaders;
700 : /// @}
701 :
702 : /// @brief the current lateral speed
703 : double mySpeedLat;
704 :
705 : /// @brief the current lateral acceleration
706 : double myAccelerationLat;
707 :
708 : /// @brief the current angle offset resulting from lane change and sigma
709 : double myAngleOffset;
710 :
711 : /// @brief the angle offset of the previous time step resulting from lane change and sigma
712 : double myPreviousAngleOffset;
713 :
714 : /// @brief the speed when committing to a change maneuver
715 : double myCommittedSpeed;
716 :
717 : /// @brief progress of the lane change maneuver 0:started, 1:complete
718 : double myLaneChangeCompletion;
719 :
720 : /// @brief direction of the lane change maneuver -1 means right, 1 means left
721 : int myLaneChangeDirection;
722 :
723 : /// @brief whether the vehicle has already moved this step
724 : bool myAlreadyChanged;
725 :
726 : /// @brief A lane that is partially occupied by the front of the vehicle but that is not the primary lane
727 : MSLane* myShadowLane;
728 : /* @brief Lanes that are partially (laterally) occupied by the back of the
729 : * vehicle (analogue to MSVehicle::myFurtherLanes) */
730 : std::vector<MSLane*> myShadowFurtherLanes;
731 : std::vector<double> myShadowFurtherLanesPosLat;
732 :
733 :
734 : /// @brief The target lane for the vehicle's current maneuver
735 : /// @note This is used by the sublane model to register the vehicle at lanes,
736 : /// it will reach within the current action step, so vehicles on that lane
737 : /// may react to the started lc-maneuver during the car-following process.
738 : /// If the shadow lane is the same as the lc maneuver target, myTargetLane is
739 : /// set to nullptr.
740 : /// The current shadow lanes and further lanes should always be updated before updating the target lane.
741 : MSLane* myTargetLane;
742 :
743 : /* @brief Further upstream lanes that are affected by the vehicle's maneuver (analogue to MSVehicle::myFurtherLanes)
744 : * @note If myTargetLane==nullptr, we may assume myFurtherTargetLanes.size()==0, otherwise we have
745 : * myFurtherTargetLanes.size() == myVehicle.getFurtherLanes.size()
746 : * Here it may occur that an element myFurtherTargetLanes[i]==nullptr if myFurtherLanes[i] has
747 : * no parallel lane in the change direction.
748 : * */
749 : std::vector<MSLane*> myFurtherTargetLanes;
750 :
751 : /// @brief The vehicle's car following model
752 : inline const MSCFModel& getCarFollowModel() const {
753 617137440 : return myVehicle.getCarFollowModel();
754 : }
755 :
756 : /// @brief the type of this model
757 : const LaneChangeModel myModel;
758 :
759 : /// @brief list of lanes where the shadow vehicle is partial occupator
760 : std::vector<MSLane*> myPartiallyOccupatedByShadow;
761 :
762 : /* @brief list of lanes where there is no shadow vehicle partial occupator
763 : * (when changing to a lane that has no predecessor) */
764 : std::vector<MSLane*> myNoPartiallyOccupatedByShadow;
765 :
766 : /// @brief the minimum lateral gaps to other vehicles that were found when last changing to the left and right
767 : double myLastLateralGapLeft;
768 : double myLastLateralGapRight;
769 :
770 : /// @brief the actual minimum longitudinal distances to vehicles on the target lane
771 : double myLastLeaderGap;
772 : double myLastFollowerGap;
773 : /// @brief the minimum longitudinal distances to vehicles on the target lane that would be necessary for stringent security
774 : double myLastLeaderSecureGap;
775 : double myLastFollowerSecureGap;
776 : /// @brief acutal and secure distance to closest leader vehicle on the original when performing lane change
777 : double myLastOrigLeaderGap;
778 : double myLastOrigLeaderSecureGap;
779 : /// @brief speeds of surrounding vehicles at the time of lane change
780 : double myLastLeaderSpeed;
781 : double myLastFollowerSpeed;
782 : double myLastOrigLeaderSpeed;
783 :
784 : /// @brief Flag to prevent resetting the memorized values for LC relevant gaps until the LC output is triggered
785 : /// in the case of continuous LC.
786 : bool myDontResetLCGaps;
787 :
788 : double myStrategicLookahead;
789 : // @brief the maximum lateral speed for non-strategic changes when standing
790 : double myMaxSpeedLatStanding;
791 : // @brief the factor of maximum lateral speed to longitudinal speed for non-strategic changes
792 : double myMaxSpeedLatFactor;
793 : // @brief the maximum lateral maneuver distance when standing
794 : double myMaxDistLatStanding;
795 : // @brief factor for lane keeping imperfection
796 : double mySigma;
797 : // allow overtaking right even though it is prohibited
798 : double myOvertakeRightParam;
799 : // @brief willingness to undercut longitudinal safe gaps
800 : double myAssertive;
801 : // @brief brake for blocked vehicles enter after they have been waiting for the given time
802 : SUMOTime myCooperativeHelpTime;
803 :
804 : /// @brief whether this vehicle is driving with special permissions and behavior
805 : bool myHaveBlueLight;
806 :
807 : /* @brief to be called by derived classes in their changed() method.
808 : * If dir=0 is given, the current value remains unchanged */
809 : void initLastLaneChangeOffset(int dir);
810 :
811 : /* @brief vector of LC-related acceleration recommendations combined with a
812 : * boolean to indicate whether the advice is from ego or someone else.
813 : * Filled in wantsChange() and applied in patchSpeed() */
814 : std::vector<std::pair<double, bool> > myLCAccelerationAdvices;
815 :
816 : /// @brief whether overtaking on the right is permitted
817 : static bool myAllowOvertakingRight;
818 :
819 : /// @brief whether to record lane-changing
820 : static bool myLCOutput;
821 : static bool myLCStartedOutput;
822 : static bool myLCEndedOutput;
823 : static bool myLCXYOutput;
824 :
825 :
826 : private:
827 : /* @brief information how long ago the vehicle has performed a lane-change,
828 : * sign indicates direction of the last change
829 : */
830 : SUMOTime myLastLaneChangeOffset;
831 :
832 : /// @brief links which are approached by the shadow vehicle
833 : mutable std::vector<MSLink*> myApproachedByShadow;
834 :
835 : /// @brief whether the vehicle is driving in the opposite direction
836 : bool myAmOpposite;
837 :
838 : /// @brief The complete lateral distance the vehicle wants to travel to finish its maneuver
839 : /// Only used by sublane model, currently.
840 : double myManeuverDist;
841 :
842 : /// @brief Maneuver distance from the previous simulation step
843 : double myPreviousManeuverDist;
844 :
845 :
846 : private:
847 : /// @brief Invalidated assignment operator
848 : MSAbstractLaneChangeModel& operator=(const MSAbstractLaneChangeModel& s);
849 : };
|