Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2024 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 191115031 : : myLeader(leader), myNeighLeader(neighLead),
62 191115031 : myNeighFollower(neighFollow) { }
63 :
64 :
65 : /// @brief Destructor
66 191115031 : ~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 2059511 : void* informNeighLeader(void* info, MSVehicle* sender) {
86 : assert(myNeighLeader != 0);
87 2059511 : 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 1729607 : void* informNeighFollower(void* info, MSVehicle* sender) {
97 : assert(myNeighFollower != 0);
98 1729607 : 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 220573209 : StateAndDist(int _state, double _latDist, double _targetDist, int _dir) :
123 220573209 : state(_state),
124 220573209 : latDist(_latDist),
125 220573209 : maneuverDist(_targetDist),
126 220573209 : dir(_dir) {}
127 :
128 : bool sameDirection(const StateAndDist& other) const {
129 3850861 : 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 667689 : virtual int checkChangeBeforeCommitting(const MSVehicle* veh, int state) const {
156 : UNUSED_PARAMETER(veh);
157 : UNUSED_PARAMETER(state);
158 667689 : 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 5823924 : return myLCOutput;
174 : }
175 :
176 : /// @brief whether start of maneuvers shall be recorede
177 : static bool outputLCStarted() {
178 394832 : return myLCStartedOutput;
179 : }
180 :
181 : /// @brief whether start of maneuvers shall be recorede
182 : static bool outputLCEnded() {
183 135218 : 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 784533084 : return myOwnState;
197 : }
198 :
199 : inline int getPrevState() const {
200 : /// at the time of this call myPreviousState already holds the new value
201 74305555 : 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 16059 : if (dir == -1) {
217 5482 : return mySavedStateRight;
218 10577 : } else if (dir == 0) {
219 5095 : return mySavedStateCenter;
220 : } else {
221 5482 : return mySavedStateLeft;
222 : }
223 : }
224 :
225 : void saveLCState(const int dir, int stateWithoutTraCI, const int state) {
226 309490467 : int canceledStrategic = getCanceledState(dir);
227 : // avoid conflicting directions
228 300697785 : if ((canceledStrategic & LCA_WANTS_LANECHANGE_OR_STAY) != 0) {
229 : stateWithoutTraCI = canceledStrategic;
230 : }
231 : const auto pair = std::make_pair(stateWithoutTraCI, state);
232 296301444 : if (dir == -1) {
233 : mySavedStateRight = pair;
234 191036149 : } 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 697796168 : if (dir == -1) {
260 254461274 : return myCanceledStateRight;
261 443334894 : } else if (dir == 0) {
262 153940840 : return myCanceledStateCenter;
263 : } else {
264 289394054 : 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 310309703 : if (myLastLaneChangeOffset > 0) {
402 49670920 : myLastLaneChangeOffset += DELTA_T;
403 260638783 : } else if (myLastLaneChangeOffset < 0) {
404 34968825 : 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 10286878402 : 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 3884054207 : return myTargetLane;
434 : }
435 :
436 : const std::vector<MSLane*>& getFurtherTargetLanes() const {
437 0 : return myFurtherTargetLanes;
438 : }
439 :
440 : inline SUMOTime getLastLaneChangeOffset() const {
441 24762 : 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 565862 : 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 3583346421 : return myLaneChangeCompletion < (1 - NUMERICAL_EPS);
469 : }
470 :
471 : /// @brief Get the current lane change completion ratio
472 : inline double getLaneChangeCompletion() const {
473 187910 : return myLaneChangeCompletion;
474 : }
475 :
476 : /// @brief return the direction of the current lane change maneuver
477 : inline int getLaneChangeDirection() const {
478 808532 : 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 620489452 : 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 620489452 : myPreviousAngleOffset = angleOffset;
500 : }
501 :
502 : /// @brief reset the flag whether a vehicle already moved to false
503 : inline bool alreadyChanged() const {
504 311695717 : return myAlreadyChanged;
505 : }
506 :
507 : /// @brief reset the flag whether a vehicle already moved to false
508 : void resetChanged() {
509 551248047 : myAlreadyChanged = false;
510 551248047 : }
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 39823431342 : 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 7522288 : return myCommittedSpeed;
585 : }
586 :
587 : /// @brief return the lateral speed of the current lane change maneuver
588 0 : double getSpeedLat() const {
589 542274393 : 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 54588 : return myAccelerationLat;
599 : }
600 :
601 : double getStrategicLookahead() const {
602 14413021 : 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 : /// reserve extra space for unseen blockers when more tnan one lane change is required
628 8 : virtual double getExtraReservation(int /*bestLaneOffset*/) const {
629 8 : return 0;
630 : }
631 :
632 : /// @brief Check for commands issued for the vehicle via TraCI and apply the appropriate state changes
633 : /// For the sublane case, this includes setting a new maneuver distance if appropriate.
634 : void checkTraCICommands();
635 :
636 : /// @brief get vehicle position relative to the forward direction lane
637 : double getForwardPos() const;
638 :
639 : bool hasBlueLight() const {
640 108101737 : return myHaveBlueLight;
641 : }
642 :
643 0 : virtual LatAlignmentDefinition getDesiredAlignment() const {
644 89324593 : return myVehicle.getVehicleType().getPreferredLateralAlignment();
645 : }
646 :
647 : static const double NO_NEIGHBOR;
648 : static const double UNDEFINED_LOOKAHEAD;
649 :
650 : protected:
651 : virtual bool congested(const MSVehicle* const neighLeader);
652 :
653 : virtual bool predInteraction(const std::pair<MSVehicle*, double>& leader);
654 :
655 : virtual bool avoidOvertakeRight() const;
656 :
657 : /// @brief whether the influencer cancels the given request
658 : bool cancelRequest(int state, int laneOffset);
659 :
660 : /// @brief return the max of maxSpeedLat and lcMaxSpeedLatStanding
661 : double getMaxSpeedLat2() const;
662 :
663 : /** @brief Takes a vSafe (speed advice for speed in the next simulation step), converts it into an acceleration
664 : * and stores it into myLCAccelerationAdvices.
665 : * @note This construction was introduced to deal with action step lengths,
666 : * where operation on the speed in the next sim step had to be replaced by acceleration
667 : * throughout the next action step.
668 : */
669 : void addLCSpeedAdvice(const double vSafe, bool ownAdvice = true);
670 :
671 :
672 : protected:
673 : /// @brief The vehicle this lane-changer belongs to
674 : MSVehicle& myVehicle;
675 :
676 : /// @brief The current state of the vehicle
677 : int myOwnState;
678 : /// @brief lane changing state from the previous simulation step
679 : int myPreviousState;
680 : /// @brief lane changing state from step before the previous simulation step
681 : int myPreviousState2;
682 :
683 : std::pair<int, int> mySavedStateRight;
684 : std::pair<int, int> mySavedStateCenter;
685 : std::pair<int, int> mySavedStateLeft;
686 : int myCanceledStateRight;
687 : int myCanceledStateCenter;
688 : int myCanceledStateLeft;
689 :
690 : /// @brief Cached info on lc-relevant neighboring vehicles
691 : /// @{
692 : std::shared_ptr<MSLeaderDistanceInfo> myLeftFollowers;
693 : std::shared_ptr<MSLeaderDistanceInfo> myLeftLeaders;
694 : std::shared_ptr<MSLeaderDistanceInfo> myRightFollowers;
695 : std::shared_ptr<MSLeaderDistanceInfo> myRightLeaders;
696 : /// @}
697 :
698 : /// @brief the current lateral speed
699 : double mySpeedLat;
700 :
701 : /// @brief the current lateral acceleration
702 : double myAccelerationLat;
703 :
704 : /// @brief the current angle offset resulting from lane change and sigma
705 : double myAngleOffset;
706 :
707 : /// @brief the angle offset of the previous time step resulting from lane change and sigma
708 : double myPreviousAngleOffset;
709 :
710 : /// @brief the speed when committing to a change maneuver
711 : double myCommittedSpeed;
712 :
713 : /// @brief progress of the lane change maneuver 0:started, 1:complete
714 : double myLaneChangeCompletion;
715 :
716 : /// @brief direction of the lane change maneuver -1 means right, 1 means left
717 : int myLaneChangeDirection;
718 :
719 : /// @brief whether the vehicle has already moved this step
720 : bool myAlreadyChanged;
721 :
722 : /// @brief A lane that is partially occupied by the front of the vehicle but that is not the primary lane
723 : MSLane* myShadowLane;
724 : /* @brief Lanes that are partially (laterally) occupied by the back of the
725 : * vehicle (analogue to MSVehicle::myFurtherLanes) */
726 : std::vector<MSLane*> myShadowFurtherLanes;
727 : std::vector<double> myShadowFurtherLanesPosLat;
728 :
729 :
730 : /// @brief The target lane for the vehicle's current maneuver
731 : /// @note This is used by the sublane model to register the vehicle at lanes,
732 : /// it will reach within the current action step, so vehicles on that lane
733 : /// may react to the started lc-maneuver during the car-following process.
734 : /// If the shadow lane is the same as the lc maneuver target, myTargetLane is
735 : /// set to nullptr.
736 : /// The current shadow lanes and further lanes should always be updated before updating the target lane.
737 : MSLane* myTargetLane;
738 :
739 : /* @brief Further upstream lanes that are affected by the vehicle's maneuver (analogue to MSVehicle::myFurtherLanes)
740 : * @note If myTargetLane==nullptr, we may assume myFurtherTargetLanes.size()==0, otherwise we have
741 : * myFurtherTargetLanes.size() == myVehicle.getFurtherLanes.size()
742 : * Here it may occur that an element myFurtherTargetLanes[i]==nullptr if myFurtherLanes[i] has
743 : * no parallel lane in the change direction.
744 : * */
745 : std::vector<MSLane*> myFurtherTargetLanes;
746 :
747 : /// @brief The vehicle's car following model
748 : inline const MSCFModel& getCarFollowModel() const {
749 558933937 : return myVehicle.getCarFollowModel();
750 : }
751 :
752 : /// @brief the type of this model
753 : const LaneChangeModel myModel;
754 :
755 : /// @brief list of lanes where the shadow vehicle is partial occupator
756 : std::vector<MSLane*> myPartiallyOccupatedByShadow;
757 :
758 : /* @brief list of lanes where there is no shadow vehicle partial occupator
759 : * (when changing to a lane that has no predecessor) */
760 : std::vector<MSLane*> myNoPartiallyOccupatedByShadow;
761 :
762 : /// @brief the minimum lateral gaps to other vehicles that were found when last changing to the left and right
763 : double myLastLateralGapLeft;
764 : double myLastLateralGapRight;
765 :
766 : /// @brief the actual minimum longitudinal distances to vehicles on the target lane
767 : double myLastLeaderGap;
768 : double myLastFollowerGap;
769 : /// @brief the minimum longitudinal distances to vehicles on the target lane that would be necessary for stringent security
770 : double myLastLeaderSecureGap;
771 : double myLastFollowerSecureGap;
772 : /// @brief acutal and secure distance to closest leader vehicle on the original when performing lane change
773 : double myLastOrigLeaderGap;
774 : double myLastOrigLeaderSecureGap;
775 : /// @brief speeds of surrounding vehicles at the time of lane change
776 : double myLastLeaderSpeed;
777 : double myLastFollowerSpeed;
778 : double myLastOrigLeaderSpeed;
779 :
780 : /// @brief Flag to prevent resetting the memorized values for LC relevant gaps until the LC output is triggered
781 : /// in the case of continuous LC.
782 : bool myDontResetLCGaps;
783 :
784 : double myStrategicLookahead;
785 : // @brief the maximum lateral speed for non-strategic changes when standing
786 : double myMaxSpeedLatStanding;
787 : // @brief the factor of maximum lateral speed to longitudinal speed for non-strategic changes
788 : double myMaxSpeedLatFactor;
789 : // @brief the maximum lateral maneuver distance when standing
790 : double myMaxDistLatStanding;
791 : // @brief factor for lane keeping imperfection
792 : double mySigma;
793 : // allow overtaking right even though it is prohibited
794 : double myOvertakeRightParam;
795 :
796 : /// @brief whether this vehicle is driving with special permissions and behavior
797 : bool myHaveBlueLight;
798 :
799 : /* @brief to be called by derived classes in their changed() method.
800 : * If dir=0 is given, the current value remains unchanged */
801 : void initLastLaneChangeOffset(int dir);
802 :
803 : /* @brief vector of LC-related acceleration recommendations combined with a
804 : * boolean to indicate whether the advice is from ego or someone else.
805 : * Filled in wantsChange() and applied in patchSpeed() */
806 : std::vector<std::pair<double, bool> > myLCAccelerationAdvices;
807 :
808 : /// @brief whether overtaking on the right is permitted
809 : static bool myAllowOvertakingRight;
810 :
811 : /// @brief whether to record lane-changing
812 : static bool myLCOutput;
813 : static bool myLCStartedOutput;
814 : static bool myLCEndedOutput;
815 : static bool myLCXYOutput;
816 :
817 :
818 : private:
819 : /* @brief information how long ago the vehicle has performed a lane-change,
820 : * sign indicates direction of the last change
821 : */
822 : SUMOTime myLastLaneChangeOffset;
823 :
824 : /// @brief links which are approached by the shadow vehicle
825 : mutable std::vector<MSLink*> myApproachedByShadow;
826 :
827 : /// @brief whether the vehicle is driving in the opposite direction
828 : bool myAmOpposite;
829 :
830 : /// @brief The complete lateral distance the vehicle wants to travel to finish its maneuver
831 : /// Only used by sublane model, currently.
832 : double myManeuverDist;
833 :
834 : /// @brief Maneuver distance from the previous simulation step
835 : double myPreviousManeuverDist;
836 :
837 :
838 : private:
839 : /// @brief Invalidated assignment operator
840 : MSAbstractLaneChangeModel& operator=(const MSAbstractLaneChangeModel& s);
841 : };
|