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