Eclipse SUMO - Simulation of Urban MObility
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-2023 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_SL2015.h"
52
53/* -------------------------------------------------------------------------
54 * static members
55 * ----------------------------------------------------------------------- */
61const double MSAbstractLaneChangeModel::NO_NEIGHBOR(std::numeric_limits<double>::max());
62
63#define LC_ASSUMED_DECEL 1.0 // the minimal constant deceleration assumed to estimate the duration of a continuous lane-change at its initiation.
64
65/* -------------------------------------------------------------------------
66 * MSAbstractLaneChangeModel-methods
67 * ----------------------------------------------------------------------- */
68
69void
71 myAllowOvertakingRight = oc.getBool("lanechange.overtake-right");
72 myLCOutput = oc.isSet("lanechange-output");
73 myLCStartedOutput = oc.getBool("lanechange-output.started");
74 myLCEndedOutput = oc.getBool("lanechange-output.ended");
75 myLCXYOutput = oc.getBool("lanechange-output.xy");
76}
77
78
82 throw ProcessError(TLF("Lane change model '%' is not compatible with sublane simulation", toString(lcm)));
83 }
84 switch (lcm) {
86 return new MSLCM_DK2008(v);
88 return new MSLCM_LC2013(v);
90 return new MSLCM_SL2015(v);
93 return new MSLCM_LC2013(v);
94 } else {
95 return new MSLCM_SL2015(v);
96 }
97 default:
98 throw ProcessError(TLF("Lane change model '%' not implemented", toString(lcm)));
99 }
100}
101
102
104 myVehicle(v),
105 myOwnState(0),
106 myPreviousState(0),
107 myPreviousState2(0),
108 myCanceledStateRight(LCA_NONE),
109 myCanceledStateCenter(LCA_NONE),
110 myCanceledStateLeft(LCA_NONE),
111 mySpeedLat(0),
112 myAccelerationLat(0),
113 myAngleOffset(0),
114 myPreviousAngleOffset(0),
115 myCommittedSpeed(0),
116 myLaneChangeCompletion(1.0),
117 myLaneChangeDirection(0),
118 myAlreadyChanged(false),
119 myShadowLane(nullptr),
120 myTargetLane(nullptr),
121 myModel(model),
122 myLastLateralGapLeft(0.),
123 myLastLateralGapRight(0.),
124 myLastLeaderGap(0.),
125 myLastFollowerGap(0.),
126 myLastLeaderSecureGap(0.),
127 myLastFollowerSecureGap(0.),
128 myLastOrigLeaderGap(0.),
129 myLastOrigLeaderSecureGap(0.),
130 myLastLeaderSpeed(0),
131 myLastFollowerSpeed(0),
132 myLastOrigLeaderSpeed(0),
133 myDontResetLCGaps(false),
134 myMaxSpeedLatStanding(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING, v.getVehicleType().getMaxSpeedLat())),
135 myMaxSpeedLatFactor(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR, 1)),
136 myMaxDistLatStanding(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXDISTLATSTANDING,
137 // prevent lateral sliding for cars but permit for two-wheelers due to better maneuverability
138 (v.getVClass() & (SVC_BICYCLE | SVC_MOTORCYCLE | SVC_MOPED)) != 0 ? std::numeric_limits<double>::max() : 1.6)),
139 mySigma(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SIGMA, 0.0)),
140 myOvertakeRightParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_OVERTAKE_RIGHT, 0)),
141 myHaveBlueLight(v.getDevice(typeid(MSDevice_Bluelight)) != nullptr), // see MSVehicle::initDevices
142 myLastLaneChangeOffset(0),
143 myAmOpposite(false),
144 myManeuverDist(0.),
145 myPreviousManeuverDist(0.) {
149}
150
151
153}
154
155void
158 myOwnState = state;
159 myPreviousState = state; // myOwnState is modified in prepareStep so we make a backup
160}
161
162void
163MSAbstractLaneChangeModel::updateSafeLatDist(const double travelledLatDist) {
164 UNUSED_PARAMETER(travelledLatDist);
165}
166
167
168void
170#ifdef DEBUG_MANEUVER
171 if (DEBUG_COND) {
172 std::cout << SIMTIME
173 << " veh=" << myVehicle.getID()
174 << " setManeuverDist() old=" << myManeuverDist << " new=" << dist
175 << std::endl;
176 }
177#endif
178 myManeuverDist = fabs(dist) < NUMERICAL_EPS ? 0. : dist;
179 // store value which may be modified by the model during the next step
181}
182
183
184double
186 return myManeuverDist;
187}
188
189double
192}
193
194void
196 if (dir == -1) {
197 myLeftFollowers = std::make_shared<MSLeaderDistanceInfo>(followers);
198 myLeftLeaders = std::make_shared<MSLeaderDistanceInfo>(leaders);
199 } else if (dir == 1) {
200 myRightFollowers = std::make_shared<MSLeaderDistanceInfo>(followers);
201 myRightLeaders = std::make_shared<MSLeaderDistanceInfo>(leaders);
202 } else {
203 // dir \in {-1,1} !
204 assert(false);
205 }
206}
207
208
209void
210MSAbstractLaneChangeModel::saveNeighbors(const int dir, const std::pair<MSVehicle* const, double>& follower, const std::pair<MSVehicle* const, double>& leader) {
211 if (dir == -1) {
212 myLeftFollowers = std::make_shared<MSLeaderDistanceInfo>(follower, myVehicle.getLane()->getWidth());
213 myLeftLeaders = std::make_shared<MSLeaderDistanceInfo>(leader, myVehicle.getLane()->getWidth());
214 } else if (dir == 1) {
215 myRightFollowers = std::make_shared<MSLeaderDistanceInfo>(follower, myVehicle.getLane()->getWidth());
216 myRightLeaders = std::make_shared<MSLeaderDistanceInfo>(leader, myVehicle.getLane()->getWidth());
217 } else {
218 // dir \in {-1,1} !
219 assert(false);
220 }
221}
222
223
224void
226 myLeftFollowers = nullptr;
227 myLeftLeaders = nullptr;
228 myRightFollowers = nullptr;
229 myRightLeaders = nullptr;
230}
231
232
233const std::shared_ptr<MSLeaderDistanceInfo>
235 if (dir == -1) {
236 return myLeftFollowers;
237 } else if (dir == 1) {
238 return myRightFollowers;
239 } else {
240 // dir \in {-1,1} !
241 assert(false);
242 }
243 return nullptr;
244}
245
246const std::shared_ptr<MSLeaderDistanceInfo>
248 if (dir == -1) {
249 return myLeftLeaders;
250 } else if (dir == 1) {
251 return myRightLeaders;
252 } else {
253 // dir \in {-1,1} !
254 assert(false);
255 }
256 return nullptr;
257}
258
259
260bool
262 if (neighLeader == nullptr) {
263 return false;
264 }
265 // Congested situation are relevant only on highways (maxSpeed > 70km/h)
266 // and congested on German Highways means that the vehicles have speeds
267 // below 60km/h. Overtaking on the right is allowed then.
268 if ((myVehicle.getLane()->getSpeedLimit() <= 70.0 / 3.6) || (neighLeader->getLane()->getSpeedLimit() <= 70.0 / 3.6)) {
269
270 return false;
271 }
272 if (myVehicle.congested() && neighLeader->congested()) {
273 return true;
274 }
275 return false;
276}
277
278
279bool
282 && !myVehicle.congested()
285}
286
287bool
288MSAbstractLaneChangeModel::predInteraction(const std::pair<MSVehicle*, double>& leader) {
289 if (leader.first == 0) {
290 return false;
291 }
292 // let's check it on highways only
293 if (leader.first->getSpeed() < (80.0 / 3.6)) {
294 return false;
295 }
296 return leader.second < getCarFollowModel().interactionGap(&myVehicle, leader.first->getSpeed());
297}
298
299
300bool
304 myLaneChangeDirection = direction;
305 setManeuverDist((target->getWidth() + source->getWidth()) * 0.5 * direction);
308 if (myLCOutput) {
310 }
311 return true;
312 } else {
313 primaryLaneChanged(source, target, direction);
314 return false;
315 }
316}
317
318void
320 myDontResetLCGaps = true;
321}
322
323void
325 myDontResetLCGaps = false;
326}
327
328void
330 initLastLaneChangeOffset(direction);
332 source->leftByLaneChange(&myVehicle);
333 laneChangeOutput("change", source, target, direction); // record position on the source edge in case of opposite change
334 if (&source->getEdge() != &target->getEdge()) {
336#ifdef DEBUG_OPPOSITE
337 if (debugVehicle()) {
338 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " primaryLaneChanged source=" << source->getID() << " target=" << target->getID() << " nowOpposite=" << myAmOpposite << "\n";
339 }
340#endif
343 } else if (myAmOpposite) {
344#ifdef DEBUG_OPPOSITE
345 if (debugVehicle()) {
346 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " primaryLaneChanged source=" << source->getID() << " target=" << target->getID() << " stayOpposite\n";
347 }
348#endif
349 myAlreadyChanged = true;
351 if (!MSGlobals::gSublane) {
352 // in the continous case, the vehicle is added to the target lane via MSLaneChanger::continueChange / registerHop
353 // in the sublane case, the vehicle is added to the target lane via MSLaneChangerSublane::checkChangeOppositeSublane / MSLane::myTmpVehicles
355 }
356 } else {
359 }
360 // Assure that the drive items are up to date (even if the following step is no actionstep for the vehicle).
361 // This is necessary because the lane advance uses the target lane from the corresponding drive item.
363 changed();
364}
365
366void
367MSAbstractLaneChangeModel::laneChangeOutput(const std::string& tag, MSLane* source, MSLane* target, int direction, double maneuverDist) {
368 if (myLCOutput) {
369 OutputDevice& of = OutputDevice::getDeviceByOption("lanechange-output");
370 of.openTag(tag);
373 of.writeAttr(SUMO_ATTR_TIME, time2string(MSNet::getInstance()->getCurrentTimeStep()));
374 of.writeAttr(SUMO_ATTR_FROM, source->getID());
375 of.writeAttr(SUMO_ATTR_TO, target->getID());
376 of.writeAttr(SUMO_ATTR_DIR, direction);
384 of.writeAttr("leaderGap", myLastLeaderGap == NO_NEIGHBOR ? "None" : toString(myLastLeaderGap));
385 of.writeAttr("leaderSecureGap", myLastLeaderSecureGap == NO_NEIGHBOR ? "None" : toString(myLastLeaderSecureGap));
386 of.writeAttr("leaderSpeed", myLastLeaderSpeed == NO_NEIGHBOR ? "None" : toString(myLastLeaderSpeed));
387 of.writeAttr("followerGap", myLastFollowerGap == NO_NEIGHBOR ? "None" : toString(myLastFollowerGap));
388 of.writeAttr("followerSecureGap", myLastFollowerSecureGap == NO_NEIGHBOR ? "None" : toString(myLastFollowerSecureGap));
389 of.writeAttr("followerSpeed", myLastFollowerSpeed == NO_NEIGHBOR ? "None" : toString(myLastFollowerSpeed));
390 of.writeAttr("origLeaderGap", myLastOrigLeaderGap == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderGap));
391 of.writeAttr("origLeaderSecureGap", myLastOrigLeaderSecureGap == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderSecureGap));
392 of.writeAttr("origLeaderSpeed", myLastOrigLeaderSpeed == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderSpeed));
394 const double latGap = direction < 0 ? myLastLateralGapRight : myLastLateralGapLeft;
395 of.writeAttr("latGap", latGap == NO_NEIGHBOR ? "None" : toString(latGap));
396 if (maneuverDist != 0) {
397 of.writeAttr("maneuverDistance", toString(maneuverDist));
398 }
399 }
400 if (myLCXYOutput) {
403 }
404 of.closeTag();
407 }
408 }
409}
410
411
412double
413MSAbstractLaneChangeModel::computeSpeedLat(double /*latDist*/, double& maneuverDist, bool /*urgent*/) const {
415 int stepsToChange = (int)ceil(fabs(maneuverDist) / SPEED2DIST(myVehicle.getVehicleType().getMaxSpeedLat()));
416 return DIST2SPEED(maneuverDist / stepsToChange);
417 } else {
418 return maneuverDist / STEPS2TIME(MSGlobals::gLaneChangeDuration);
419 }
420}
421
422
423double
426}
427
428void
431 mySpeedLat = speedLat;
432}
433
434
435void
438 setSpeedLat(0);
439 }
440}
441
442
443bool
445 const bool pastBefore = pastMidpoint();
446 // maneuverDist is not updated in the context of continuous lane changing but represents the full LC distance
447 double maneuverDist = getManeuverDist();
448 setSpeedLat(computeSpeedLat(0, maneuverDist, (myOwnState & LCA_URGENT) != 0));
450 return !pastBefore && pastMidpoint();
451}
452
453
454void
456 UNUSED_PARAMETER(reason);
465 // opposite driving continues after parking
466 } else {
467 // aborted maneuver
468#ifdef DEBUG_OPPOSITE
469 if (debugVehicle()) {
470 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " aborted maneuver (no longer opposite)\n";
471 }
472#endif
474 }
475 }
476}
477
478
479MSLane*
480MSAbstractLaneChangeModel::getShadowLane(const MSLane* lane, double posLat) const {
482 // initialize shadow lane
483 const double overlap = myVehicle.getLateralOverlap(posLat, lane);
484#ifdef DEBUG_SHADOWLANE
485 if (debugVehicle()) {
486 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " posLat=" << posLat << " overlap=" << overlap << "\n";
487 }
488#endif
489 if (myAmOpposite) {
490 // return the neigh-lane in forward direction
491 return lane->getParallelLane(1);
492 } else if (overlap > NUMERICAL_EPS) {
493 const int shadowDirection = posLat < 0 ? -1 : 1;
494 return lane->getParallelLane(shadowDirection);
495 } else if (isChangingLanes() && myLaneChangeCompletion < 0.5) {
496 // "reserve" target lane even when there is no overlap yet
498 } else {
499 return nullptr;
500 }
501 } else {
502 return nullptr;
503 }
504}
505
506
507MSLane*
510}
511
512
513void
515 if (myShadowLane != nullptr) {
516 if (debugVehicle()) {
517 std::cout << SIMTIME << " cleanupShadowLane\n";
518 }
520 myShadowLane = nullptr;
521 }
522 for (std::vector<MSLane*>::const_iterator it = myShadowFurtherLanes.begin(); it != myShadowFurtherLanes.end(); ++it) {
523 if (debugVehicle()) {
524 std::cout << SIMTIME << " cleanupShadowLane2\n";
525 }
526 (*it)->resetPartialOccupation(&myVehicle);
527 }
528 myShadowFurtherLanes.clear();
530}
531
532void
534 if (myTargetLane != nullptr) {
535 if (debugVehicle()) {
536 std::cout << SIMTIME << " cleanupTargetLane\n";
537 }
539 myTargetLane = nullptr;
540 }
541 for (std::vector<MSLane*>::const_iterator it = myFurtherTargetLanes.begin(); it != myFurtherTargetLanes.end(); ++it) {
542 if (debugVehicle()) {
543 std::cout << SIMTIME << " cleanupTargetLane\n";
544 }
545 if (*it != nullptr) {
546 (*it)->resetManeuverReservation(&myVehicle);
547 }
548 }
549 myFurtherTargetLanes.clear();
550// myNoPartiallyOccupatedByShadow.clear();
551}
552
553
554bool
556 // store request before canceling
557 getCanceledState(laneOffset) |= state;
558 int ret = myVehicle.influenceChangeDecision(state);
559 return ret != state;
560}
561
562double
565}
566
567void
569 if (dir > 0) {
571 } else if (dir < 0) {
573 }
574}
575
576void
578 if (!MSGlobals::gSublane) {
579 // assume each vehicle drives at the center of its lane and act as if it fits
580 return;
581 }
582 if (myShadowLane != nullptr) {
583#ifdef DEBUG_SHADOWLANE
584 if (debugVehicle()) {
585 std::cout << SIMTIME << " updateShadowLane()\n";
586 }
587#endif
589 }
591 std::vector<MSLane*> passed;
592 if (myShadowLane != nullptr) {
594 const std::vector<MSLane*>& further = myVehicle.getFurtherLanes();
595 if (myAmOpposite) {
596 assert(further.size() == 0);
597 } else {
598 const std::vector<double>& furtherPosLat = myVehicle.getFurtherLanesPosLat();
599 assert(further.size() == furtherPosLat.size());
600 passed.push_back(myShadowLane);
601 for (int i = 0; i < (int)further.size(); ++i) {
602 MSLane* shadowFurther = getShadowLane(further[i], furtherPosLat[i]);
603#ifdef DEBUG_SHADOWLANE
604 if (debugVehicle()) {
605 std::cout << SIMTIME << " further=" << further[i]->getID() << " (posLat=" << furtherPosLat[i] << ") shadowFurther=" << Named::getIDSecure(shadowFurther) << "\n";
606 }
607#endif
608 if (shadowFurther != nullptr && shadowFurther->getLinkTo(passed.back()) != nullptr) {
609 passed.push_back(shadowFurther);
610 }
611 }
612 std::reverse(passed.begin(), passed.end());
613 }
614 } else {
615 if (isChangingLanes() && myVehicle.getLateralOverlap() > NUMERICAL_EPS) {
616 WRITE_WARNING("Vehicle '" + myVehicle.getID() + "' could not finish continuous lane change (lane disappeared) time=" +
617 time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
619 }
620 }
621#ifdef DEBUG_SHADOWLANE
622 if (debugVehicle()) {
623 std::cout << SIMTIME << " updateShadowLane() veh=" << myVehicle.getID()
624 << " newShadowLane=" << Named::getIDSecure(myShadowLane)
625 << "\n before:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << " further=" << toString(myVehicle.getFurtherLanes()) << " passed=" << toString(passed);
626 std::cout << std::endl;
627 }
628#endif
630#ifdef DEBUG_SHADOWLANE
631 if (debugVehicle()) std::cout
632 << "\n after:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << "\n";
633#endif
634}
635
636
637int
639 if (isChangingLanes()) {
640 if (pastMidpoint()) {
641 return -myLaneChangeDirection;
642 } else {
644 }
645 } else if (myShadowLane == nullptr) {
646 return 0;
647 } else if (myAmOpposite) {
648 // return neigh-lane in forward direction
649 return 1;
650 } else if (&myShadowLane->getEdge() == &myVehicle.getLane()->getEdge()) {
652 } else {
653 // overlap with opposite direction lane
654 return 1;
655 }
656}
657
658
659MSLane*
661#ifdef DEBUG_TARGET_LANE
662 MSLane* oldTarget = myTargetLane;
663 std::vector<MSLane*> oldFurtherTargets = myFurtherTargetLanes;
664 if (debugVehicle()) {
665 std::cout << SIMTIME << " veh '" << myVehicle.getID() << "' (lane=" << myVehicle.getLane()->getID() << ") updateTargetLane()"
666 << "\n oldTarget: " << (oldTarget == nullptr ? "NULL" : oldTarget->getID())
667 << " oldFurtherTargets: " << toString(oldFurtherTargets);
668 }
669#endif
670 if (myTargetLane != nullptr) {
672 }
673 // Clear old further target lanes
674 for (MSLane* oldTargetLane : myFurtherTargetLanes) {
675 if (oldTargetLane != nullptr) {
676 oldTargetLane->resetManeuverReservation(&myVehicle);
677 }
678 }
679 myFurtherTargetLanes.clear();
680
681 // Get new target lanes and issue a maneuver reservation.
682 int targetDir;
684 if (myTargetLane != nullptr) {
686 // further targets are just the target lanes corresponding to the vehicle's further lanes
687 // @note In a neglectable amount of situations we might add a reservation for a shadow further lane.
688 for (MSLane* furtherLane : myVehicle.getFurtherLanes()) {
689 MSLane* furtherTargetLane = furtherLane->getParallelLane(targetDir);
690 myFurtherTargetLanes.push_back(furtherTargetLane);
691 if (furtherTargetLane != nullptr) {
692 furtherTargetLane->setManeuverReservation(&myVehicle);
693 }
694 }
695 }
696#ifdef DEBUG_TARGET_LANE
697 if (debugVehicle()) {
698 std::cout << "\n newTarget (maneuverDist=" << myManeuverDist << " offset=" << targetDir << "): " << (myTargetLane == nullptr ? "NULL" : myTargetLane->getID())
699 << " newFurtherTargets: " << toString(myFurtherTargetLanes)
700 << std::endl;
701 }
702#endif
703 return myTargetLane;
704}
705
706
707MSLane*
709 targetDir = 0;
710 if (myManeuverDist == 0) {
711 return nullptr;
712 }
713 // Current lateral boundaries of the vehicle
714 const double vehRight = myVehicle.getLateralPositionOnLane() - 0.5 * myVehicle.getWidth();
715 const double vehLeft = myVehicle.getLateralPositionOnLane() + 0.5 * myVehicle.getWidth();
716 const double halfLaneWidth = 0.5 * myVehicle.getLane()->getWidth();
717
718 if (vehRight + myManeuverDist < -halfLaneWidth) {
719 // Vehicle intends to traverse the right lane boundary
720 targetDir = -1;
721 } else if (vehLeft + myManeuverDist > halfLaneWidth) {
722 // Vehicle intends to traverse the left lane boundary
723 targetDir = 1;
724 }
725 if (targetDir == 0) {
726 // Presently, no maneuvering into another lane is begun.
727 return nullptr;
728 }
729 MSLane* target = myVehicle.getLane()->getParallelLane(targetDir);
730 if (target == nullptr || target == myShadowLane) {
731 return nullptr;
732 } else {
733 return target;
734 }
735}
736
737
738
739double
741 double result = 0.;
742 if (!(fabs(mySpeedLat) < NUMERICAL_EPS && fabs(myPreviousAngleOffset * 180 / M_PI) < NUMERICAL_EPS)) {
744 result = atan2(mySpeedLat, myVehicle.getSpeed());
745 } else {
747 }
748 }
749
750 myAngleOffset = result;
751 return result;
752}
753
754
755double
756MSAbstractLaneChangeModel::estimateLCDuration(const double speed, const double remainingManeuverDist, const double decel, bool urgent) const {
757
759 if (lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING) == lcParams.end() && lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR) == lcParams.end()) {
761 // no dependency of lateral speed on longitudinal speed. (Only called prior to LC initialization to determine whether it could be completed)
763 } else {
764 return remainingManeuverDist / myVehicle.getVehicleType().getMaxSpeedLat();
765 }
766 }
767
768 if (remainingManeuverDist == 0) {
769 return 0;
770 }
771
772 // Check argument assumptions
773 assert(speed >= 0);
774 assert(remainingManeuverDist >= 0);
775 assert(decel > 0);
778 assert(myMaxSpeedLatStanding >= 0);
779
780 // for brevity
781 const double v0 = speed;
782 const double D = remainingManeuverDist;
783 const double b = decel;
784 const double wmin = myMaxSpeedLatStanding;
785 const double f = myMaxSpeedLatFactor;
786 const double wmax = myVehicle.getVehicleType().getMaxSpeedLat();
787
788 /* Here's the approach for the calculation of the required time for the LC:
789 * To obtain the maximal LC-duration, for v(t) we assume that v(t)=max(0, v0-b*t),
790 * Where v(t)=0 <=> t >= ts:=v0/b
791 * For the lateral speed w(t) this gives:
792 * w(t) = min(wmax, wmin + f*v(t))
793 * The lateral distance covered until t is
794 * d(t) = int_0^t w(s) ds
795 * We distinguish three possibilities for the solution d(T)=D, where T is the time of the LC completion.
796 * 1) w(T) = wmax, i.e. v(T)>(wmax-wmin)/f
797 * 2) wmin < w(T) < wmax, i.e. (wmax-wmin)/f > v(T) > 0
798 * 3) w(T) = wmin, i.e., v(T)=0
799 */
800 const double vm = (wmax - wmin) / f;
801 double distSoFar = 0.;
802 double timeSoFar = 0.;
803 double v = v0;
804 if (v > vm) {
805 const double wmaxTime = (v0 - vm) / b;
806 const double d1 = wmax * wmaxTime;
807 if (d1 >= D) {
808 return D / wmax;
809 } else {
810 distSoFar += d1;
811 timeSoFar += wmaxTime;
812 v = vm;
813 }
814 }
815 if (v > 0) {
816 /* Here, w(t1+t) = wmin + f*v(t1+t) = wmin + f*(v - b*t)
817 * Thus, the additional lateral distance covered after time t is:
818 * d2 = (wmin + f*v)*t - 0.5*f*b*t^2
819 * and the additional lateral distance covered until v=0 at t=v/b is:
820 * d2 = (wmin + 0.5*f*v)*t
821 */
822 const double t = v / b; // stop time
823 const double d2 = (wmin + 0.5 * f * v) * t; // lateral distance covered until stop
824 assert(d2 > 0);
825 if (distSoFar + d2 >= D) {
826 // LC is completed during this phase
827 const double x = 0.5 * f * b;
828 const double y = wmin + f * v;
829 /* Solve D - distSoFar = y*t - x*t^2.
830 * 0 = x*t^2 - y*t/x + (D - distSoFar)/x
831 */
832 const double p = 0.5 * y / x;
833 const double q = (D - distSoFar) / x;
834 assert(p * p - q > 0);
835 const double t2 = p + sqrt(p * p - q);
836 return timeSoFar + t2;
837 } else {
838 distSoFar += d2;
839 timeSoFar += t;
840 //v = 0;
841 }
842 }
843 // If we didn't return yet this means the LC was not completed until the vehicle stops (if braking with rate b)
844 if (wmin == 0) {
845 // LC won't be completed if vehicle stands
846 double maneuverDist = remainingManeuverDist;
847 const double vModel = computeSpeedLat(maneuverDist, maneuverDist, urgent);
848 if (vModel > 0) {
849 // unless the model tells us something different
850 return D / vModel;
851 } else {
852 return -1;
853 }
854 } else {
855 // complete LC with lateral speed wmin
856 return timeSoFar + (D - distSoFar) / wmin;
857 }
858}
859
862 assert(isChangingLanes()); // Only to be called during ongoing lane change
864 if (lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING) == lcParams.end() && lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR) == lcParams.end()) {
867 } else {
869 }
870 }
871 // Using maxSpeedLat(Factor/Standing)
872 const bool urgent = (myOwnState & LCA_URGENT) != 0;
876}
877
878
879void
881 //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " set shadow approaching=" << link->getViaLaneOrLane()->getID() << "\n";
882 myApproachedByShadow.push_back(link);
883}
884
885void
887 for (std::vector<MSLink*>::iterator it = myApproachedByShadow.begin(); it != myApproachedByShadow.end(); ++it) {
888 //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " remove shadow approaching=" << (*it)->getViaLaneOrLane()->getID() << "\n";
889 (*it)->removeApproaching(&myVehicle);
890 }
891 myApproachedByShadow.clear();
892}
893
894
895
896void
899 int oldstate = myVehicle.getLaneChangeModel().getOwnState();
900 if (myOwnState != newstate) {
902 // Calculate and set the lateral maneuver distance corresponding to the change request
903 // to induce a corresponding sublane change.
904 const int dir = (newstate & LCA_RIGHT) != 0 ? -1 : ((newstate & LCA_LEFT) != 0 ? 1 : 0);
905 // minimum distance to move the vehicle fully onto the lane at offset dir
906 const double latLaneDist = myVehicle.lateralDistanceToLane(dir);
907 if ((newstate & LCA_TRACI) != 0) {
908 if ((newstate & LCA_STAY) != 0) {
909 setManeuverDist(0.);
910 } else if (((newstate & LCA_RIGHT) != 0 && dir < 0)
911 || ((newstate & LCA_LEFT) != 0 && dir > 0)) {
912 setManeuverDist(latLaneDist);
913 }
914 }
915 if (myVehicle.hasInfluencer()) {
916 // lane change requests override sublane change requests
918 }
919
920 }
921 setOwnState(newstate);
922 } else {
923 // Check for sublane change requests
925 const double maneuverDist = myVehicle.getInfluencer().getLatDist();
928 newstate |= LCA_TRACI;
929 if (myOwnState != newstate) {
930 setOwnState(newstate);
931 }
932 if (gDebugFlag2) {
933 std::cout << " traci influenced maneuverDist=" << maneuverDist << "\n";
934 }
935 }
936 }
937 if (gDebugFlag2) {
938 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " stateAfterTraCI=" << toString((LaneChangeAction)newstate) << " original=" << toString((LaneChangeAction)oldstate) << "\n";
939 }
940}
941
942void
945 myAlreadyChanged = true;
946}
947
948void
950 if (follower.first != 0) {
951 myLastFollowerGap = follower.second + follower.first->getVehicleType().getMinGap();
953 myLastFollowerSpeed = follower.first->getSpeed();
954 }
955}
956
957void
959 if (leader.first != 0) {
961 myLastLeaderSecureGap = secGap;
962 myLastLeaderSpeed = leader.first->getSpeed();
963 }
964}
965
966void
968 if (leader.first != 0) {
971 myLastOrigLeaderSpeed = leader.first->getSpeed();
972 }
973}
974
975void
985 if (!myDontResetLCGaps) {
995 }
997}
998
999void
1001 int rightmost;
1002 int leftmost;
1003 vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
1004 for (int i = rightmost; i <= leftmost; ++i) {
1005 CLeaderDist vehDist = vehicles[i];
1006 if (vehDist.first != 0) {
1007 const MSVehicle* leader = &myVehicle;
1008 const MSVehicle* follower = vehDist.first;
1009 const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
1010 if (netGap < myLastFollowerGap && netGap >= 0) {
1011 myLastFollowerGap = netGap;
1012 myLastFollowerSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
1013 myLastFollowerSpeed = follower->getSpeed();
1014 }
1015 }
1016 }
1017}
1018
1019void
1021 int rightmost;
1022 int leftmost;
1023 vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
1024 for (int i = rightmost; i <= leftmost; ++i) {
1025 CLeaderDist vehDist = vehicles[i];
1026 if (vehDist.first != 0) {
1027 const MSVehicle* leader = vehDist.first;
1028 const MSVehicle* follower = &myVehicle;
1029 const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
1030 if (netGap < myLastLeaderGap && netGap >= 0) {
1031 myLastLeaderGap = netGap;
1032 myLastLeaderSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
1033 myLastLeaderSpeed = leader->getSpeed();
1034 }
1035 }
1036 }
1037}
1038
1039void
1041 int rightmost;
1042 int leftmost;
1043 vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
1044 for (int i = rightmost; i <= leftmost; ++i) {
1045 CLeaderDist vehDist = vehicles[i];
1046 if (vehDist.first != 0) {
1047 const MSVehicle* leader = vehDist.first;
1048 const MSVehicle* follower = &myVehicle;
1049 const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
1050 if (netGap < myLastOrigLeaderGap && netGap >= 0) {
1051 myLastOrigLeaderGap = netGap;
1052 myLastOrigLeaderSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
1053 myLastOrigLeaderSpeed = leader->getSpeed();
1054 }
1055 }
1056 }
1057}
1058
1059
1060bool
1062 const int stateRight = mySavedStateRight.second;
1063 if (
1064 (stateRight & LCA_STRATEGIC) != 0
1065 && (stateRight & LCA_RIGHT) != 0
1066 && (stateRight & LCA_BLOCKED) != 0) {
1067 return true;
1068 }
1069 const int stateLeft = mySavedStateLeft.second;
1070 if (
1071 (stateLeft & LCA_STRATEGIC) != 0
1072 && (stateLeft & LCA_LEFT) != 0
1073 && (stateLeft & LCA_BLOCKED) != 0) {
1074 return true;
1075 }
1076 return false;
1077}
1078
1079double
1082}
1083
1084
1085int
1087 const int i = myVehicle.getLane()->getIndex();
1088 if (myAmOpposite) {
1090 } else {
1091 return i;
1092 }
1093}
1094
1095void
1096MSAbstractLaneChangeModel::addLCSpeedAdvice(const double vSafe, bool ownAdvice) {
1097 const double accel = SPEED2ACCEL(vSafe - myVehicle.getSpeed());
1098 myLCAccelerationAdvices.push_back({accel, ownAdvice});
1099}
1100
1101
1102void
1104 std::vector<std::string> lcState;
1106 lcState.push_back(toString(mySpeedLat));
1107 lcState.push_back(toString(myLaneChangeCompletion));
1108 lcState.push_back(toString(myLaneChangeDirection));
1109 }
1110 if (lcState.size() > 0) {
1111 out.writeAttr(SUMO_ATTR_LCSTATE, lcState);
1112 }
1113}
1114
1115void
1117 if (attrs.hasAttribute(SUMO_ATTR_LCSTATE)) {
1118 std::istringstream bis(attrs.getString(SUMO_ATTR_LCSTATE));
1119 bis >> mySpeedLat;
1121 bis >> myLaneChangeDirection;
1122 }
1123}
long long int SUMOTime
Definition: GUI.h:36
#define LC_ASSUMED_DECEL
#define DEBUG_COND
std::pair< const MSVehicle *, double > CLeaderDist
Definition: MSLeaderInfo.h:38
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:270
#define TLF(string,...)
Definition: MsgHandler.h:288
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:69
#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_NONE
@ 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_MRIGHT
@ 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_MLEFT
@ LCA_AMBLOCKINGFOLLOWER
LaneChangeModel
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_Y
@ SUMO_ATTR_X
@ SUMO_ATTR_LCA_MAXDISTLATSTANDING
@ SUMO_ATTR_LCA_MAXSPEEDLATFACTOR
@ SUMO_ATTR_LCA_MAXSPEEDLATSTANDING
@ 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:36
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MAX2(T a, T b)
Definition: StdDefs.h:82
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)
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::pair< int, int > mySavedStateLeft
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
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.
MSStop & getNextStop()
double getWidth() const
Returns the vehicle's width.
SumoRNG * getRNG() 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.
Definition: MSCFModel.cpp:277
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)
Definition: MSCFModel.cpp:166
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
Definition: MSCFModel.h:264
A device which collects info on the vehicle trip (mainly on departure and arrival)
int getNumLanes() const
Definition: MSEdge.h:172
static double gLateralResolution
Definition: MSGlobals.h:97
static bool gSublane
whether sublane simulation is enabled (sublane model or continuous lanechanging)
Definition: MSGlobals.h:160
static SUMOTime gLaneChangeDuration
Definition: MSGlobals.h:94
A lane change model developed by D. Krajzewicz between 2004 and 2010.
Definition: MSLCM_DK2008.h:37
A lane change model developed by D. Krajzewicz, J. Erdmann et al. between 2004 and 2013.
Definition: MSLCM_LC2013.h:45
A lane change model developed by J. Erdmann.
Definition: MSLCM_SL2015.h:35
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:2653
virtual void resetManeuverReservation(MSVehicle *v)
Unregisters a vehicle, which previously registered for maneuvering into this lane.
Definition: MSLane.cpp:395
const MSLink * getLinkTo(const MSLane *const) const
returns the link to the given lane or nullptr, if it is not connected
Definition: MSLane.cpp:2560
void forceVehicleInsertion(MSVehicle *veh, double pos, MSMoveReminder::Notification notification, double posLat=0)
Inserts the given vehicle at the given position.
Definition: MSLane.cpp:1295
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition: MSLane.h:579
void enteredByLaneChange(MSVehicle *v)
Definition: MSLane.cpp:3142
double getLength() const
Returns the lane's length.
Definition: MSLane.h:593
virtual double setPartialOccupation(MSVehicle *v)
Sets the information about a vehicle lapping into this lane.
Definition: MSLane.cpp:342
int getIndex() const
Returns the lane's index.
Definition: MSLane.h:629
void leftByLaneChange(MSVehicle *v)
Definition: MSLane.cpp:3135
double getOppositePos(double pos) const
return the corresponding position on the opposite lane
Definition: MSLane.cpp:4172
virtual void resetPartialOccupation(MSVehicle *v)
Removes the information about a vehicle lapping into this lane.
Definition: MSLane.cpp:361
virtual void setManeuverReservation(MSVehicle *v)
Registers the lane change intentions (towards this lane) for the given vehicle.
Definition: MSLane.cpp:384
MSLane * getParallelOpposite() const
return the opposite direction lane of this lanes edge or nullptr
Definition: MSLane.cpp:4166
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:745
double getWidth() const
Returns the lane's width.
Definition: MSLane.h:622
saves leader/follower vehicles and their distances relative to an ego vehicle
Definition: MSLeaderInfo.h:144
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:183
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:851
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...
Definition: MSVehicle.cpp:6507
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:5620
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
Definition: MSVehicle.cpp:7111
void fixPosition()
repair errors in vehicle position after changing between internal edges
Definition: MSVehicle.cpp:6314
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:517
Position getPosition(const double offset=0) const
Return current position (x/y, cartesian)
Definition: MSVehicle.cpp:1223
double lateralDistanceToLane(const int offset) const
Get the minimal lateral distance required to move fully onto the lane at given offset.
Definition: MSVehicle.cpp:6682
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.
Definition: MSVehicle.cpp:5529
void switchOffSignal(int signal)
Switches the given signal off.
Definition: MSVehicle.h:1174
@ VEH_SIGNAL_BLINKER_RIGHT
Right blinker lights are switched on.
Definition: MSVehicle.h:1113
@ VEH_SIGNAL_BLINKER_LEFT
Left blinker lights are switched on.
Definition: MSVehicle.h:1115
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:584
void enterLaneAtLaneChange(MSLane *enteredLane)
Update when the vehicle enters a new lane in the laneChange step.
Definition: MSVehicle.cpp:5324
Influencer & getInfluencer()
Definition: MSVehicle.cpp:7076
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
Definition: MSVehicle.cpp:4755
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
Definition: MSVehicle.h:416
bool congested() const
Definition: MSVehicle.cpp:1441
double getSpeed() const
Returns the vehicle's current speed.
Definition: MSVehicle.h:493
const std::vector< MSLane * > & getFurtherLanes() const
Definition: MSVehicle.h:847
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition: MSVehicle.h:978
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition: MSVehicle.h:377
double getLateralOverlap() const
return the amount by which the vehicle extends laterally outside it's primary lane
Definition: MSVehicle.cpp:6738
bool hasInfluencer() const
whether the vehicle is individually influenced (via TraCI or special parameters)
Definition: MSVehicle.h:1682
void switchOnSignal(int signal)
Switches the given signal on.
Definition: MSVehicle.h:1166
void updateDriveItems()
Check whether the drive items (myLFLinkLanes) are up to date, and update them if required.
Definition: MSVehicle.cpp:3832
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
const std::string & getID() const
Returns the name of the vehicle type.
Definition: MSVehicleType.h:91
double getMinGap() const
Get the free space in front of vehicles of this class.
double getMaxSpeedLat() const
Get vehicle's maximum lateral speed [m/s].
bool wasSet(int what) const
Returns whether the given parameter was set.
Definition: MSVehicleType.h:80
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.
Definition: OutputDevice.h:61
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
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:55
double y() const
Returns the y-position.
Definition: Position.h:60
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
Definition: RandHelper.cpp:94
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.
Definition: json.hpp:4471
#define M_PI
Definition: odrSpiral.cpp:45