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-2024 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
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());
63
64#define LC_ASSUMED_DECEL 1.0 // the minimal constant deceleration assumed to estimate the duration of a continuous lane-change at its initiation.
65
66/* -------------------------------------------------------------------------
67 * MSAbstractLaneChangeModel-methods
68 * ----------------------------------------------------------------------- */
69
70void
72 myAllowOvertakingRight = oc.getBool("lanechange.overtake-right");
73 myLCOutput = oc.isSet("lanechange-output");
74 myLCStartedOutput = oc.getBool("lanechange-output.started");
75 myLCEndedOutput = oc.getBool("lanechange-output.ended");
76 myLCXYOutput = oc.getBool("lanechange-output.xy");
77}
78
79
83 throw ProcessError(TLF("Lane change model '%' is not compatible with sublane simulation", toString(lcm)));
84 }
85 switch (lcm) {
87 return new MSLCM_DK2008(v);
89 return new MSLCM_LC2013(v);
91 return new MSLCM_LC2013_CC(v);
93 return new MSLCM_SL2015(v);
96 return new MSLCM_LC2013(v);
97 } else {
98 return new MSLCM_SL2015(v);
99 }
100 default:
101 throw ProcessError(TLF("Lane change model '%' not implemented", toString(lcm)));
102 }
103}
104
105
107 myVehicle(v),
108 myOwnState(0),
109 myPreviousState(0),
110 myPreviousState2(0),
111 myCanceledStateRight(LCA_NONE),
112 myCanceledStateCenter(LCA_NONE),
113 myCanceledStateLeft(LCA_NONE),
114 mySpeedLat(0),
115 myAccelerationLat(0),
116 myAngleOffset(0),
117 myPreviousAngleOffset(0),
118 myCommittedSpeed(0),
119 myLaneChangeCompletion(1.0),
120 myLaneChangeDirection(0),
121 myAlreadyChanged(false),
122 myShadowLane(nullptr),
123 myTargetLane(nullptr),
124 myModel(model),
125 myLastLateralGapLeft(0.),
126 myLastLateralGapRight(0.),
127 myLastLeaderGap(0.),
128 myLastFollowerGap(0.),
129 myLastLeaderSecureGap(0.),
130 myLastFollowerSecureGap(0.),
131 myLastOrigLeaderGap(0.),
132 myLastOrigLeaderSecureGap(0.),
133 myLastLeaderSpeed(0),
134 myLastFollowerSpeed(0),
135 myLastOrigLeaderSpeed(0),
136 myDontResetLCGaps(false),
137 myMaxSpeedLatStanding(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING, v.getVehicleType().getMaxSpeedLat())),
138 myMaxSpeedLatFactor(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR, 1)),
139 myMaxDistLatStanding(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXDISTLATSTANDING,
140 // prevent lateral sliding for cars but permit for two-wheelers due to better maneuverability
141 (v.getVClass() & (SVC_BICYCLE | SVC_MOTORCYCLE | SVC_MOPED)) != 0 ? std::numeric_limits<double>::max() : 1.6)),
142 mySigma(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SIGMA, 0.0)),
143 myOvertakeRightParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_OVERTAKE_RIGHT, 0)),
144 myHaveBlueLight(v.getDevice(typeid(MSDevice_Bluelight)) != nullptr), // see MSVehicle::initDevices
145 myLastLaneChangeOffset(0),
146 myAmOpposite(false),
147 myManeuverDist(0.),
148 myPreviousManeuverDist(0.) {
152}
153
154
157
158void
161 myOwnState = state;
162 myPreviousState = state; // myOwnState is modified in prepareStep so we make a backup
163}
164
165void
166MSAbstractLaneChangeModel::updateSafeLatDist(const double travelledLatDist) {
167 UNUSED_PARAMETER(travelledLatDist);
168}
169
170
171void
173#ifdef DEBUG_MANEUVER
174 if (DEBUG_COND) {
175 std::cout << SIMTIME
176 << " veh=" << myVehicle.getID()
177 << " setManeuverDist() old=" << myManeuverDist << " new=" << dist
178 << std::endl;
179 }
180#endif
181 myManeuverDist = fabs(dist) < NUMERICAL_EPS ? 0. : dist;
182 // store value which may be modified by the model during the next step
184}
185
186
187double
191
192double
196
197void
199 if (dir == -1) {
200 myLeftFollowers = std::make_shared<MSLeaderDistanceInfo>(followers);
201 myLeftLeaders = std::make_shared<MSLeaderDistanceInfo>(leaders);
202 } else if (dir == 1) {
203 myRightFollowers = std::make_shared<MSLeaderDistanceInfo>(followers);
204 myRightLeaders = std::make_shared<MSLeaderDistanceInfo>(leaders);
205 } else {
206 // dir \in {-1,1} !
207 assert(false);
208 }
209}
210
211
212void
213MSAbstractLaneChangeModel::saveNeighbors(const int dir, const std::pair<MSVehicle* const, double>& follower, const std::pair<MSVehicle* const, double>& leader) {
214 if (dir == -1) {
215 myLeftFollowers = std::make_shared<MSLeaderDistanceInfo>(follower, myVehicle.getLane()->getWidth());
216 myLeftLeaders = std::make_shared<MSLeaderDistanceInfo>(leader, myVehicle.getLane()->getWidth());
217 } else if (dir == 1) {
218 myRightFollowers = std::make_shared<MSLeaderDistanceInfo>(follower, myVehicle.getLane()->getWidth());
219 myRightLeaders = std::make_shared<MSLeaderDistanceInfo>(leader, myVehicle.getLane()->getWidth());
220 } else {
221 // dir \in {-1,1} !
222 assert(false);
223 }
224}
225
226
227void
229 myLeftFollowers = nullptr;
230 myLeftLeaders = nullptr;
231 myRightFollowers = nullptr;
232 myRightLeaders = nullptr;
233}
234
235
236const std::shared_ptr<MSLeaderDistanceInfo>
238 if (dir == -1) {
239 return myLeftFollowers;
240 } else if (dir == 1) {
241 return myRightFollowers;
242 } else {
243 // dir \in {-1,1} !
244 assert(false);
245 }
246 return nullptr;
247}
248
249const std::shared_ptr<MSLeaderDistanceInfo>
251 if (dir == -1) {
252 return myLeftLeaders;
253 } else if (dir == 1) {
254 return myRightLeaders;
255 } else {
256 // dir \in {-1,1} !
257 assert(false);
258 }
259 return nullptr;
260}
261
262
263bool
265 if (neighLeader == nullptr) {
266 return false;
267 }
268 // Congested situation are relevant only on highways (maxSpeed > 70km/h)
269 // and congested on German Highways means that the vehicles have speeds
270 // below 60km/h. Overtaking on the right is allowed then.
271 if ((myVehicle.getLane()->getSpeedLimit() <= 70.0 / 3.6) || (neighLeader->getLane()->getSpeedLimit() <= 70.0 / 3.6)) {
272
273 return false;
274 }
275 if (myVehicle.congested() && neighLeader->congested()) {
276 return true;
277 }
278 return false;
279}
280
281
282bool
289
290bool
291MSAbstractLaneChangeModel::predInteraction(const std::pair<MSVehicle*, double>& leader) {
292 if (leader.first == 0) {
293 return false;
294 }
295 // let's check it on highways only
296 if (leader.first->getSpeed() < (80.0 / 3.6)) {
297 return false;
298 }
299 return leader.second < getCarFollowModel().interactionGap(&myVehicle, leader.first->getSpeed());
300}
301
302
303bool
307 myLaneChangeDirection = direction;
308 setManeuverDist((target->getWidth() + source->getWidth()) * 0.5 * direction);
311 if (myLCOutput) {
313 }
314 return true;
315 } else {
316 primaryLaneChanged(source, target, direction);
317 return false;
318 }
319}
320
321void
325
326void
330
331void
333 initLastLaneChangeOffset(direction);
335 source->leftByLaneChange(&myVehicle);
336 laneChangeOutput("change", source, target, direction); // record position on the source edge in case of opposite change
337 if (&source->getEdge() != &target->getEdge()) {
339#ifdef DEBUG_OPPOSITE
340 if (debugVehicle()) {
341 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " primaryLaneChanged source=" << source->getID() << " target=" << target->getID() << " nowOpposite=" << myAmOpposite << "\n";
342 }
343#endif
346 } else if (myAmOpposite) {
347#ifdef DEBUG_OPPOSITE
348 if (debugVehicle()) {
349 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " primaryLaneChanged source=" << source->getID() << " target=" << target->getID() << " stayOpposite\n";
350 }
351#endif
352 myAlreadyChanged = true;
354 if (!MSGlobals::gSublane) {
355 // in the continous case, the vehicle is added to the target lane via MSLaneChanger::continueChange / registerHop
356 // in the sublane case, the vehicle is added to the target lane via MSLaneChangerSublane::checkChangeOppositeSublane / MSLane::myTmpVehicles
358 }
359 } else {
362 }
363 // Assure that the drive items are up to date (even if the following step is no actionstep for the vehicle).
364 // This is necessary because the lane advance uses the target lane from the corresponding drive item.
366 changed();
367}
368
369void
370MSAbstractLaneChangeModel::laneChangeOutput(const std::string& tag, MSLane* source, MSLane* target, int direction, double maneuverDist) {
371 if (myLCOutput) {
372 OutputDevice& of = OutputDevice::getDeviceByOption("lanechange-output");
373 of.openTag(tag);
376 of.writeAttr(SUMO_ATTR_TIME, time2string(MSNet::getInstance()->getCurrentTimeStep()));
377 of.writeAttr(SUMO_ATTR_FROM, source->getID());
378 of.writeAttr(SUMO_ATTR_TO, target->getID());
379 of.writeAttr(SUMO_ATTR_DIR, direction);
387 of.writeAttr("leaderGap", myLastLeaderGap == NO_NEIGHBOR ? "None" : toString(myLastLeaderGap));
388 of.writeAttr("leaderSecureGap", myLastLeaderSecureGap == NO_NEIGHBOR ? "None" : toString(myLastLeaderSecureGap));
389 of.writeAttr("leaderSpeed", myLastLeaderSpeed == NO_NEIGHBOR ? "None" : toString(myLastLeaderSpeed));
390 of.writeAttr("followerGap", myLastFollowerGap == NO_NEIGHBOR ? "None" : toString(myLastFollowerGap));
391 of.writeAttr("followerSecureGap", myLastFollowerSecureGap == NO_NEIGHBOR ? "None" : toString(myLastFollowerSecureGap));
392 of.writeAttr("followerSpeed", myLastFollowerSpeed == NO_NEIGHBOR ? "None" : toString(myLastFollowerSpeed));
393 of.writeAttr("origLeaderGap", myLastOrigLeaderGap == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderGap));
394 of.writeAttr("origLeaderSecureGap", myLastOrigLeaderSecureGap == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderSecureGap));
395 of.writeAttr("origLeaderSpeed", myLastOrigLeaderSpeed == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderSpeed));
397 const double latGap = direction < 0 ? myLastLateralGapRight : myLastLateralGapLeft;
398 of.writeAttr("latGap", latGap == NO_NEIGHBOR ? "None" : toString(latGap));
399 if (maneuverDist != 0) {
400 of.writeAttr("maneuverDistance", toString(maneuverDist));
401 }
402 }
403 if (myLCXYOutput) {
406 }
407 of.closeTag();
410 }
411 }
412}
413
414
415double
416MSAbstractLaneChangeModel::computeSpeedLat(double /*latDist*/, double& maneuverDist, bool /*urgent*/) const {
418 int stepsToChange = (int)ceil(fabs(maneuverDist) / SPEED2DIST(myVehicle.getVehicleType().getMaxSpeedLat()));
419 return DIST2SPEED(maneuverDist / stepsToChange);
420 } else {
421 return maneuverDist / STEPS2TIME(MSGlobals::gLaneChangeDuration);
422 }
423}
424
425
426double
430
431void
434 mySpeedLat = speedLat;
435}
436
437
438void
444
445
446bool
448 const bool pastBefore = pastMidpoint();
449 // maneuverDist is not updated in the context of continuous lane changing but represents the full LC distance
450 double maneuverDist = getManeuverDist();
451 setSpeedLat(computeSpeedLat(0, maneuverDist, (myOwnState & LCA_URGENT) != 0));
453 return !pastBefore && pastMidpoint();
454}
455
456
457void
459 UNUSED_PARAMETER(reason);
468 // opposite driving continues after parking
469 } else {
470 // aborted maneuver
471#ifdef DEBUG_OPPOSITE
472 if (debugVehicle()) {
473 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " aborted maneuver (no longer opposite)\n";
474 }
475#endif
477 }
478 }
479}
480
481
482MSLane*
483MSAbstractLaneChangeModel::getShadowLane(const MSLane* lane, double posLat) const {
485 // initialize shadow lane
486 const double overlap = myVehicle.getLateralOverlap(posLat, lane);
487#ifdef DEBUG_SHADOWLANE
488 if (debugVehicle()) {
489 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " posLat=" << posLat << " overlap=" << overlap << "\n";
490 }
491#endif
492 if (myAmOpposite) {
493 // return the neigh-lane in forward direction
494 return lane->getParallelLane(1);
495 } else if (overlap > NUMERICAL_EPS) {
496 const int shadowDirection = posLat < 0 ? -1 : 1;
497 return lane->getParallelLane(shadowDirection);
498 } else if (isChangingLanes() && myLaneChangeCompletion < 0.5) {
499 // "reserve" target lane even when there is no overlap yet
501 } else {
502 return nullptr;
503 }
504 } else {
505 return nullptr;
506 }
507}
508
509
510MSLane*
514
515
516void
518 if (myShadowLane != nullptr) {
519 if (debugVehicle()) {
520 std::cout << SIMTIME << " cleanupShadowLane\n";
521 }
523 myShadowLane = nullptr;
524 }
525 for (std::vector<MSLane*>::const_iterator it = myShadowFurtherLanes.begin(); it != myShadowFurtherLanes.end(); ++it) {
526 if (debugVehicle()) {
527 std::cout << SIMTIME << " cleanupShadowLane2\n";
528 }
530 }
531 myShadowFurtherLanes.clear();
533}
534
535void
537 if (myTargetLane != nullptr) {
538 if (debugVehicle()) {
539 std::cout << SIMTIME << " cleanupTargetLane\n";
540 }
542 myTargetLane = nullptr;
543 }
544 for (std::vector<MSLane*>::const_iterator it = myFurtherTargetLanes.begin(); it != myFurtherTargetLanes.end(); ++it) {
545 if (debugVehicle()) {
546 std::cout << SIMTIME << " cleanupTargetLane\n";
547 }
548 if (*it != nullptr) {
550 }
551 }
552 myFurtherTargetLanes.clear();
553// myNoPartiallyOccupatedByShadow.clear();
554}
555
556
557bool
559 // store request before canceling
560 getCanceledState(laneOffset) |= state;
561 int ret = myVehicle.influenceChangeDecision(state);
562 return ret != state;
563}
564
565double
569
570void
572 if (dir > 0) {
574 } else if (dir < 0) {
576 }
577}
578
579void
581 if (!MSGlobals::gSublane) {
582 // assume each vehicle drives at the center of its lane and act as if it fits
583 return;
584 }
585 if (myShadowLane != nullptr) {
586#ifdef DEBUG_SHADOWLANE
587 if (debugVehicle()) {
588 std::cout << SIMTIME << " updateShadowLane()\n";
589 }
590#endif
592 }
594 std::vector<MSLane*> passed;
595 if (myShadowLane != nullptr) {
597 const std::vector<MSLane*>& further = myVehicle.getFurtherLanes();
598 if (myAmOpposite) {
599 assert(further.size() == 0);
600 } else {
601 const std::vector<double>& furtherPosLat = myVehicle.getFurtherLanesPosLat();
602 assert(further.size() == furtherPosLat.size());
603 passed.push_back(myShadowLane);
604 for (int i = 0; i < (int)further.size(); ++i) {
605 MSLane* shadowFurther = getShadowLane(further[i], furtherPosLat[i]);
606#ifdef DEBUG_SHADOWLANE
607 if (debugVehicle()) {
608 std::cout << SIMTIME << " further=" << further[i]->getID() << " (posLat=" << furtherPosLat[i] << ") shadowFurther=" << Named::getIDSecure(shadowFurther) << "\n";
609 }
610#endif
611 if (shadowFurther != nullptr && shadowFurther->getLinkTo(passed.back()) != nullptr) {
612 passed.push_back(shadowFurther);
613 }
614 }
615 std::reverse(passed.begin(), passed.end());
616 }
617 } else {
618 if (isChangingLanes() && myVehicle.getLateralOverlap() > NUMERICAL_EPS) {
619 WRITE_WARNING("Vehicle '" + myVehicle.getID() + "' could not finish continuous lane change (lane disappeared) time=" +
620 time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
622 }
623 }
624#ifdef DEBUG_SHADOWLANE
625 if (debugVehicle()) {
626 std::cout << SIMTIME << " updateShadowLane() veh=" << myVehicle.getID()
627 << " newShadowLane=" << Named::getIDSecure(myShadowLane)
628 << "\n before:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << " further=" << toString(myVehicle.getFurtherLanes()) << " passed=" << toString(passed);
629 std::cout << std::endl;
630 }
631#endif
633#ifdef DEBUG_SHADOWLANE
634 if (debugVehicle()) std::cout
635 << "\n after:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << "\n";
636#endif
637}
638
639
640int
642 if (isChangingLanes()) {
643 if (pastMidpoint()) {
644 return -myLaneChangeDirection;
645 } else {
647 }
648 } else if (myShadowLane == nullptr) {
649 return 0;
650 } else if (myAmOpposite) {
651 // return neigh-lane in forward direction
652 return 1;
653 } else if (&myShadowLane->getEdge() == &myVehicle.getLane()->getEdge()) {
655 } else {
656 // overlap with opposite direction lane
657 return 1;
658 }
659}
660
661
662MSLane*
664#ifdef DEBUG_TARGET_LANE
665 MSLane* oldTarget = myTargetLane;
666 std::vector<MSLane*> oldFurtherTargets = myFurtherTargetLanes;
667 if (debugVehicle()) {
668 std::cout << SIMTIME << " veh '" << myVehicle.getID() << "' (lane=" << myVehicle.getLane()->getID() << ") updateTargetLane()"
669 << "\n oldTarget: " << (oldTarget == nullptr ? "NULL" : oldTarget->getID())
670 << " oldFurtherTargets: " << toString(oldFurtherTargets);
671 }
672#endif
673 if (myTargetLane != nullptr) {
675 }
676 // Clear old further target lanes
677 for (MSLane* oldTargetLane : myFurtherTargetLanes) {
678 if (oldTargetLane != nullptr) {
679 oldTargetLane->resetManeuverReservation(&myVehicle);
680 }
681 }
682 myFurtherTargetLanes.clear();
683
684 // Get new target lanes and issue a maneuver reservation.
685 int targetDir;
687 if (myTargetLane != nullptr) {
689 // further targets are just the target lanes corresponding to the vehicle's further lanes
690 // @note In a neglectable amount of situations we might add a reservation for a shadow further lane.
691 for (MSLane* furtherLane : myVehicle.getFurtherLanes()) {
692 MSLane* furtherTargetLane = furtherLane->getParallelLane(targetDir);
693 myFurtherTargetLanes.push_back(furtherTargetLane);
694 if (furtherTargetLane != nullptr) {
695 furtherTargetLane->setManeuverReservation(&myVehicle);
696 }
697 }
698 }
699#ifdef DEBUG_TARGET_LANE
700 if (debugVehicle()) {
701 std::cout << "\n newTarget (maneuverDist=" << myManeuverDist << " offset=" << targetDir << "): " << (myTargetLane == nullptr ? "NULL" : myTargetLane->getID())
702 << " newFurtherTargets: " << toString(myFurtherTargetLanes)
703 << std::endl;
704 }
705#endif
706 return myTargetLane;
707}
708
709
710MSLane*
712 targetDir = 0;
713 if (myManeuverDist == 0) {
714 return nullptr;
715 }
716 // Current lateral boundaries of the vehicle
717 const double vehRight = myVehicle.getLateralPositionOnLane() - 0.5 * myVehicle.getWidth();
718 const double vehLeft = myVehicle.getLateralPositionOnLane() + 0.5 * myVehicle.getWidth();
719 const double halfLaneWidth = 0.5 * myVehicle.getLane()->getWidth();
720
721 if (vehRight + myManeuverDist < -halfLaneWidth) {
722 // Vehicle intends to traverse the right lane boundary
723 targetDir = -1;
724 } else if (vehLeft + myManeuverDist > halfLaneWidth) {
725 // Vehicle intends to traverse the left lane boundary
726 targetDir = 1;
727 }
728 if (targetDir == 0) {
729 // Presently, no maneuvering into another lane is begun.
730 return nullptr;
731 }
732 MSLane* target = myVehicle.getLane()->getParallelLane(targetDir);
733 if (target == nullptr || target == myShadowLane) {
734 return nullptr;
735 } else {
736 return target;
737 }
738}
739
740
741
742double
744 double result = 0.;
745 if (!(fabs(mySpeedLat) < NUMERICAL_EPS && fabs(myPreviousAngleOffset * 180 / M_PI) < NUMERICAL_EPS)) {
747 result = atan2(mySpeedLat, myVehicle.getSpeed());
748 } else {
750 }
751 }
752
753 myAngleOffset = result;
754 return result;
755}
756
757
758double
759MSAbstractLaneChangeModel::estimateLCDuration(const double speed, const double remainingManeuverDist, const double decel, bool urgent) const {
760
762 if (lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING) == lcParams.end() && lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR) == lcParams.end()) {
764 // no dependency of lateral speed on longitudinal speed. (Only called prior to LC initialization to determine whether it could be completed)
766 } else {
767 return remainingManeuverDist / myVehicle.getVehicleType().getMaxSpeedLat();
768 }
769 }
770
771 if (remainingManeuverDist == 0) {
772 return 0;
773 }
774
775 // Check argument assumptions
776 assert(speed >= 0);
777 assert(remainingManeuverDist >= 0);
778 assert(decel > 0);
781 assert(myMaxSpeedLatStanding >= 0);
782
783 // for brevity
784 const double v0 = speed;
785 const double D = remainingManeuverDist;
786 const double b = decel;
787 const double wmin = myMaxSpeedLatStanding;
788 const double f = myMaxSpeedLatFactor;
789 const double wmax = myVehicle.getVehicleType().getMaxSpeedLat();
790
791 /* Here's the approach for the calculation of the required time for the LC:
792 * To obtain the maximal LC-duration, for v(t) we assume that v(t)=max(0, v0-b*t),
793 * Where v(t)=0 <=> t >= ts:=v0/b
794 * For the lateral speed w(t) this gives:
795 * w(t) = min(wmax, wmin + f*v(t))
796 * The lateral distance covered until t is
797 * d(t) = int_0^t w(s) ds
798 * We distinguish three possibilities for the solution d(T)=D, where T is the time of the LC completion.
799 * 1) w(T) = wmax, i.e. v(T)>(wmax-wmin)/f
800 * 2) wmin < w(T) < wmax, i.e. (wmax-wmin)/f > v(T) > 0
801 * 3) w(T) = wmin, i.e., v(T)=0
802 */
803 const double vm = (wmax - wmin) / f;
804 double distSoFar = 0.;
805 double timeSoFar = 0.;
806 double v = v0;
807 if (v > vm) {
808 const double wmaxTime = (v0 - vm) / b;
809 const double d1 = wmax * wmaxTime;
810 if (d1 >= D) {
811 return D / wmax;
812 } else {
813 distSoFar += d1;
814 timeSoFar += wmaxTime;
815 v = vm;
816 }
817 }
818 if (v > 0) {
819 /* Here, w(t1+t) = wmin + f*v(t1+t) = wmin + f*(v - b*t)
820 * Thus, the additional lateral distance covered after time t is:
821 * d2 = (wmin + f*v)*t - 0.5*f*b*t^2
822 * and the additional lateral distance covered until v=0 at t=v/b is:
823 * d2 = (wmin + 0.5*f*v)*t
824 */
825 const double t = v / b; // stop time
826 const double d2 = (wmin + 0.5 * f * v) * t; // lateral distance covered until stop
827 assert(d2 > 0);
828 if (distSoFar + d2 >= D) {
829 // LC is completed during this phase
830 const double x = 0.5 * f * b;
831 const double y = wmin + f * v;
832 /* Solve D - distSoFar = y*t - x*t^2.
833 * 0 = x*t^2 - y*t/x + (D - distSoFar)/x
834 */
835 const double p = 0.5 * y / x;
836 const double q = (D - distSoFar) / x;
837 assert(p * p - q > 0);
838 const double t2 = p + sqrt(p * p - q);
839 return timeSoFar + t2;
840 } else {
841 distSoFar += d2;
842 timeSoFar += t;
843 //v = 0;
844 }
845 }
846 // If we didn't return yet this means the LC was not completed until the vehicle stops (if braking with rate b)
847 if (wmin == 0) {
848 // LC won't be completed if vehicle stands
849 double maneuverDist = remainingManeuverDist;
850 const double vModel = computeSpeedLat(maneuverDist, maneuverDist, urgent);
851 double result = D / vModel;
852 // make sure that the vehicle isn't braking to a stop during the manuever
853 if (vModel > SUMO_const_haltingSpeed && (vModel + myVehicle.getAcceleration() * result) > SUMO_const_haltingSpeed) {
854 // unless the model tells us something different
855 return result;
856 } else {
857 return -1;
858 }
859 } else {
860 // complete LC with lateral speed wmin
861 return timeSoFar + (D - distSoFar) / wmin;
862 }
863}
864
867 assert(isChangingLanes()); // Only to be called during ongoing lane change
869 if (lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING) == lcParams.end() && lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR) == lcParams.end()) {
872 } else {
874 }
875 }
876 // Using maxSpeedLat(Factor/Standing)
877 const bool urgent = (myOwnState & LCA_URGENT) != 0;
881}
882
883
884void
886 //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " set shadow approaching=" << link->getViaLaneOrLane()->getID() << "\n";
887 myApproachedByShadow.push_back(link);
888}
889
890void
892 for (std::vector<MSLink*>::iterator it = myApproachedByShadow.begin(); it != myApproachedByShadow.end(); ++it) {
893 //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " remove shadow approaching=" << (*it)->getViaLaneOrLane()->getID() << "\n";
894 (*it)->removeApproaching(&myVehicle);
895 }
896 myApproachedByShadow.clear();
897}
898
899
900
901void
904 int oldstate = myVehicle.getLaneChangeModel().getOwnState();
905 if (myOwnState != newstate) {
907 // Calculate and set the lateral maneuver distance corresponding to the change request
908 // to induce a corresponding sublane change.
909 const int dir = (newstate & LCA_RIGHT) != 0 ? -1 : ((newstate & LCA_LEFT) != 0 ? 1 : 0);
910 // minimum distance to move the vehicle fully onto the lane at offset dir
911 const double latLaneDist = myVehicle.lateralDistanceToLane(dir);
912 if ((newstate & LCA_TRACI) != 0) {
913 if ((newstate & LCA_STAY) != 0) {
914 setManeuverDist(0.);
915 } else if (((newstate & LCA_RIGHT) != 0 && dir < 0)
916 || ((newstate & LCA_LEFT) != 0 && dir > 0)) {
917 setManeuverDist(latLaneDist);
918 }
919 }
920 if (myVehicle.hasInfluencer()) {
921 // lane change requests override sublane change requests
923 }
924
925 }
926 setOwnState(newstate);
927 } else {
928 // Check for sublane change requests
930 const double maneuverDist = myVehicle.getInfluencer().getLatDist();
933 newstate |= LCA_TRACI;
934 if (myOwnState != newstate) {
935 setOwnState(newstate);
936 }
937 if (gDebugFlag2) {
938 std::cout << " traci influenced maneuverDist=" << maneuverDist << "\n";
939 }
940 }
941 }
942 if (gDebugFlag2) {
943 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " stateAfterTraCI=" << toString((LaneChangeAction)newstate) << " original=" << toString((LaneChangeAction)oldstate) << "\n";
944 }
945}
946
947void
952
953void
955 if (follower.first != 0) {
956 myLastFollowerGap = follower.second + follower.first->getVehicleType().getMinGap();
958 myLastFollowerSpeed = follower.first->getSpeed();
959 }
960}
961
962void
964 if (leader.first != 0) {
966 myLastLeaderSecureGap = secGap;
967 myLastLeaderSpeed = leader.first->getSpeed();
968 }
969}
970
971void
973 if (leader.first != 0) {
976 myLastOrigLeaderSpeed = leader.first->getSpeed();
977 }
978}
979
980void
1003
1004void
1006 int rightmost;
1007 int leftmost;
1008 vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
1009 for (int i = rightmost; i <= leftmost; ++i) {
1010 CLeaderDist vehDist = vehicles[i];
1011 if (vehDist.first != 0) {
1012 const MSVehicle* leader = &myVehicle;
1013 const MSVehicle* follower = vehDist.first;
1014 const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
1015 if (netGap < myLastFollowerGap && netGap >= 0) {
1016 myLastFollowerGap = netGap;
1017 myLastFollowerSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
1018 myLastFollowerSpeed = follower->getSpeed();
1019 }
1020 }
1021 }
1022}
1023
1024void
1026 int rightmost;
1027 int leftmost;
1028 vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
1029 for (int i = rightmost; i <= leftmost; ++i) {
1030 CLeaderDist vehDist = vehicles[i];
1031 if (vehDist.first != 0) {
1032 const MSVehicle* leader = vehDist.first;
1033 const MSVehicle* follower = &myVehicle;
1034 const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
1035 if (netGap < myLastLeaderGap && netGap >= 0) {
1036 myLastLeaderGap = netGap;
1037 myLastLeaderSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
1038 myLastLeaderSpeed = leader->getSpeed();
1039 }
1040 }
1041 }
1042}
1043
1044void
1046 int rightmost;
1047 int leftmost;
1048 vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
1049 for (int i = rightmost; i <= leftmost; ++i) {
1050 CLeaderDist vehDist = vehicles[i];
1051 if (vehDist.first != 0) {
1052 const MSVehicle* leader = vehDist.first;
1053 const MSVehicle* follower = &myVehicle;
1054 const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
1055 if (netGap < myLastOrigLeaderGap && netGap >= 0) {
1056 myLastOrigLeaderGap = netGap;
1057 myLastOrigLeaderSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
1058 myLastOrigLeaderSpeed = leader->getSpeed();
1059 }
1060 }
1061 }
1062}
1063
1064
1065bool
1067 const int stateRight = mySavedStateRight.second;
1068 if (
1069 (stateRight & LCA_STRATEGIC) != 0
1070 && (stateRight & LCA_RIGHT) != 0
1071 && (stateRight & LCA_BLOCKED) != 0) {
1072 return true;
1073 }
1074 const int stateLeft = mySavedStateLeft.second;
1075 if (
1076 (stateLeft & LCA_STRATEGIC) != 0
1077 && (stateLeft & LCA_LEFT) != 0
1078 && (stateLeft & LCA_BLOCKED) != 0) {
1079 return true;
1080 }
1081 return false;
1082}
1083
1084double
1088
1089
1090int
1092 const int i = myVehicle.getLane()->getIndex();
1093 if (myAmOpposite) {
1095 } else {
1096 return i;
1097 }
1098}
1099
1100void
1101MSAbstractLaneChangeModel::addLCSpeedAdvice(const double vSafe, bool ownAdvice) {
1102 const double accel = SPEED2ACCEL(vSafe - myVehicle.getSpeed());
1103 myLCAccelerationAdvices.push_back({accel, ownAdvice});
1104}
1105
1106
1107void
1109 std::vector<std::string> lcState;
1111 lcState.push_back(toString(mySpeedLat));
1112 lcState.push_back(toString(myLaneChangeCompletion));
1113 lcState.push_back(toString(myLaneChangeDirection));
1114 }
1115 if (lcState.size() > 0) {
1116 out.writeAttr(SUMO_ATTR_LCSTATE, lcState);
1117 }
1118}
1119
1120void
1122 if (attrs.hasAttribute(SUMO_ATTR_LCSTATE)) {
1123 std::istringstream bis(attrs.getString(SUMO_ATTR_LCSTATE));
1124 bis >> mySpeedLat;
1126 bis >> myLaneChangeDirection;
1127 }
1128}
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:295
#define TLF(string,...)
Definition MsgHandler.h:317
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_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_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:38
#define UNUSED_PARAMETER(x)
Definition StdDefs.h:30
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition StdDefs.h:58
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::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.
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: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: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:2773
virtual void resetManeuverReservation(MSVehicle *v)
Unregisters a vehicle, which previously registered for maneuvering into this lane.
Definition MSLane.cpp:427
const MSLink * getLinkTo(const MSLane *const) const
returns the link to the given lane or nullptr, if it is not connected
Definition MSLane.cpp:2668
void forceVehicleInsertion(MSVehicle *veh, double pos, MSMoveReminder::Notification notification, double posLat=0)
Inserts the given vehicle at the given position.
Definition MSLane.cpp:1348
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition MSLane.h:592
void enteredByLaneChange(MSVehicle *v)
Definition MSLane.cpp:3278
double getLength() const
Returns the lane's length.
Definition MSLane.h:606
virtual double setPartialOccupation(MSVehicle *v)
Sets the information about a vehicle lapping into this lane.
Definition MSLane.cpp:374
int getIndex() const
Returns the lane's index.
Definition MSLane.h:642
void leftByLaneChange(MSVehicle *v)
Definition MSLane.cpp:3271
double getOppositePos(double pos) const
return the corresponding position on the opposite lane
Definition MSLane.cpp:4311
virtual void resetPartialOccupation(MSVehicle *v)
Removes the information about a vehicle lapping into this lane.
Definition MSLane.cpp:393
virtual void setManeuverReservation(MSVehicle *v)
Registers the lane change intentions (towards this lane) for the given vehicle.
Definition MSLane.cpp:416
MSLane * getParallelOpposite() const
return the opposite direction lane of this lanes edge or nullptr
Definition MSLane.cpp:4305
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:764
double getWidth() const
Returns the lane's width.
Definition MSLane.h:635
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:185
bool isOpposite
whether this an opposite-direction stop
Definition MSStop.h:87
double getLatDist() const
Definition MSVehicle.h:1584
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:1169
@ VEH_SIGNAL_BLINKER_RIGHT
Right blinker lights are switched on.
Definition MSVehicle.h:1108
@ VEH_SIGNAL_BLINKER_LEFT
Left blinker lights are switched on.
Definition MSVehicle.h:1110
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:1680
void switchOnSignal(int signal)
Switches the given signal on.
Definition MSVehicle.h:1161
void updateDriveItems()
Check whether the drive items (myLFLinkLanes) are up to date, and update them if required.
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: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)
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 DEBUG_COND
Definition json.hpp:4471
#define M_PI
Definition odrSpiral.cpp:45