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