Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSAbstractLaneChangeModel.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
23// Interface for lane-change models
24/****************************************************************************/
25
26// ===========================================================================
27// DEBUG
28// ===========================================================================
29//#define DEBUG_TARGET_LANE
30//#define DEBUG_SHADOWLANE
31//#define DEBUG_OPPOSITE
32//#define DEBUG_MANEUVER
33#define DEBUG_COND (myVehicle.isSelected())
34
35#include <config.h>
36
40#include <microsim/MSNet.h>
41#include <microsim/MSEdge.h>
42#include <microsim/MSLane.h>
43#include <microsim/MSLink.h>
44#include <microsim/MSStop.h>
46#include <microsim/MSGlobals.h>
48#include "MSLCM_DK2008.h"
49#include "MSLCM_LC2013.h"
50#include "MSLCM_LC2013_CC.h"
51#include "MSLCM_SL2015.h"
53
54/* -------------------------------------------------------------------------
55 * static members
56 * ----------------------------------------------------------------------- */
62const double MSAbstractLaneChangeModel::NO_NEIGHBOR(std::numeric_limits<double>::max());
64
65#define LC_ASSUMED_DECEL 1.0 // the minimal constant deceleration assumed to estimate the duration of a continuous lane-change at its initiation.
66
67/* -------------------------------------------------------------------------
68 * MSAbstractLaneChangeModel-methods
69 * ----------------------------------------------------------------------- */
70
71void
73 myAllowOvertakingRight = oc.getBool("lanechange.overtake-right");
74 myLCOutput = oc.isSet("lanechange-output");
75 myLCStartedOutput = oc.getBool("lanechange-output.started");
76 myLCEndedOutput = oc.getBool("lanechange-output.ended");
77 myLCXYOutput = oc.getBool("lanechange-output.xy");
78}
79
80
84 throw ProcessError(TLF("Lane change model '%' is not compatible with sublane simulation", toString(lcm)));
85 }
86 switch (lcm) {
88 return new MSLCM_DK2008(v);
90 return new MSLCM_LC2013(v);
92 return new MSLCM_LC2013_CC(v);
94 return new MSLCM_SL2015(v);
97 return new MSLCM_LC2013(v);
98 } else {
99 return new MSLCM_SL2015(v);
100 }
101 default:
102 throw ProcessError(TLF("Lane change model '%' not implemented", toString(lcm)));
103 }
104}
105
106
108 myVehicle(v),
109 myOwnState(0),
110 myPreviousState(0),
111 myPreviousState2(0),
112 myCanceledStateRight(LCA_NONE),
113 myCanceledStateCenter(LCA_NONE),
114 myCanceledStateLeft(LCA_NONE),
115 mySpeedLat(0),
116 myAccelerationLat(0),
117 myAngleOffset(0),
118 myPreviousAngleOffset(0),
119 myCommittedSpeed(0),
120 myLaneChangeCompletion(1.0),
121 myLaneChangeDirection(0),
122 myAlreadyChanged(false),
123 myShadowLane(nullptr),
124 myTargetLane(nullptr),
125 myModel(model),
126 myLastLateralGapLeft(0.),
127 myLastLateralGapRight(0.),
128 myLastLeaderGap(0.),
129 myLastFollowerGap(0.),
130 myLastLeaderSecureGap(0.),
131 myLastFollowerSecureGap(0.),
132 myLastOrigLeaderGap(0.),
133 myLastOrigLeaderSecureGap(0.),
134 myLastLeaderSpeed(0),
135 myLastFollowerSpeed(0),
136 myLastOrigLeaderSpeed(0),
137 myDontResetLCGaps(false),
138 myStrategicLookahead(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_STRATEGIC_LOOKAHEAD, UNDEFINED_LOOKAHEAD)),
139 myMaxSpeedLatStanding(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING, v.getVehicleType().getMaxSpeedLat())),
140 myMaxSpeedLatFactor(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR, 1)),
141 myMaxDistLatStanding(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXDISTLATSTANDING,
142 // prevent lateral sliding for cars but permit for two-wheelers due to better maneuverability
143 (v.getVClass() & (SVC_BICYCLE | SVC_MOTORCYCLE | SVC_MOPED)) != 0 ? std::numeric_limits<double>::max() : 1.6)),
144 mySigma(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SIGMA, 0.0)),
145 myOvertakeRightParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_OVERTAKE_RIGHT, 0)),
146 myAssertive(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_ASSERTIVE, 1)),
147 myCooperativeHelpTime(TIME2STEPS(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_COOPERATIVE_HELPTIME, 60))),
148 myHaveBlueLight(v.getDevice(typeid(MSDevice_Bluelight)) != nullptr), // see MSVehicle::initDevices
149 myLastLaneChangeOffset(0),
150 myAmOpposite(false),
151 myManeuverDist(0.),
152 myPreviousManeuverDist(0.) {
156}
157
158
161
162void
165 myOwnState = state;
166 myPreviousState = state; // myOwnState is modified in prepareStep so we make a backup
167}
168
169void
170MSAbstractLaneChangeModel::updateSafeLatDist(const double travelledLatDist) {
171 UNUSED_PARAMETER(travelledLatDist);
172}
173
174
175void
177#ifdef DEBUG_MANEUVER
178 if (DEBUG_COND) {
179 std::cout << SIMTIME
180 << " veh=" << myVehicle.getID()
181 << " setManeuverDist() old=" << myManeuverDist << " new=" << dist
182 << std::endl;
183 }
184#endif
185 myManeuverDist = fabs(dist) < NUMERICAL_EPS ? 0. : dist;
186 // store value which may be modified by the model during the next step
188}
189
190
191double
195
196double
200
201void
203 if (dir == -1) {
204 myLeftFollowers = std::make_shared<MSLeaderDistanceInfo>(followers);
205 myLeftLeaders = std::make_shared<MSLeaderDistanceInfo>(leaders);
206 } else if (dir == 1) {
207 myRightFollowers = std::make_shared<MSLeaderDistanceInfo>(followers);
208 myRightLeaders = std::make_shared<MSLeaderDistanceInfo>(leaders);
209 } else {
210 // dir \in {-1,1} !
211 assert(false);
212 }
213}
214
215
216void
217MSAbstractLaneChangeModel::saveNeighbors(const int dir, const std::pair<MSVehicle* const, double>& follower, const std::pair<MSVehicle* const, double>& leader) {
218 if (dir == -1) {
219 myLeftFollowers = std::make_shared<MSLeaderDistanceInfo>(follower, myVehicle.getLane()->getWidth());
220 myLeftLeaders = std::make_shared<MSLeaderDistanceInfo>(leader, myVehicle.getLane()->getWidth());
221 } else if (dir == 1) {
222 myRightFollowers = std::make_shared<MSLeaderDistanceInfo>(follower, myVehicle.getLane()->getWidth());
223 myRightLeaders = std::make_shared<MSLeaderDistanceInfo>(leader, myVehicle.getLane()->getWidth());
224 } else {
225 // dir \in {-1,1} !
226 assert(false);
227 }
228}
229
230
231void
233 myLeftFollowers = nullptr;
234 myLeftLeaders = nullptr;
235 myRightFollowers = nullptr;
236 myRightLeaders = nullptr;
237}
238
239
240const std::shared_ptr<MSLeaderDistanceInfo>
242 if (dir == -1) {
243 return myLeftFollowers;
244 } else if (dir == 1) {
245 return myRightFollowers;
246 } else {
247 // dir \in {-1,1} !
248 assert(false);
249 }
250 return nullptr;
251}
252
253const std::shared_ptr<MSLeaderDistanceInfo>
255 if (dir == -1) {
256 return myLeftLeaders;
257 } else if (dir == 1) {
258 return myRightLeaders;
259 } else {
260 // dir \in {-1,1} !
261 assert(false);
262 }
263 return nullptr;
264}
265
266
267bool
269 if (neighLeader == nullptr) {
270 return false;
271 }
272 // Congested situation are relevant only on highways (maxSpeed > 70km/h)
273 // and congested on German Highways means that the vehicles have speeds
274 // below 60km/h. Overtaking on the right is allowed then.
275 if ((myVehicle.getLane()->getSpeedLimit() <= 70.0 / 3.6) || (neighLeader->getLane()->getSpeedLimit() <= 70.0 / 3.6)) {
276
277 return false;
278 }
279 if (myVehicle.congested() && neighLeader->congested()) {
280 return true;
281 }
282 return false;
283}
284
285
286bool
293
294bool
295MSAbstractLaneChangeModel::predInteraction(const std::pair<MSVehicle*, double>& leader) {
296 if (leader.first == 0) {
297 return false;
298 }
299 // let's check it on highways only
300 if (leader.first->getSpeed() < (80.0 / 3.6)) {
301 return false;
302 }
303 return leader.second < getCarFollowModel().interactionGap(&myVehicle, leader.first->getSpeed());
304}
305
306
307bool
311 myLaneChangeDirection = direction;
312 setManeuverDist((target->getWidth() + source->getWidth()) * 0.5 * direction);
315 if (myLCOutput) {
317 }
318 return true;
319 } else {
320 primaryLaneChanged(source, target, direction);
321 return false;
322 }
323}
324
325void
329
330void
334
335void
337 initLastLaneChangeOffset(direction);
339 source->leftByLaneChange(&myVehicle);
340 laneChangeOutput("change", source, target, direction); // record position on the source edge in case of opposite change
341 if (&source->getEdge() != &target->getEdge()) {
343#ifdef DEBUG_OPPOSITE
344 if (debugVehicle()) {
345 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " primaryLaneChanged source=" << source->getID() << " target=" << target->getID() << " nowOpposite=" << myAmOpposite << "\n";
346 }
347#endif
350 } else if (myAmOpposite) {
351#ifdef DEBUG_OPPOSITE
352 if (debugVehicle()) {
353 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " primaryLaneChanged source=" << source->getID() << " target=" << target->getID() << " stayOpposite\n";
354 }
355#endif
356 myAlreadyChanged = true;
358 if (!MSGlobals::gSublane) {
359 // in the continous case, the vehicle is added to the target lane via MSLaneChanger::continueChange / registerHop
360 // in the sublane case, the vehicle is added to the target lane via MSLaneChangerSublane::checkChangeOppositeSublane / MSLane::myTmpVehicles
362 }
363 } else {
366 }
367 // Assure that the drive items are up to date (even if the following step is no actionstep for the vehicle).
368 // This is necessary because the lane advance uses the target lane from the corresponding drive item.
370 changed();
371}
372
373void
374MSAbstractLaneChangeModel::laneChangeOutput(const std::string& tag, MSLane* source, MSLane* target, int direction, double maneuverDist) {
375 if (myLCOutput) {
376 OutputDevice& of = OutputDevice::getDeviceByOption("lanechange-output");
377 of.openTag(tag);
380 of.writeAttr(SUMO_ATTR_TIME, time2string(MSNet::getInstance()->getCurrentTimeStep()));
381 of.writeAttr(SUMO_ATTR_FROM, source->getID());
382 of.writeAttr(SUMO_ATTR_TO, target->getID());
383 of.writeAttr(SUMO_ATTR_DIR, direction);
391 of.writeAttr("leaderGap", myLastLeaderGap == NO_NEIGHBOR ? "None" : toString(myLastLeaderGap));
392 of.writeAttr("leaderSecureGap", myLastLeaderSecureGap == NO_NEIGHBOR ? "None" : toString(myLastLeaderSecureGap));
393 of.writeAttr("leaderSpeed", myLastLeaderSpeed == NO_NEIGHBOR ? "None" : toString(myLastLeaderSpeed));
394 of.writeAttr("followerGap", myLastFollowerGap == NO_NEIGHBOR ? "None" : toString(myLastFollowerGap));
395 of.writeAttr("followerSecureGap", myLastFollowerSecureGap == NO_NEIGHBOR ? "None" : toString(myLastFollowerSecureGap));
396 of.writeAttr("followerSpeed", myLastFollowerSpeed == NO_NEIGHBOR ? "None" : toString(myLastFollowerSpeed));
397 of.writeAttr("origLeaderGap", myLastOrigLeaderGap == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderGap));
398 of.writeAttr("origLeaderSecureGap", myLastOrigLeaderSecureGap == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderSecureGap));
399 of.writeAttr("origLeaderSpeed", myLastOrigLeaderSpeed == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderSpeed));
401 const double latGap = direction < 0 ? myLastLateralGapRight : myLastLateralGapLeft;
402 of.writeAttr("latGap", latGap == NO_NEIGHBOR ? "None" : toString(latGap));
403 if (maneuverDist != 0) {
404 of.writeAttr("maneuverDistance", toString(maneuverDist));
405 }
406 }
407 if (myLCXYOutput) {
410 }
411 of.closeTag();
414 }
415 }
416}
417
418
419double
420MSAbstractLaneChangeModel::computeSpeedLat(double /*latDist*/, double& maneuverDist, bool /*urgent*/) const {
422 int stepsToChange = (int)ceil(fabs(maneuverDist) / SPEED2DIST(myVehicle.getVehicleType().getMaxSpeedLat()));
423 return DIST2SPEED(maneuverDist / stepsToChange);
424 } else {
425 return maneuverDist / STEPS2TIME(MSGlobals::gLaneChangeDuration);
426 }
427}
428
429
430double
434
435void
438 mySpeedLat = speedLat;
439}
440
441
442void
448
449
450bool
452 const bool pastBefore = pastMidpoint();
453 // maneuverDist is not updated in the context of continuous lane changing but represents the full LC distance
454 double maneuverDist = getManeuverDist();
455 setSpeedLat(computeSpeedLat(0, maneuverDist, (myOwnState & LCA_URGENT) != 0));
457 return !pastBefore && pastMidpoint();
458}
459
460
461void
463 UNUSED_PARAMETER(reason);
472 // opposite driving continues after parking
473 } else {
474 // aborted maneuver
475#ifdef DEBUG_OPPOSITE
476 if (debugVehicle()) {
477 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " aborted maneuver (no longer opposite)\n";
478 }
479#endif
481 }
482 }
483}
484
485
486MSLane*
487MSAbstractLaneChangeModel::getShadowLane(const MSLane* lane, double posLat) const {
489 // initialize shadow lane
490 const double overlap = myVehicle.getLateralOverlap(posLat, lane);
491#ifdef DEBUG_SHADOWLANE
492 if (debugVehicle()) {
493 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " posLat=" << posLat << " overlap=" << overlap << "\n";
494 }
495#endif
496 if (myAmOpposite) {
497 // return the neigh-lane in forward direction
498 return lane->getParallelLane(1);
499 } else if (overlap > NUMERICAL_EPS) {
500 const int shadowDirection = posLat < 0 ? -1 : 1;
501 return lane->getParallelLane(shadowDirection);
502 } else if (isChangingLanes() && myLaneChangeCompletion < 0.5) {
503 // "reserve" target lane even when there is no overlap yet
505 } else {
506 return nullptr;
507 }
508 } else {
509 return nullptr;
510 }
511}
512
513
514MSLane*
518
519
520void
522 if (myShadowLane != nullptr) {
523 if (debugVehicle()) {
524 std::cout << SIMTIME << " cleanupShadowLane\n";
525 }
527 myShadowLane = nullptr;
528 }
529 for (std::vector<MSLane*>::const_iterator it = myShadowFurtherLanes.begin(); it != myShadowFurtherLanes.end(); ++it) {
530 if (debugVehicle()) {
531 std::cout << SIMTIME << " cleanupShadowLane2\n";
532 }
534 }
535 myShadowFurtherLanes.clear();
537}
538
539void
541 if (myTargetLane != nullptr) {
542 if (debugVehicle()) {
543 std::cout << SIMTIME << " cleanupTargetLane\n";
544 }
546 myTargetLane = nullptr;
547 }
548 for (std::vector<MSLane*>::const_iterator it = myFurtherTargetLanes.begin(); it != myFurtherTargetLanes.end(); ++it) {
549 if (debugVehicle()) {
550 std::cout << SIMTIME << " cleanupTargetLane\n";
551 }
552 if (*it != nullptr) {
554 }
555 }
556 myFurtherTargetLanes.clear();
557// myNoPartiallyOccupatedByShadow.clear();
558}
559
560
561bool
563 // store request before canceling
564 getCanceledState(laneOffset) |= state;
565 int ret = myVehicle.influenceChangeDecision(state);
566 return ret != state;
567}
568
569double
573
574void
576 if (dir > 0) {
578 } else if (dir < 0) {
580 }
581}
582
583void
585 if (!MSGlobals::gSublane) {
586 // assume each vehicle drives at the center of its lane and act as if it fits
587 return;
588 }
589 if (myShadowLane != nullptr) {
590#ifdef DEBUG_SHADOWLANE
591 if (debugVehicle()) {
592 std::cout << SIMTIME << " updateShadowLane()\n";
593 }
594#endif
596 }
598 std::vector<MSLane*> passed;
599 if (myShadowLane != nullptr) {
601 const std::vector<MSLane*>& further = myVehicle.getFurtherLanes();
602 if (myAmOpposite) {
603 assert(further.size() == 0);
604 } else {
605 const std::vector<double>& furtherPosLat = myVehicle.getFurtherLanesPosLat();
606 assert(further.size() == furtherPosLat.size());
607 passed.push_back(myShadowLane);
608 for (int i = 0; i < (int)further.size(); ++i) {
609 MSLane* shadowFurther = getShadowLane(further[i], furtherPosLat[i]);
610#ifdef DEBUG_SHADOWLANE
611 if (debugVehicle()) {
612 std::cout << SIMTIME << " further=" << further[i]->getID() << " (posLat=" << furtherPosLat[i] << ") shadowFurther=" << Named::getIDSecure(shadowFurther) << "\n";
613 }
614#endif
615 if (shadowFurther != nullptr && shadowFurther->getLinkTo(passed.back()) != nullptr) {
616 passed.push_back(shadowFurther);
617 }
618 }
619 std::reverse(passed.begin(), passed.end());
620 }
621 } else {
622 if (isChangingLanes() && myVehicle.getLateralOverlap() > NUMERICAL_EPS) {
623 WRITE_WARNING("Vehicle '" + myVehicle.getID() + "' could not finish continuous lane change (lane disappeared) time=" +
624 time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
626 }
627 }
628#ifdef DEBUG_SHADOWLANE
629 if (debugVehicle()) {
630 std::cout << SIMTIME << " updateShadowLane() veh=" << myVehicle.getID()
631 << " newShadowLane=" << Named::getIDSecure(myShadowLane)
632 << "\n before:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << " further=" << toString(myVehicle.getFurtherLanes()) << " passed=" << toString(passed);
633 std::cout << std::endl;
634 }
635#endif
637#ifdef DEBUG_SHADOWLANE
638 if (debugVehicle()) std::cout
639 << "\n after:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << "\n";
640#endif
641}
642
643
644int
646 if (isChangingLanes()) {
647 if (pastMidpoint()) {
648 return -myLaneChangeDirection;
649 } else {
651 }
652 } else if (myShadowLane == nullptr) {
653 return 0;
654 } else if (myAmOpposite) {
655 // return neigh-lane in forward direction
656 return 1;
657 } else if (&myShadowLane->getEdge() == &myVehicle.getLane()->getEdge()) {
659 } else {
660 // overlap with opposite direction lane
661 return 1;
662 }
663}
664
665
666MSLane*
668#ifdef DEBUG_TARGET_LANE
669 MSLane* oldTarget = myTargetLane;
670 std::vector<MSLane*> oldFurtherTargets = myFurtherTargetLanes;
671 if (debugVehicle()) {
672 std::cout << SIMTIME << " veh '" << myVehicle.getID() << "' (lane=" << myVehicle.getLane()->getID() << ") updateTargetLane()"
673 << "\n oldTarget: " << (oldTarget == nullptr ? "NULL" : oldTarget->getID())
674 << " oldFurtherTargets: " << toString(oldFurtherTargets);
675 }
676#endif
677 if (myTargetLane != nullptr) {
679 }
680 // Clear old further target lanes
681 for (MSLane* oldTargetLane : myFurtherTargetLanes) {
682 if (oldTargetLane != nullptr) {
683 oldTargetLane->resetManeuverReservation(&myVehicle);
684 }
685 }
686 myFurtherTargetLanes.clear();
687
688 // Get new target lanes and issue a maneuver reservation.
689 int targetDir;
691 if (myTargetLane != nullptr) {
693 // further targets are just the target lanes corresponding to the vehicle's further lanes
694 // @note In a neglectable amount of situations we might add a reservation for a shadow further lane.
695 for (MSLane* furtherLane : myVehicle.getFurtherLanes()) {
696 MSLane* furtherTargetLane = furtherLane->getParallelLane(targetDir);
697 myFurtherTargetLanes.push_back(furtherTargetLane);
698 if (furtherTargetLane != nullptr) {
699 furtherTargetLane->setManeuverReservation(&myVehicle);
700 }
701 }
702 }
703#ifdef DEBUG_TARGET_LANE
704 if (debugVehicle()) {
705 std::cout << "\n newTarget (maneuverDist=" << myManeuverDist << " offset=" << targetDir << "): " << (myTargetLane == nullptr ? "NULL" : myTargetLane->getID())
706 << " newFurtherTargets: " << toString(myFurtherTargetLanes)
707 << std::endl;
708 }
709#endif
710 return myTargetLane;
711}
712
713
714MSLane*
716 targetDir = 0;
717 if (myManeuverDist == 0) {
718 return nullptr;
719 }
720 // Current lateral boundaries of the vehicle
721 const double vehRight = myVehicle.getLateralPositionOnLane() - 0.5 * myVehicle.getWidth();
722 const double vehLeft = myVehicle.getLateralPositionOnLane() + 0.5 * myVehicle.getWidth();
723 const double halfLaneWidth = 0.5 * myVehicle.getLane()->getWidth();
724
725 if (vehRight + myManeuverDist < -halfLaneWidth) {
726 // Vehicle intends to traverse the right lane boundary
727 targetDir = -1;
728 } else if (vehLeft + myManeuverDist > halfLaneWidth) {
729 // Vehicle intends to traverse the left lane boundary
730 targetDir = 1;
731 }
732 if (targetDir == 0) {
733 // Presently, no maneuvering into another lane is begun.
734 return nullptr;
735 }
736 MSLane* target = myVehicle.getLane()->getParallelLane(targetDir);
737 if (target == nullptr || target == myShadowLane) {
738 return nullptr;
739 } else {
740 return target;
741 }
742}
743
744
745
746double
748 double result = 0.;
749 if (!(fabs(mySpeedLat) < NUMERICAL_EPS && fabs(myPreviousAngleOffset * 180 / M_PI) < NUMERICAL_EPS)) {
751 result = atan2(mySpeedLat, myVehicle.getSpeed());
752 } else {
754 }
755 }
756
757 myAngleOffset = result;
758 return result;
759}
760
761
762double
763MSAbstractLaneChangeModel::estimateLCDuration(const double speed, const double remainingManeuverDist, const double decel, bool urgent) const {
764
766 if (lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING) == lcParams.end() && lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR) == lcParams.end()) {
768 // no dependency of lateral speed on longitudinal speed. (Only called prior to LC initialization to determine whether it could be completed)
770 } else {
771 return remainingManeuverDist / myVehicle.getVehicleType().getMaxSpeedLat();
772 }
773 }
774
775 if (remainingManeuverDist == 0) {
776 return 0;
777 }
778
779 // Check argument assumptions
780 assert(speed >= 0);
781 assert(remainingManeuverDist >= 0);
782 assert(decel > 0);
785 assert(myMaxSpeedLatStanding >= 0);
786
787 // for brevity
788 const double v0 = speed;
789 const double D = remainingManeuverDist;
790 const double b = decel;
791 const double wmin = myMaxSpeedLatStanding;
792 const double f = myMaxSpeedLatFactor;
793 const double wmax = myVehicle.getVehicleType().getMaxSpeedLat();
794
795 /* Here's the approach for the calculation of the required time for the LC:
796 * To obtain the maximal LC-duration, for v(t) we assume that v(t)=max(0, v0-b*t),
797 * Where v(t)=0 <=> t >= ts:=v0/b
798 * For the lateral speed w(t) this gives:
799 * w(t) = min(wmax, wmin + f*v(t))
800 * The lateral distance covered until t is
801 * d(t) = int_0^t w(s) ds
802 * We distinguish three possibilities for the solution d(T)=D, where T is the time of the LC completion.
803 * 1) w(T) = wmax, i.e. v(T)>(wmax-wmin)/f
804 * 2) wmin < w(T) < wmax, i.e. (wmax-wmin)/f > v(T) > 0
805 * 3) w(T) = wmin, i.e., v(T)=0
806 */
807 const double vm = (wmax - wmin) / f;
808 double distSoFar = 0.;
809 double timeSoFar = 0.;
810 double v = v0;
811 if (v > vm) {
812 const double wmaxTime = (v0 - vm) / b;
813 const double d1 = wmax * wmaxTime;
814 if (d1 >= D) {
815 return D / wmax;
816 } else {
817 distSoFar += d1;
818 timeSoFar += wmaxTime;
819 v = vm;
820 }
821 }
822 if (v > 0) {
823 /* Here, w(t1+t) = wmin + f*v(t1+t) = wmin + f*(v - b*t)
824 * Thus, the additional lateral distance covered after time t is:
825 * d2 = (wmin + f*v)*t - 0.5*f*b*t^2
826 * and the additional lateral distance covered until v=0 at t=v/b is:
827 * d2 = (wmin + 0.5*f*v)*t
828 */
829 const double t = v / b; // stop time
830 const double d2 = (wmin + 0.5 * f * v) * t; // lateral distance covered until stop
831 assert(d2 > 0);
832 if (distSoFar + d2 >= D) {
833 // LC is completed during this phase
834 const double x = 0.5 * f * b;
835 const double y = wmin + f * v;
836 /* Solve D - distSoFar = y*t - x*t^2.
837 * 0 = x*t^2 - y*t/x + (D - distSoFar)/x
838 */
839 const double p = 0.5 * y / x;
840 const double q = (D - distSoFar) / x;
841 assert(p * p - q > 0);
842 const double t2 = p + sqrt(p * p - q);
843 return timeSoFar + t2;
844 } else {
845 distSoFar += d2;
846 timeSoFar += t;
847 //v = 0;
848 }
849 }
850 // If we didn't return yet this means the LC was not completed until the vehicle stops (if braking with rate b)
851 if (wmin == 0) {
852 // LC won't be completed if vehicle stands
853 double maneuverDist = remainingManeuverDist;
854 const double vModel = computeSpeedLat(maneuverDist, maneuverDist, urgent);
855 double result = D / vModel;
856 // make sure that the vehicle isn't braking to a stop during the manuever
857 if (vModel > SUMO_const_haltingSpeed && (vModel + myVehicle.getAcceleration() * result) > SUMO_const_haltingSpeed) {
858 // unless the model tells us something different
859 return result;
860 } else {
861 return -1;
862 }
863 } else {
864 // complete LC with lateral speed wmin
865 return timeSoFar + (D - distSoFar) / wmin;
866 }
867}
868
871 assert(isChangingLanes()); // Only to be called during ongoing lane change
873 if (lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING) == lcParams.end() && lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR) == lcParams.end()) {
876 } else {
878 }
879 }
880 // Using maxSpeedLat(Factor/Standing)
881 const bool urgent = (myOwnState & LCA_URGENT) != 0;
885}
886
887
888void
890 //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " set shadow approaching=" << link->getViaLaneOrLane()->getID() << "\n";
891 myApproachedByShadow.push_back(link);
892}
893
894void
896 for (std::vector<MSLink*>::iterator it = myApproachedByShadow.begin(); it != myApproachedByShadow.end(); ++it) {
897 //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " remove shadow approaching=" << (*it)->getViaLaneOrLane()->getID() << "\n";
898 (*it)->removeApproaching(&myVehicle);
899 }
900 myApproachedByShadow.clear();
901}
902
903
904
905void
908 int oldstate = myVehicle.getLaneChangeModel().getOwnState();
909 if (myOwnState != newstate) {
911 // Calculate and set the lateral maneuver distance corresponding to the change request
912 // to induce a corresponding sublane change.
913 const int dir = (newstate & LCA_RIGHT) != 0 ? -1 : ((newstate & LCA_LEFT) != 0 ? 1 : 0);
914 // minimum distance to move the vehicle fully onto the lane at offset dir
915 const double latLaneDist = myVehicle.lateralDistanceToLane(dir);
916 if ((newstate & LCA_TRACI) != 0) {
917 if ((newstate & LCA_STAY) != 0) {
918 setManeuverDist(0.);
919 } else if (((newstate & LCA_RIGHT) != 0 && dir < 0)
920 || ((newstate & LCA_LEFT) != 0 && dir > 0)) {
921 setManeuverDist(latLaneDist);
922 }
923 }
924 if (myVehicle.hasInfluencer()) {
925 // lane change requests override sublane change requests
927 }
928
929 }
930 setOwnState(newstate);
931 } else {
932 // Check for sublane change requests
934 const double maneuverDist = myVehicle.getInfluencer().getLatDist();
937 newstate |= LCA_TRACI;
938 if (myOwnState != newstate) {
939 setOwnState(newstate);
940 }
941 if (gDebugFlag2) {
942 std::cout << " traci influenced maneuverDist=" << maneuverDist << "\n";
943 }
944 }
945 }
946 if (gDebugFlag2) {
947 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " stateAfterTraCI=" << toString((LaneChangeAction)newstate) << " original=" << toString((LaneChangeAction)oldstate) << "\n";
948 }
949}
950
951void
956
957void
959 if (follower.first != 0) {
960 myLastFollowerGap = follower.second + follower.first->getVehicleType().getMinGap();
962 myLastFollowerSpeed = follower.first->getSpeed();
963 }
964}
965
966void
968 if (leader.first != 0) {
970 myLastLeaderSecureGap = secGap;
971 myLastLeaderSpeed = leader.first->getSpeed();
972 }
973}
974
975void
977 if (leader.first != 0) {
980 myLastOrigLeaderSpeed = leader.first->getSpeed();
981 }
982}
983
984void
1007
1008void
1010 int rightmost;
1011 int leftmost;
1012 vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
1013 for (int i = rightmost; i <= leftmost; ++i) {
1014 CLeaderDist vehDist = vehicles[i];
1015 if (vehDist.first != 0) {
1016 const MSVehicle* leader = &myVehicle;
1017 const MSVehicle* follower = vehDist.first;
1018 const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
1019 if (netGap < myLastFollowerGap && netGap >= 0) {
1020 myLastFollowerGap = netGap;
1021 myLastFollowerSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
1022 myLastFollowerSpeed = follower->getSpeed();
1023 }
1024 }
1025 }
1026}
1027
1028void
1030 int rightmost;
1031 int leftmost;
1032 vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
1033 for (int i = rightmost; i <= leftmost; ++i) {
1034 CLeaderDist vehDist = vehicles[i];
1035 if (vehDist.first != 0) {
1036 const MSVehicle* leader = vehDist.first;
1037 const MSVehicle* follower = &myVehicle;
1038 const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
1039 if (netGap < myLastLeaderGap && netGap >= 0) {
1040 myLastLeaderGap = netGap;
1041 myLastLeaderSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
1042 myLastLeaderSpeed = leader->getSpeed();
1043 }
1044 }
1045 }
1046}
1047
1048void
1050 int rightmost;
1051 int leftmost;
1052 vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
1053 for (int i = rightmost; i <= leftmost; ++i) {
1054 CLeaderDist vehDist = vehicles[i];
1055 if (vehDist.first != 0) {
1056 const MSVehicle* leader = vehDist.first;
1057 const MSVehicle* follower = &myVehicle;
1058 const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
1059 if (netGap < myLastOrigLeaderGap && netGap >= 0) {
1060 myLastOrigLeaderGap = netGap;
1061 myLastOrigLeaderSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
1062 myLastOrigLeaderSpeed = leader->getSpeed();
1063 }
1064 }
1065 }
1066}
1067
1068
1069bool
1071 const int stateRight = mySavedStateRight.second;
1072 if (
1073 (stateRight & LCA_STRATEGIC) != 0
1074 && (stateRight & LCA_RIGHT) != 0
1075 && (stateRight & LCA_BLOCKED) != 0) {
1076 return true;
1077 }
1078 const int stateLeft = mySavedStateLeft.second;
1079 if (
1080 (stateLeft & LCA_STRATEGIC) != 0
1081 && (stateLeft & LCA_LEFT) != 0
1082 && (stateLeft & LCA_BLOCKED) != 0) {
1083 return true;
1084 }
1085 return false;
1086}
1087
1088double
1092
1093
1094int
1096 const int i = myVehicle.getLane()->getIndex();
1097 if (myAmOpposite) {
1099 } else {
1100 return i;
1101 }
1102}
1103
1104void
1105MSAbstractLaneChangeModel::addLCSpeedAdvice(const double vSafe, bool ownAdvice) {
1106 const double accel = SPEED2ACCEL(vSafe - myVehicle.getSpeed());
1107 myLCAccelerationAdvices.push_back({accel, ownAdvice});
1108}
1109
1110
1111void
1113 std::vector<std::string> lcState;
1115 lcState.push_back(toString(mySpeedLat));
1116 lcState.push_back(toString(myLaneChangeCompletion));
1117 lcState.push_back(toString(myLaneChangeDirection));
1118 }
1119 if (lcState.size() > 0) {
1120 out.writeAttr(SUMO_ATTR_LCSTATE, lcState);
1121 }
1122}
1123
1124void
1126 if (attrs.hasAttribute(SUMO_ATTR_LCSTATE)) {
1127 std::istringstream bis(attrs.getString(SUMO_ATTR_LCSTATE));
1128 bis >> mySpeedLat;
1130 bis >> myLaneChangeDirection;
1131 }
1132}
1133
1134
1135double
1136MSAbstractLaneChangeModel::getExtraReservation(int bestLaneOffset, double neighExtraDist) const {
1137 if (neighExtraDist > myVehicle.getVehicleType().getLengthWithGap()) {
1138 return 0;
1139 }
1140 if (bestLaneOffset < -1) {
1141 return 20;
1142 } else if (bestLaneOffset > 1) {
1143 return 40;
1144 }
1145 return 0;
1146}
1147
1148
1149double
1150MSAbstractLaneChangeModel::getCooperativeHelpSpeed(const MSLane* lane, double distToLaneEnd) const {
1151 if (myCooperativeHelpTime >= 0) {
1152 std::pair<double, SUMOTime> backAndWaiting = lane->getEdge().getLastBlocked(lane->getIndex());
1153 if (backAndWaiting.second >= myCooperativeHelpTime) {
1154 const double gap = distToLaneEnd - lane->getLength() + backAndWaiting.first - myVehicle.getVehicleType().getMinGap() - NUMERICAL_EPS;
1155 if (gap > 0) {
1156 double stopSpeed = myVehicle.getCarFollowModel().stopSpeed(&myVehicle, myVehicle.getSpeed(), gap);
1157 //if (myVehicle.isSelected() && stopSpeed < myVehicle.getSpeed()) {
1158 // std::cout << SIMTIME << " veh=" << myVehicle.getID() << " lane=" << lane->getID() << " dte=" << distToLaneEnd << " gap=" << gap << " waiting=" << backAndWaiting.second << " helpTime=" << myCooperativeHelpTime << " stopSpeed=" << stopSpeed << " minNext=" << myVehicle.getCarFollowModel().minNextSpeed(myVehicle.getSpeed(), &myVehicle) << "\n";
1159 //}
1161 // regular braking is helpful
1162 return stopSpeed;
1163 }
1164 }
1165 }
1166 }
1167 // do not restrict speed
1168 return std::numeric_limits<double>::max();
1169}
long long int SUMOTime
Definition GUI.h:36
#define LC_ASSUMED_DECEL
std::pair< const MSVehicle *, double > CLeaderDist
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TLF(string,...)
Definition MsgHandler.h:306
SUMOTime DELTA_T
Definition SUMOTime.cpp:38
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition SUMOTime.cpp:91
#define STEPS2TIME(x)
Definition SUMOTime.h:55
#define SPEED2DIST(x)
Definition SUMOTime.h:45
#define SIMTIME
Definition SUMOTime.h:62
#define TIME2STEPS(x)
Definition SUMOTime.h:57
#define DIST2SPEED(x)
Definition SUMOTime.h:47
#define SPEED2ACCEL(x)
Definition SUMOTime.h:53
const long long int VTYPEPARS_MAXSPEED_LAT_SET
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_MOTORCYCLE
vehicle is a motorcycle
@ SVC_EMERGENCY
public emergency vehicles
@ SVC_MOPED
vehicle is a moped
LaneChangeAction
The state of a vehicle's lane-change behavior.
@ LCA_UNKNOWN
The action has not been determined.
@ LCA_BLOCKED
blocked in all directions
@ LCA_URGENT
The action is urgent (to be defined by lc-model)
@ LCA_STAY
Needs to stay on the current lane.
@ LCA_AMBACKBLOCKER
@ LCA_AMBLOCKINGLEADER
@ LCA_LEFT
Wants go to the left.
@ LCA_STRATEGIC
The action is needed to follow the route (navigational lc)
@ LCA_AMBACKBLOCKER_STANDING
@ LCA_TRACI
The action is due to a TraCI request.
@ LCA_RIGHT
Wants go to the right.
@ LCA_AMBLOCKINGFOLLOWER
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_LCA_ASSERTIVE
@ SUMO_ATTR_Y
@ SUMO_ATTR_X
@ SUMO_ATTR_LCA_MAXDISTLATSTANDING
@ SUMO_ATTR_LCA_COOPERATIVE_HELPTIME
@ SUMO_ATTR_LCA_MAXSPEEDLATFACTOR
@ SUMO_ATTR_LCA_MAXSPEEDLATSTANDING
@ SUMO_ATTR_LCA_STRATEGIC_LOOKAHEAD
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_LCA_SIGMA
@ SUMO_ATTR_TYPE
@ SUMO_ATTR_ID
@ SUMO_ATTR_LCSTATE
The state of the lanechange model.
@ SUMO_ATTR_LCA_OVERTAKE_RIGHT
@ SUMO_ATTR_DIR
The abstract direction of a link.
@ SUMO_ATTR_POSITION
@ SUMO_ATTR_TIME
trigger: the time of the step
bool gDebugFlag2
Definition StdDefs.cpp:44
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition StdDefs.h:62
T MAX2(T a, T b)
Definition StdDefs.h:86
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
Interface for lane-change models.
double getForwardPos() const
get vehicle position relative to the forward direction lane
double myAccelerationLat
the current lateral acceleration
void setFollowerGaps(CLeaderDist follower, double secGap)
virtual double getExtraReservation(int bestLaneOffset, double neighExtraDist=0) const
std::vector< MSLane * > myFurtherTargetLanes
bool myAlreadyChanged
whether the vehicle has already moved this step
bool myAmOpposite
whether the vehicle is driving in the opposite direction
std::shared_ptr< MSLeaderDistanceInfo > myRightFollowers
std::shared_ptr< MSLeaderDistanceInfo > myRightLeaders
virtual void setOwnState(const int state)
bool pastMidpoint() const
return whether the vehicle passed the midpoint of a continuous lane change maneuver
double myPreviousAngleOffset
the angle offset of the previous time step resulting from lane change and sigma
virtual double getAssumedDecelForLaneChangeDuration() const
Returns a deceleration value which is used for the estimation of the duration of a lane change.
virtual double computeSpeedLat(double latDist, double &maneuverDist, bool urgent) const
decides the next lateral speed depending on the remaining lane change distance to be covered and upda...
virtual double estimateLCDuration(const double speed, const double remainingManeuverDist, const double decel, bool urgent) const
Calculates the maximal time needed to complete a lane change maneuver if lcMaxSpeedLatFactor and lcMa...
std::shared_ptr< MSLeaderDistanceInfo > myLeftLeaders
int myPreviousState
lane changing state from the previous simulation step
double getManeuverDist() const
Returns the remaining unblocked distance for the current maneuver. (only used by sublane model)
int myOwnState
The current state of the vehicle.
double myLastOrigLeaderGap
acutal and secure distance to closest leader vehicle on the original when performing lane change
virtual bool predInteraction(const std::pair< MSVehicle *, double > &leader)
void laneChangeOutput(const std::string &tag, MSLane *source, MSLane *target, int direction, double maneuverDist=0)
called once the vehicle ends a lane change manoeuvre (non-instant)
bool myDontResetLCGaps
Flag to prevent resetting the memorized values for LC relevant gaps until the LC output is triggered ...
int myPreviousState2
lane changing state from step before the previous simulation step
MSLane * getShadowLane() const
Returns the lane the vehicle's shadow is on during continuous/sublane lane change.
const std::shared_ptr< MSLeaderDistanceInfo > getFollowers(const int dir)
Returns the neighboring, lc-relevant followers for the last step in the requested direction.
double myCommittedSpeed
the speed when committing to a change maneuver
std::shared_ptr< MSLeaderDistanceInfo > myLeftFollowers
Cached info on lc-relevant neighboring vehicles.
static bool myLCOutput
whether to record lane-changing
bool startLaneChangeManeuver(MSLane *source, MSLane *target, int direction)
start the lane change maneuver and return whether it continues
virtual void saveState(OutputDevice &out) const
Save the state of the laneChangeModel.
std::pair< int, int > mySavedStateRight
double myLastLeaderSecureGap
the minimum longitudinal distances to vehicles on the target lane that would be necessary for stringe...
void endLaneChangeManeuver(const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_LANE_CHANGE)
void saveLCState(const int dir, int stateWithoutTraCI, const int state)
static bool myAllowOvertakingRight
whether overtaking on the right is permitted
std::vector< MSLink * > myApproachedByShadow
links which are approached by the shadow vehicle
void addLCSpeedAdvice(const double vSafe, bool ownAdvice=true)
Takes a vSafe (speed advice for speed in the next simulation step), converts it into an acceleration ...
void setLeaderGaps(CLeaderDist, double secGap)
const std::shared_ptr< MSLeaderDistanceInfo > getLeaders(const int dir)
Returns the neighboring, lc-relevant leaders for the last step in the requested direction.
std::vector< MSLane * > myNoPartiallyOccupatedByShadow
bool cancelRequest(int state, int laneOffset)
whether the influencer cancels the given request
double myLastLeaderGap
the actual minimum longitudinal distances to vehicles on the target lane
SUMOTime remainingTime() const
Compute the remaining time until LC completion.
void setOrigLeaderGaps(CLeaderDist, double secGap)
void setManeuverDist(const double dist)
Updates the remaining distance for the current maneuver while it is continued within non-action steps...
std::vector< std::pair< double, bool > > myLCAccelerationAdvices
void setShadowApproachingInformation(MSLink *link) const
set approach information for the shadow vehicle
double getCooperativeHelpSpeed(const MSLane *lane, double distToLaneEnd) const
return speed for helping a vehicle that is blocked from changing
int getNormalizedLaneIndex()
brief return lane index that treats opposite lanes like normal lanes to the left of the forward lanes
static MSAbstractLaneChangeModel * build(LaneChangeModel lcm, MSVehicle &vehicle)
Factory method for instantiating new lane changing models.
void changedToOpposite()
called when a vehicle changes between lanes in opposite directions
void setSpeedLat(double speedLat)
set the lateral speed and update lateral acceleraton
MSLane * myTargetLane
The target lane for the vehicle's current maneuver.
MSLane * determineTargetLane(int &targetDir) const
double myPreviousManeuverDist
Maneuver distance from the previous simulation step.
double getMaxSpeedLat2() const
return the max of maxSpeedLat and lcMaxSpeedLatStanding
std::vector< double > myShadowFurtherLanesPosLat
const MSCFModel & getCarFollowModel() const
The vehicle's car following model.
MSLane * myShadowLane
A lane that is partially occupied by the front of the vehicle but that is not the primary lane.
double mySpeedLat
the current lateral speed
virtual void updateSafeLatDist(const double travelledLatDist)
Updates the value of safe lateral distances (in SL2015) during maneuver continuation in non-action st...
void checkTraCICommands()
Check for commands issued for the vehicle via TraCI and apply the appropriate state changes For the s...
double myManeuverDist
The complete lateral distance the vehicle wants to travel to finish its maneuver Only used by sublane...
int myLaneChangeDirection
direction of the lane change maneuver -1 means right, 1 means left
void primaryLaneChanged(MSLane *source, MSLane *target, int direction)
called once when the vehicles primary lane changes
int getShadowDirection() const
return the direction in which the current shadow lane lies
double myLastLeaderSpeed
speeds of surrounding vehicles at the time of lane change
virtual void loadState(const SUMOSAXAttributes &attrs)
Loads the state of the laneChangeModel from the given attributes.
MSAbstractLaneChangeModel(MSVehicle &v, const LaneChangeModel model)
Constructor.
MSVehicle & myVehicle
The vehicle this lane-changer belongs to.
double calcAngleOffset()
return the angle offset during a continuous change maneuver
double myAngleOffset
the current angle offset resulting from lane change and sigma
double myLastLateralGapLeft
the minimum lateral gaps to other vehicles that were found when last changing to the left and right
virtual ~MSAbstractLaneChangeModel()
Destructor.
static void initGlobalOptions(const OptionsCont &oc)
init global model parameters
void memorizeGapsAtLCInit()
Control for resetting the memorized values for LC relevant gaps until the LC output is triggered in t...
double myLaneChangeCompletion
progress of the lane change maneuver 0:started, 1:complete
virtual bool debugVehicle() const
whether the current vehicles shall be debugged
virtual void changed()=0
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
std::vector< MSLane * > myShadowFurtherLanes
virtual bool congested(const MSVehicle *const neighLeader)
void clearNeighbors()
Clear info on neighboring vehicle from previous step.
void saveNeighbors(const int dir, const MSLeaderDistanceInfo &followers, const MSLeaderDistanceInfo &leaders)
Saves the lane change relevant vehicles, which are currently on neighboring lanes in the given direct...
const SUMOVehicleParameter & getParameter() const
Returns the vehicle's parameter (including departure definition)
double getLength() const
Returns the vehicle's length.
double getWidth() const
Returns the vehicle's width.
SumoRNG * getRNG() const
const MSStop & getNextStop() const
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
virtual double interactionGap(const MSVehicle *const veh, double vL) const
Returns the maximum gap at which an interaction between both vehicles occurs.
virtual double minNextSpeed(double speed, const MSVehicle *const veh=0) const
Returns the minimum speed given the current speed (depends on the numerical update scheme and its ste...
virtual double getSecureGap(const MSVehicle *const veh, const MSVehicle *const, const double speed, const double leaderSpeed, const double leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum (>=0)
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
Definition MSCFModel.h:269
double stopSpeed(const MSVehicle *const veh, const double speed, double gap, const CalcReason usage=CalcReason::CURRENT) const
Computes the vehicle's safe speed for approaching a non-moving obstacle (no dawdling)
Definition MSCFModel.h:173
A device which collects info on the vehicle trip (mainly on departure and arrival)
std::pair< double, SUMOTime > getLastBlocked(int index) const
retrieve properties of a blocked vehicle that wants to chane to the lane with the given index
Definition MSEdge.cpp:1687
int getNumLanes() const
Definition MSEdge.h:172
static double gLateralResolution
Definition MSGlobals.h:100
static bool gLefthand
Whether lefthand-drive is being simulated.
Definition MSGlobals.h:174
static bool gSublane
whether sublane simulation is enabled (sublane model or continuous lanechanging)
Definition MSGlobals.h:165
static SUMOTime gLaneChangeDuration
Definition MSGlobals.h:97
A lane change model developed by D. Krajzewicz between 2004 and 2010.
A lane change model developed by D. Krajzewicz, J. Erdmann et al. between 2004 and 2013,...
A lane change model developed by D. Krajzewicz, J. Erdmann et al. between 2004 and 2013.
A lane change model developed by J. Erdmann.
Representation of a lane in the micro simulation.
Definition MSLane.h:84
MSLane * getParallelLane(int offset, bool includeOpposite=true) const
Returns the lane with the given offset parallel to this one or 0 if it does not exist.
Definition MSLane.cpp:2851
virtual void resetManeuverReservation(MSVehicle *v)
Unregisters a vehicle, which previously registered for maneuvering into this lane.
Definition MSLane.cpp:437
const MSLink * getLinkTo(const MSLane *const) const
returns the link to the given lane or nullptr, if it is not connected
Definition MSLane.cpp:2746
void forceVehicleInsertion(MSVehicle *veh, double pos, MSMoveReminder::Notification notification, double posLat=0)
Inserts the given vehicle at the given position.
Definition MSLane.cpp:1393
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition MSLane.h:597
void enteredByLaneChange(MSVehicle *v)
Definition MSLane.cpp:3360
double getLength() const
Returns the lane's length.
Definition MSLane.h:611
virtual double setPartialOccupation(MSVehicle *v)
Sets the information about a vehicle lapping into this lane.
Definition MSLane.cpp:384
int getIndex() const
Returns the lane's index.
Definition MSLane.h:647
void leftByLaneChange(MSVehicle *v)
Definition MSLane.cpp:3353
double getOppositePos(double pos) const
return the corresponding position on the opposite lane
Definition MSLane.cpp:4396
virtual void resetPartialOccupation(MSVehicle *v)
Removes the information about a vehicle lapping into this lane.
Definition MSLane.cpp:403
virtual void setManeuverReservation(MSVehicle *v)
Registers the lane change intentions (towards this lane) for the given vehicle.
Definition MSLane.cpp:426
MSLane * getParallelOpposite() const
return the opposite direction lane of this lanes edge or nullptr
Definition MSLane.cpp:4390
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:769
double getWidth() const
Returns the lane's width.
Definition MSLane.h:640
saves leader/follower vehicles and their distances relative to an ego vehicle
void getSubLanes(const MSVehicle *veh, double latOffset, int &rightmost, int &leftmost) const
Notification
Definition of a vehicle state.
@ NOTIFICATION_LANE_CHANGE
The vehicle changes lanes (micro only)
@ NOTIFICATION_PARKING
The vehicle starts or ends parking.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:186
bool isOpposite
whether this an opposite-direction stop
Definition MSStop.h:87
double getLatDist() const
Definition MSVehicle.h:1591
Representation of a vehicle in the micro simulation.
Definition MSVehicle.h:77
const std::vector< double > & getFurtherLanesPosLat() const
Definition MSVehicle.h:839
void setTentativeLaneAndPosition(MSLane *lane, double pos, double posLat=0)
set tentative lane and position during insertion to ensure that all cfmodels work (some of them requi...
MSAbstractLaneChangeModel & getLaneChangeModel()
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
void fixPosition()
repair errors in vehicle position after changing between internal edges
double getAcceleration() const
Returns the vehicle's acceleration in m/s (this is computed as the last step's mean acceleration in c...
Definition MSVehicle.h:514
Position getPosition(const double offset=0) const
Return current position (x/y, cartesian)
double lateralDistanceToLane(const int offset) const
Get the minimal lateral distance required to move fully onto the lane at given offset.
void leaveLane(const MSMoveReminder::Notification reason, const MSLane *approachedLane=0)
Update of members if vehicle leaves a new lane in the lane change step or at arrival.
void switchOffSignal(int signal)
Switches the given signal off.
Definition MSVehicle.h:1170
@ VEH_SIGNAL_BLINKER_RIGHT
Right blinker lights are switched on.
Definition MSVehicle.h:1109
@ VEH_SIGNAL_BLINKER_LEFT
Left blinker lights are switched on.
Definition MSVehicle.h:1111
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition MSVehicle.h:581
void enterLaneAtLaneChange(MSLane *enteredLane)
Update when the vehicle enters a new lane in the laneChange step.
Influencer & getInfluencer()
double updateFurtherLanes(std::vector< MSLane * > &furtherLanes, std::vector< double > &furtherLanesPosLat, const std::vector< MSLane * > &passedLanes)
update a vector of further lanes and return the new backPos
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
Definition MSVehicle.h:413
bool congested() const
double getSpeed() const
Returns the vehicle's current speed.
Definition MSVehicle.h:490
const std::vector< MSLane * > & getFurtherLanes() const
Definition MSVehicle.h:835
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition MSVehicle.h:969
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition MSVehicle.h:374
double getLateralOverlap() const
return the amount by which the vehicle extends laterally outside it's primary lane
bool hasInfluencer() const
whether the vehicle is individually influenced (via TraCI or special parameters)
Definition MSVehicle.h:1690
void switchOnSignal(int signal)
Switches the given signal on.
Definition MSVehicle.h:1162
void updateDriveItems()
Check whether the drive items (myLFLinkLanes) are up to date, and update them if required.
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
const std::string & getID() const
Returns the name of the vehicle type.
double getMinGap() const
Get the free space in front of vehicles of this class.
bool wasSet(long long int what) const
Returns whether the given parameter was set.
double getMaxSpeedLat() const
Get vehicle's maximum lateral speed [m/s].
const SUMOVTypeParameter & getParameter() const
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition Named.h:67
const std::string & getID() const
Returns the id.
Definition Named.h:74
A storage for options typed value containers)
Definition OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
Static storage of an output device and its base (abstract) implementation.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
static OutputDevice & getDeviceByOption(const std::string &name)
Returns the device described by the option.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
double x() const
Returns the x-position.
Definition Position.h:52
double y() const
Returns the y-position.
Definition Position.h:57
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
Encapsulated SAX-Attributes.
virtual std::string getString(int id, bool *isPresent=nullptr) const =0
Returns the string-value of the named (by its enum-value) attribute.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
std::map< SumoXMLAttr, std::string > SubParams
sub-model parameters
const SubParams & getLCParams() const
Returns the LC parameter.
#define UNUSED_PARAMETER(x)
#define DEBUG_COND
Definition json.hpp:4471
#define M_PI
Definition odrSpiral.cpp:45