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.org/sumo
3// Copyright (C) 2001-2022 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
39#include <microsim/MSNet.h>
40#include <microsim/MSEdge.h>
41#include <microsim/MSLane.h>
42#include <microsim/MSLink.h>
43#include <microsim/MSStop.h>
45#include <microsim/MSGlobals.h>
47#include "MSLCM_DK2008.h"
48#include "MSLCM_LC2013.h"
49#include "MSLCM_SL2015.h"
51
52/* -------------------------------------------------------------------------
53 * static members
54 * ----------------------------------------------------------------------- */
60const double MSAbstractLaneChangeModel::NO_NEIGHBOR(std::numeric_limits<double>::max());
61
62/* -------------------------------------------------------------------------
63 * MSAbstractLaneChangeModel-methods
64 * ----------------------------------------------------------------------- */
65
66void
68 myAllowOvertakingRight = oc.getBool("lanechange.overtake-right");
69 myLCOutput = oc.isSet("lanechange-output");
70 myLCStartedOutput = oc.getBool("lanechange-output.started");
71 myLCEndedOutput = oc.getBool("lanechange-output.ended");
72 myLCXYOutput = oc.getBool("lanechange-output.xy");
73}
74
75
79 throw ProcessError("Lane change model '" + toString(lcm) + "' is not compatible with sublane simulation");
80 }
81 switch (lcm) {
83 return new MSLCM_DK2008(v);
85 return new MSLCM_LC2013(v);
87 return new MSLCM_SL2015(v);
90 return new MSLCM_LC2013(v);
91 } else {
92 return new MSLCM_SL2015(v);
93 }
94 default:
95 throw ProcessError("Lane change model '" + toString(lcm) + "' not implemented");
96 }
97}
98
99
101 myVehicle(v),
102 myOwnState(0),
103 myPreviousState(0),
104 myPreviousState2(0),
105 myCanceledStateRight(LCA_NONE),
106 myCanceledStateCenter(LCA_NONE),
107 myCanceledStateLeft(LCA_NONE),
108 mySpeedLat(0),
109 myAccelerationLat(0),
110 myCommittedSpeed(0),
111 myLaneChangeCompletion(1.0),
112 myLaneChangeDirection(0),
113 myAlreadyChanged(false),
114 myShadowLane(nullptr),
115 myTargetLane(nullptr),
116 myModel(model),
117 myLastLateralGapLeft(0.),
118 myLastLateralGapRight(0.),
119 myLastLeaderGap(0.),
120 myLastFollowerGap(0.),
121 myLastLeaderSecureGap(0.),
122 myLastFollowerSecureGap(0.),
123 myLastOrigLeaderGap(0.),
124 myLastOrigLeaderSecureGap(0.),
125 myLastLeaderSpeed(0),
126 myLastFollowerSpeed(0),
127 myLastOrigLeaderSpeed(0),
128 myDontResetLCGaps(false),
129 myMaxSpeedLatStanding(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING, v.getVehicleType().getMaxSpeedLat())),
130 myMaxSpeedLatFactor(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR, 1)),
131 myMaxDistLatStanding(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXDISTLATSTANDING,
132 // prevent lateral sliding for cars but permit for two-wheelers due to better maneuverability
133 (v.getVClass() & (SVC_BICYCLE | SVC_MOTORCYCLE | SVC_MOPED)) != 0 ? std::numeric_limits<double>::max() : 1.6)),
134 mySigma(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SIGMA, 0.0)),
135 myOvertakeRightParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_OVERTAKE_RIGHT, 0)),
136 myHaveBlueLight(v.getDevice(typeid(MSDevice_Bluelight)) != nullptr), // see MSVehicle::initDevices
137 myLastLaneChangeOffset(0),
138 myAmOpposite(false),
139 myManeuverDist(0.),
140 myPreviousManeuverDist(0.) {
144}
145
146
148}
149
150void
153 myOwnState = state;
154 myPreviousState = state; // myOwnState is modified in prepareStep so we make a backup
155}
156
157void
158MSAbstractLaneChangeModel::updateSafeLatDist(const double travelledLatDist) {
159 UNUSED_PARAMETER(travelledLatDist);
160}
161
162
163void
165#ifdef DEBUG_MANEUVER
166 if (DEBUG_COND) {
167 std::cout << SIMTIME
168 << " veh=" << myVehicle.getID()
169 << " setManeuverDist() old=" << myManeuverDist << " new=" << dist
170 << std::endl;
171 }
172#endif
173 myManeuverDist = fabs(dist) < NUMERICAL_EPS ? 0. : dist;
174 // store value which may be modified by the model during the next step
176}
177
178
179double
181 return myManeuverDist;
182}
183
184double
187}
188
189void
191 if (dir == -1) {
192 myLeftFollowers = std::make_shared<MSLeaderDistanceInfo>(followers);
193 myLeftLeaders = std::make_shared<MSLeaderDistanceInfo>(leaders);
194 } else if (dir == 1) {
195 myRightFollowers = std::make_shared<MSLeaderDistanceInfo>(followers);
196 myRightLeaders = std::make_shared<MSLeaderDistanceInfo>(leaders);
197 } else {
198 // dir \in {-1,1} !
199 assert(false);
200 }
201}
202
203
204void
205MSAbstractLaneChangeModel::saveNeighbors(const int dir, const std::pair<MSVehicle* const, double>& follower, const std::pair<MSVehicle* const, double>& leader) {
206 if (dir == -1) {
207 myLeftFollowers = std::make_shared<MSLeaderDistanceInfo>(follower, myVehicle.getLane()->getWidth());
208 myLeftLeaders = std::make_shared<MSLeaderDistanceInfo>(leader, myVehicle.getLane()->getWidth());
209 } else if (dir == 1) {
210 myRightFollowers = std::make_shared<MSLeaderDistanceInfo>(follower, myVehicle.getLane()->getWidth());
211 myRightLeaders = std::make_shared<MSLeaderDistanceInfo>(leader, myVehicle.getLane()->getWidth());
212 } else {
213 // dir \in {-1,1} !
214 assert(false);
215 }
216}
217
218
219void
221 myLeftFollowers = nullptr;
222 myLeftLeaders = nullptr;
223 myRightFollowers = nullptr;
224 myRightLeaders = nullptr;
225}
226
227
228const std::shared_ptr<MSLeaderDistanceInfo>
230 if (dir == -1) {
231 return myLeftFollowers;
232 } else if (dir == 1) {
233 return myRightFollowers;
234 } else {
235 // dir \in {-1,1} !
236 assert(false);
237 }
238 return nullptr;
239}
240
241const std::shared_ptr<MSLeaderDistanceInfo>
243 if (dir == -1) {
244 return myLeftLeaders;
245 } else if (dir == 1) {
246 return myRightLeaders;
247 } else {
248 // dir \in {-1,1} !
249 assert(false);
250 }
251 return nullptr;
252}
253
254
255bool
257 if (neighLeader == nullptr) {
258 return false;
259 }
260 // Congested situation are relevant only on highways (maxSpeed > 70km/h)
261 // and congested on German Highways means that the vehicles have speeds
262 // below 60km/h. Overtaking on the right is allowed then.
263 if ((myVehicle.getLane()->getSpeedLimit() <= 70.0 / 3.6) || (neighLeader->getLane()->getSpeedLimit() <= 70.0 / 3.6)) {
264
265 return false;
266 }
267 if (myVehicle.congested() && neighLeader->congested()) {
268 return true;
269 }
270 return false;
271}
272
273
274bool
277 && !myVehicle.congested()
280}
281
282bool
283MSAbstractLaneChangeModel::predInteraction(const std::pair<MSVehicle*, double>& leader) {
284 if (leader.first == 0) {
285 return false;
286 }
287 // let's check it on highways only
288 if (leader.first->getSpeed() < (80.0 / 3.6)) {
289 return false;
290 }
291 return leader.second < getCarFollowModel().interactionGap(&myVehicle, leader.first->getSpeed());
292}
293
294
295bool
299 myLaneChangeDirection = direction;
300 setManeuverDist((target->getWidth() + source->getWidth()) * 0.5 * direction);
303 if (myLCOutput) {
305 }
306 return true;
307 } else {
308 primaryLaneChanged(source, target, direction);
309 return false;
310 }
311}
312
313void
315 myDontResetLCGaps = true;
316}
317
318void
320 myDontResetLCGaps = false;
321}
322
323void
325 initLastLaneChangeOffset(direction);
327 source->leftByLaneChange(&myVehicle);
328 laneChangeOutput("change", source, target, direction); // record position on the source edge in case of opposite change
329 if (&source->getEdge() != &target->getEdge()) {
331#ifdef DEBUG_OPPOSITE
332 if (debugVehicle()) {
333 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " primaryLaneChanged source=" << source->getID() << " target=" << target->getID() << " nowOpposite=" << myAmOpposite << "\n";
334 }
335#endif
338 } else if (myAmOpposite) {
339#ifdef DEBUG_OPPOSITE
340 if (debugVehicle()) {
341 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " primaryLaneChanged source=" << source->getID() << " target=" << target->getID() << " stayOpposite\n";
342 }
343#endif
344 myAlreadyChanged = true;
346 if (!MSGlobals::gSublane) {
347 // in the continous case, the vehicle is added to the target lane via MSLaneChanger::continueChange / registerHop
348 // in the sublane case, the vehicle is added to the target lane via MSLaneChangerSublane::checkChangeOppositeSublane / MSLane::myTmpVehicles
350 }
351 } else {
354 }
355 // Assure that the drive items are up to date (even if the following step is no actionstep for the vehicle).
356 // This is necessary because the lane advance uses the target lane from the corresponding drive item.
358 changed();
359}
360
361void
362MSAbstractLaneChangeModel::laneChangeOutput(const std::string& tag, MSLane* source, MSLane* target, int direction, double maneuverDist) {
363 if (myLCOutput) {
364 OutputDevice& of = OutputDevice::getDeviceByOption("lanechange-output");
365 of.openTag(tag);
368 of.writeAttr(SUMO_ATTR_TIME, time2string(MSNet::getInstance()->getCurrentTimeStep()));
369 of.writeAttr(SUMO_ATTR_FROM, source->getID());
370 of.writeAttr(SUMO_ATTR_TO, target->getID());
371 of.writeAttr(SUMO_ATTR_DIR, direction);
379 of.writeAttr("leaderGap", myLastLeaderGap == NO_NEIGHBOR ? "None" : toString(myLastLeaderGap));
380 of.writeAttr("leaderSecureGap", myLastLeaderSecureGap == NO_NEIGHBOR ? "None" : toString(myLastLeaderSecureGap));
381 of.writeAttr("leaderSpeed", myLastLeaderSpeed == NO_NEIGHBOR ? "None" : toString(myLastLeaderSpeed));
382 of.writeAttr("followerGap", myLastFollowerGap == NO_NEIGHBOR ? "None" : toString(myLastFollowerGap));
383 of.writeAttr("followerSecureGap", myLastFollowerSecureGap == NO_NEIGHBOR ? "None" : toString(myLastFollowerSecureGap));
384 of.writeAttr("followerSpeed", myLastFollowerSpeed == NO_NEIGHBOR ? "None" : toString(myLastFollowerSpeed));
385 of.writeAttr("origLeaderGap", myLastOrigLeaderGap == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderGap));
386 of.writeAttr("origLeaderSecureGap", myLastOrigLeaderSecureGap == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderSecureGap));
387 of.writeAttr("origLeaderSpeed", myLastOrigLeaderSpeed == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderSpeed));
389 const double latGap = direction < 0 ? myLastLateralGapRight : myLastLateralGapLeft;
390 of.writeAttr("latGap", latGap == NO_NEIGHBOR ? "None" : toString(latGap));
391 if (maneuverDist != 0) {
392 of.writeAttr("maneuverDistance", toString(maneuverDist));
393 }
394 }
395 if (myLCXYOutput) {
398 }
399 of.closeTag();
402 }
403 }
404}
405
406
407double
408MSAbstractLaneChangeModel::computeSpeedLat(double /*latDist*/, double& maneuverDist, bool /*urgent*/) const {
410 int stepsToChange = (int)ceil(fabs(maneuverDist) / SPEED2DIST(myVehicle.getVehicleType().getMaxSpeedLat()));
411 return DIST2SPEED(maneuverDist / stepsToChange);
412 } else {
413 return maneuverDist / STEPS2TIME(MSGlobals::gLaneChangeDuration);
414 }
415}
416
417
418double
420 throw ProcessError("Method getAssumedDecelForLaneChangeDuration() not implemented by model " + toString(myModel));
421}
422
423void
426 mySpeedLat = speedLat;
427}
428
429bool
431 const bool pastBefore = pastMidpoint();
432 // maneuverDist is not updated in the context of continuous lane changing but represents the full LC distance
433 double maneuverDist = getManeuverDist();
434 setSpeedLat(computeSpeedLat(0, maneuverDist, (myOwnState & LCA_URGENT) != 0));
436 return !pastBefore && pastMidpoint();
437}
438
439
440void
442 UNUSED_PARAMETER(reason);
451 // opposite driving continues after parking
452 } else {
453 // aborted maneuver
454#ifdef DEBUG_OPPOSITE
455 if (debugVehicle()) {
456 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " aborted maneuver (no longer opposite)\n";
457 }
458#endif
460 }
461 }
462}
463
464
465MSLane*
466MSAbstractLaneChangeModel::getShadowLane(const MSLane* lane, double posLat) const {
468 // initialize shadow lane
469 const double overlap = myVehicle.getLateralOverlap(posLat, lane);
470#ifdef DEBUG_SHADOWLANE
471 if (debugVehicle()) {
472 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " posLat=" << posLat << " overlap=" << overlap << "\n";
473 }
474#endif
475 if (myAmOpposite) {
476 // return the neigh-lane in forward direction
477 return lane->getParallelLane(1);
478 } else if (overlap > NUMERICAL_EPS) {
479 const int shadowDirection = posLat < 0 ? -1 : 1;
480 return lane->getParallelLane(shadowDirection);
481 } else if (isChangingLanes() && myLaneChangeCompletion < 0.5) {
482 // "reserve" target lane even when there is no overlap yet
484 } else {
485 return nullptr;
486 }
487 } else {
488 return nullptr;
489 }
490}
491
492
493MSLane*
496}
497
498
499void
501 if (myShadowLane != nullptr) {
502 if (debugVehicle()) {
503 std::cout << SIMTIME << " cleanupShadowLane\n";
504 }
506 myShadowLane = nullptr;
507 }
508 for (std::vector<MSLane*>::const_iterator it = myShadowFurtherLanes.begin(); it != myShadowFurtherLanes.end(); ++it) {
509 if (debugVehicle()) {
510 std::cout << SIMTIME << " cleanupShadowLane2\n";
511 }
512 (*it)->resetPartialOccupation(&myVehicle);
513 }
514 myShadowFurtherLanes.clear();
516}
517
518void
520 if (myTargetLane != nullptr) {
521 if (debugVehicle()) {
522 std::cout << SIMTIME << " cleanupTargetLane\n";
523 }
525 myTargetLane = nullptr;
526 }
527 for (std::vector<MSLane*>::const_iterator it = myFurtherTargetLanes.begin(); it != myFurtherTargetLanes.end(); ++it) {
528 if (debugVehicle()) {
529 std::cout << SIMTIME << " cleanupTargetLane\n";
530 }
531 if (*it != nullptr) {
532 (*it)->resetManeuverReservation(&myVehicle);
533 }
534 }
535 myFurtherTargetLanes.clear();
536// myNoPartiallyOccupatedByShadow.clear();
537}
538
539
540bool
542 // store request before canceling
543 getCanceledState(laneOffset) |= state;
544 int ret = myVehicle.influenceChangeDecision(state);
545 return ret != state;
546}
547
548double
551}
552
553void
555 if (dir > 0) {
557 } else if (dir < 0) {
559 }
560}
561
562void
564 if (!MSGlobals::gSublane) {
565 // assume each vehicle drives at the center of its lane and act as if it fits
566 return;
567 }
568 if (myShadowLane != nullptr) {
569#ifdef DEBUG_SHADOWLANE
570 if (debugVehicle()) {
571 std::cout << SIMTIME << " updateShadowLane()\n";
572 }
573#endif
575 }
577 std::vector<MSLane*> passed;
578 if (myShadowLane != nullptr) {
580 const std::vector<MSLane*>& further = myVehicle.getFurtherLanes();
581 if (myAmOpposite) {
582 assert(further.size() == 0);
583 } else {
584 const std::vector<double>& furtherPosLat = myVehicle.getFurtherLanesPosLat();
585 assert(further.size() == furtherPosLat.size());
586 passed.push_back(myShadowLane);
587 for (int i = 0; i < (int)further.size(); ++i) {
588 MSLane* shadowFurther = getShadowLane(further[i], furtherPosLat[i]);
589#ifdef DEBUG_SHADOWLANE
590 if (debugVehicle()) {
591 std::cout << SIMTIME << " further=" << further[i]->getID() << " (posLat=" << furtherPosLat[i] << ") shadowFurther=" << Named::getIDSecure(shadowFurther) << "\n";
592 }
593#endif
594 if (shadowFurther != nullptr && shadowFurther->getLinkTo(passed.back()) != nullptr) {
595 passed.push_back(shadowFurther);
596 }
597 }
598 std::reverse(passed.begin(), passed.end());
599 }
600 } else {
601 if (isChangingLanes() && myVehicle.getLateralOverlap() > NUMERICAL_EPS) {
602 WRITE_WARNING("Vehicle '" + myVehicle.getID() + "' could not finish continuous lane change (lane disappeared) time=" +
603 time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
605 }
606 }
607#ifdef DEBUG_SHADOWLANE
608 if (debugVehicle()) {
609 std::cout << SIMTIME << " updateShadowLane() veh=" << myVehicle.getID()
610 << " newShadowLane=" << Named::getIDSecure(myShadowLane)
611 << "\n before:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << " further=" << toString(myVehicle.getFurtherLanes()) << " passed=" << toString(passed);
612 std::cout << std::endl;
613 }
614#endif
616#ifdef DEBUG_SHADOWLANE
617 if (debugVehicle()) std::cout
618 << "\n after:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << "\n";
619#endif
620}
621
622
623int
625 if (isChangingLanes()) {
626 if (pastMidpoint()) {
627 return -myLaneChangeDirection;
628 } else {
630 }
631 } else if (myShadowLane == nullptr) {
632 return 0;
633 } else if (myAmOpposite) {
634 // return neigh-lane in forward direction
635 return 1;
636 } else if (&myShadowLane->getEdge() == &myVehicle.getLane()->getEdge()) {
638 } else {
639 // overlap with opposite direction lane
640 return 1;
641 }
642}
643
644
645MSLane*
647#ifdef DEBUG_TARGET_LANE
648 MSLane* oldTarget = myTargetLane;
649 std::vector<MSLane*> oldFurtherTargets = myFurtherTargetLanes;
650 if (debugVehicle()) {
651 std::cout << SIMTIME << " veh '" << myVehicle.getID() << "' (lane=" << myVehicle.getLane()->getID() << ") updateTargetLane()"
652 << "\n oldTarget: " << (oldTarget == nullptr ? "NULL" : oldTarget->getID())
653 << " oldFurtherTargets: " << toString(oldFurtherTargets);
654 }
655#endif
656 if (myTargetLane != nullptr) {
658 }
659 // Clear old further target lanes
660 for (MSLane* oldTargetLane : myFurtherTargetLanes) {
661 if (oldTargetLane != nullptr) {
662 oldTargetLane->resetManeuverReservation(&myVehicle);
663 }
664 }
665 myFurtherTargetLanes.clear();
666
667 // Get new target lanes and issue a maneuver reservation.
668 int targetDir;
670 if (myTargetLane != nullptr) {
672 // further targets are just the target lanes corresponding to the vehicle's further lanes
673 // @note In a neglectable amount of situations we might add a reservation for a shadow further lane.
674 for (MSLane* furtherLane : myVehicle.getFurtherLanes()) {
675 MSLane* furtherTargetLane = furtherLane->getParallelLane(targetDir);
676 myFurtherTargetLanes.push_back(furtherTargetLane);
677 if (furtherTargetLane != nullptr) {
678 furtherTargetLane->setManeuverReservation(&myVehicle);
679 }
680 }
681 }
682#ifdef DEBUG_TARGET_LANE
683 if (debugVehicle()) {
684 std::cout << "\n newTarget (maneuverDist=" << myManeuverDist << " offset=" << targetDir << "): " << (myTargetLane == nullptr ? "NULL" : myTargetLane->getID())
685 << " newFurtherTargets: " << toString(myFurtherTargetLanes)
686 << std::endl;
687 }
688#endif
689 return myTargetLane;
690}
691
692
693MSLane*
695 targetDir = 0;
696 if (myManeuverDist == 0) {
697 return nullptr;
698 }
699 // Current lateral boundaries of the vehicle
700 const double vehRight = myVehicle.getLateralPositionOnLane() - 0.5 * myVehicle.getWidth();
701 const double vehLeft = myVehicle.getLateralPositionOnLane() + 0.5 * myVehicle.getWidth();
702 const double halfLaneWidth = 0.5 * myVehicle.getLane()->getWidth();
703
704 if (vehRight + myManeuverDist < -halfLaneWidth) {
705 // Vehicle intends to traverse the right lane boundary
706 targetDir = -1;
707 } else if (vehLeft + myManeuverDist > halfLaneWidth) {
708 // Vehicle intends to traverse the left lane boundary
709 targetDir = 1;
710 }
711 if (targetDir == 0) {
712 // Presently, no maneuvering into another lane is begun.
713 return nullptr;
714 }
715 MSLane* target = myVehicle.getLane()->getParallelLane(targetDir);
716 if (target == nullptr || target == myShadowLane) {
717 return nullptr;
718 } else {
719 return target;
720 }
721}
722
723
724
725double
727 const double totalDuration = (myVehicle.getVehicleType().wasSet(VTYPEPARS_MAXSPEED_LAT_SET)
730
731 const double angleOffset = 60 / totalDuration * (pastMidpoint() ? 1 - myLaneChangeCompletion : myLaneChangeCompletion);
732 return myLaneChangeDirection * angleOffset;
733}
734
735
736double
737MSAbstractLaneChangeModel::estimateLCDuration(const double speed, const double remainingManeuverDist, const double decel, bool urgent) const {
738
740 if (lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING) == lcParams.end() && lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR) == lcParams.end()) {
742 // no dependency of lateral speed on longitudinal speed. (Only called prior to LC initialization to determine whether it could be completed)
744 } else {
745 return remainingManeuverDist / myVehicle.getVehicleType().getMaxSpeedLat();
746 }
747 }
748
749 if (remainingManeuverDist == 0) {
750 return 0;
751 }
752
753 // Check argument assumptions
754 assert(speed >= 0);
755 assert(remainingManeuverDist >= 0);
756 assert(decel > 0);
759 assert(myMaxSpeedLatStanding >= 0);
760
761 // for brevity
762 const double v0 = speed;
763 const double D = remainingManeuverDist;
764 const double b = decel;
765 const double wmin = myMaxSpeedLatStanding;
766 const double f = myMaxSpeedLatFactor;
767 const double wmax = myVehicle.getVehicleType().getMaxSpeedLat();
768
769 /* Here's the approach for the calculation of the required time for the LC:
770 * To obtain the maximal LC-duration, for v(t) we assume that v(t)=max(0, v0-b*t),
771 * Where v(t)=0 <=> t >= ts:=v0/b
772 * For the lateral speed w(t) this gives:
773 * w(t) = min(wmax, wmin + f*v(t))
774 * The lateral distance covered until t is
775 * d(t) = int_0^t w(s) ds
776 * We distinguish three possibilities for the solution d(T)=D, where T is the time of the LC completion.
777 * 1) w(T) = wmax, i.e. v(T)>(wmax-wmin)/f
778 * 2) wmin < w(T) < wmax, i.e. (wmax-wmin)/f > v(T) > 0
779 * 3) w(T) = wmin, i.e., v(T)=0
780 */
781 const double vm = (wmax - wmin) / f;
782 double distSoFar = 0.;
783 double timeSoFar = 0.;
784 double v = v0;
785 if (v > vm) {
786 const double wmaxTime = (v0 - vm) / b;
787 const double d1 = wmax * wmaxTime;
788 if (d1 >= D) {
789 return D / wmax;
790 } else {
791 distSoFar += d1;
792 timeSoFar += wmaxTime;
793 v = vm;
794 }
795 }
796 if (v > 0) {
797 /* Here, w(t1+t) = wmin + f*v(t1+t) = wmin + f*(v - b*t)
798 * Thus, the additional lateral distance covered after time t is:
799 * d2 = (wmin + f*v)*t - 0.5*f*b*t^2
800 * and the additional lateral distance covered until v=0 at t=v/b is:
801 * d2 = (wmin + 0.5*f*v)*t
802 */
803 const double t = v / b; // stop time
804 const double d2 = (wmin + 0.5 * f * v) * t; // lateral distance covered until stop
805 assert(d2 > 0);
806 if (distSoFar + d2 >= D) {
807 // LC is completed during this phase
808 const double x = 0.5 * f * b;
809 const double y = wmin + f * v;
810 /* Solve D - distSoFar = y*t - x*t^2.
811 * 0 = x*t^2 - y*t/x + (D - distSoFar)/x
812 */
813 const double p = 0.5 * y / x;
814 const double q = (D - distSoFar) / x;
815 assert(p * p - q > 0);
816 const double t2 = p + sqrt(p * p - q);
817 return timeSoFar + t2;
818 } else {
819 distSoFar += d2;
820 timeSoFar += t;
821 //v = 0;
822 }
823 }
824 // If we didn't return yet this means the LC was not completed until the vehicle stops (if braking with rate b)
825 if (wmin == 0) {
826 // LC won't be completed if vehicle stands
827 double maneuverDist = remainingManeuverDist;
828 const double vModel = computeSpeedLat(maneuverDist, maneuverDist, urgent);
829 if (vModel > 0) {
830 // unless the model tells us something different
831 return D / vModel;
832 } else {
833 return -1;
834 }
835 } else {
836 // complete LC with lateral speed wmin
837 return timeSoFar + (D - distSoFar) / wmin;
838 }
839}
840
843 assert(isChangingLanes()); // Only to be called during ongoing lane change
845 if (lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING) == lcParams.end() && lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR) == lcParams.end()) {
848 } else {
850 }
851 }
852 // Using maxSpeedLat(Factor/Standing)
853 const bool urgent = (myOwnState & LCA_URGENT) != 0;
857}
858
859
860void
862 //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " set shadow approaching=" << link->getViaLaneOrLane()->getID() << "\n";
863 myApproachedByShadow.push_back(link);
864}
865
866void
868 for (std::vector<MSLink*>::iterator it = myApproachedByShadow.begin(); it != myApproachedByShadow.end(); ++it) {
869 //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " remove shadow approaching=" << (*it)->getViaLaneOrLane()->getID() << "\n";
870 (*it)->removeApproaching(&myVehicle);
871 }
872 myApproachedByShadow.clear();
873}
874
875
876
877void
880 int oldstate = myVehicle.getLaneChangeModel().getOwnState();
881 if (myOwnState != newstate) {
883 // Calculate and set the lateral maneuver distance corresponding to the change request
884 // to induce a corresponding sublane change.
885 const int dir = (newstate & LCA_RIGHT) != 0 ? -1 : ((newstate & LCA_LEFT) != 0 ? 1 : 0);
886 // minimum distance to move the vehicle fully onto the lane at offset dir
887 const double latLaneDist = myVehicle.lateralDistanceToLane(dir);
888 if ((newstate & LCA_TRACI) != 0) {
889 if ((newstate & LCA_STAY) != 0) {
890 setManeuverDist(0.);
891 } else if (((newstate & LCA_RIGHT) != 0 && dir < 0)
892 || ((newstate & LCA_LEFT) != 0 && dir > 0)) {
893 setManeuverDist(latLaneDist);
894 }
895 }
896 if (myVehicle.hasInfluencer()) {
897 // lane change requests override sublane change requests
899 }
900
901 }
902 setOwnState(newstate);
903 } else {
904 // Check for sublane change requests
906 const double maneuverDist = myVehicle.getInfluencer().getLatDist();
909 newstate |= LCA_TRACI;
910 if (myOwnState != newstate) {
911 setOwnState(newstate);
912 }
913 if (gDebugFlag2) {
914 std::cout << " traci influenced maneuverDist=" << maneuverDist << "\n";
915 }
916 }
917 }
918 if (gDebugFlag2) {
919 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " stateAfterTraCI=" << toString((LaneChangeAction)newstate) << " original=" << toString((LaneChangeAction)oldstate) << "\n";
920 }
921}
922
923void
926 myAlreadyChanged = true;
927}
928
929void
931 if (follower.first != 0) {
932 myLastFollowerGap = follower.second + follower.first->getVehicleType().getMinGap();
934 myLastFollowerSpeed = follower.first->getSpeed();
935 }
936}
937
938void
940 if (leader.first != 0) {
942 myLastLeaderSecureGap = secGap;
943 myLastLeaderSpeed = leader.first->getSpeed();
944 }
945}
946
947void
949 if (leader.first != 0) {
952 myLastOrigLeaderSpeed = leader.first->getSpeed();
953 }
954}
955
956void
966 if (!myDontResetLCGaps) {
976 }
978}
979
980void
982 int rightmost;
983 int leftmost;
984 vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
985 for (int i = rightmost; i <= leftmost; ++i) {
986 CLeaderDist vehDist = vehicles[i];
987 if (vehDist.first != 0) {
988 const MSVehicle* leader = &myVehicle;
989 const MSVehicle* follower = vehDist.first;
990 const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
991 if (netGap < myLastFollowerGap && netGap >= 0) {
992 myLastFollowerGap = netGap;
993 myLastFollowerSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
994 myLastFollowerSpeed = follower->getSpeed();
995 }
996 }
997 }
998}
999
1000void
1002 int rightmost;
1003 int leftmost;
1004 vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
1005 for (int i = rightmost; i <= leftmost; ++i) {
1006 CLeaderDist vehDist = vehicles[i];
1007 if (vehDist.first != 0) {
1008 const MSVehicle* leader = vehDist.first;
1009 const MSVehicle* follower = &myVehicle;
1010 const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
1011 if (netGap < myLastLeaderGap && netGap >= 0) {
1012 myLastLeaderGap = netGap;
1013 myLastLeaderSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
1014 myLastLeaderSpeed = leader->getSpeed();
1015 }
1016 }
1017 }
1018}
1019
1020void
1022 int rightmost;
1023 int leftmost;
1024 vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
1025 for (int i = rightmost; i <= leftmost; ++i) {
1026 CLeaderDist vehDist = vehicles[i];
1027 if (vehDist.first != 0) {
1028 const MSVehicle* leader = vehDist.first;
1029 const MSVehicle* follower = &myVehicle;
1030 const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
1031 if (netGap < myLastOrigLeaderGap && netGap >= 0) {
1032 myLastOrigLeaderGap = netGap;
1033 myLastOrigLeaderSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
1034 myLastOrigLeaderSpeed = leader->getSpeed();
1035 }
1036 }
1037 }
1038}
1039
1040
1041bool
1043 const int stateRight = mySavedStateRight.second;
1044 if (
1045 (stateRight & LCA_STRATEGIC) != 0
1046 && (stateRight & LCA_RIGHT) != 0
1047 && (stateRight & LCA_BLOCKED) != 0) {
1048 return true;
1049 }
1050 const int stateLeft = mySavedStateLeft.second;
1051 if (
1052 (stateLeft & LCA_STRATEGIC) != 0
1053 && (stateLeft & LCA_LEFT) != 0
1054 && (stateLeft & LCA_BLOCKED) != 0) {
1055 return true;
1056 }
1057 return false;
1058}
1059
1060double
1063}
1064
1065
1066int
1068 const int i = myVehicle.getLane()->getIndex();
1069 if (myAmOpposite) {
1071 } else {
1072 return i;
1073 }
1074}
1075
1076
1077void
1079 std::vector<std::string> lcState;
1081 lcState.push_back(toString(mySpeedLat));
1082 lcState.push_back(toString(myLaneChangeCompletion));
1083 lcState.push_back(toString(myLaneChangeDirection));
1084 }
1085 if (lcState.size() > 0) {
1086 out.writeAttr(SUMO_ATTR_LCSTATE, lcState);
1087 }
1088}
1089
1090void
1092 if (attrs.hasAttribute(SUMO_ATTR_LCSTATE)) {
1093 std::istringstream bis(attrs.getString(SUMO_ATTR_LCSTATE));
1094 bis >> mySpeedLat;
1096 bis >> myLaneChangeDirection;
1097 }
1098}
long long int SUMOTime
Definition: GUI.h:36
#define DEBUG_COND
std::pair< const MSVehicle *, double > CLeaderDist
Definition: MSLeaderInfo.h:38
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:265
SUMOTime DELTA_T
Definition: SUMOTime.cpp:37
std::string time2string(SUMOTime t)
convert SUMOTime to string
Definition: SUMOTime.cpp:68
#define STEPS2TIME(x)
Definition: SUMOTime.h:54
#define SPEED2DIST(x)
Definition: SUMOTime.h:44
#define SIMTIME
Definition: SUMOTime.h:61
#define TIME2STEPS(x)
Definition: SUMOTime.h:56
#define DIST2SPEED(x)
Definition: SUMOTime.h:46
#define SPEED2ACCEL(x)
Definition: SUMOTime.h:52
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:34
const double SUMO_const_laneWidth
Definition: StdDefs.h:48
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MAX2(T a, T b)
Definition: StdDefs.h:77
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
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 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
const LaneChangeModel myModel
the type of this model
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...
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 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
double getAngleOffset() const
return the angle offset during a continuous change maneuver
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)
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 getSecureGap(const MSVehicle *const, 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.h:390
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:255
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
Definition: MSCFModel.h:262
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:159
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:2521
virtual void resetManeuverReservation(MSVehicle *v)
Unregisters a vehicle, which previously registered for maneuvering into this lane.
Definition: MSLane.cpp:389
const MSLink * getLinkTo(const MSLane *const) const
returns the link to the given lane or nullptr, if it is not connected
Definition: MSLane.cpp:2428
void forceVehicleInsertion(MSVehicle *veh, double pos, MSMoveReminder::Notification notification, double posLat=0)
Inserts the given vehicle at the given position.
Definition: MSLane.cpp:1259
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition: MSLane.h:561
void enteredByLaneChange(MSVehicle *v)
Definition: MSLane.cpp:2999
double getLength() const
Returns the lane's length.
Definition: MSLane.h:575
virtual double setPartialOccupation(MSVehicle *v)
Sets the information about a vehicle lapping into this lane.
Definition: MSLane.cpp:336
int getIndex() const
Returns the lane's index.
Definition: MSLane.h:597
void leftByLaneChange(MSVehicle *v)
Definition: MSLane.cpp:2992
double getOppositePos(double pos) const
return the corresponding position on the opposite lane
Definition: MSLane.cpp:4017
virtual void resetPartialOccupation(MSVehicle *v)
Removes the information about a vehicle lapping into this lane.
Definition: MSLane.cpp:355
virtual void setManeuverReservation(MSVehicle *v)
Registers the lane change intentions (towards this lane) for the given vehicle.
Definition: MSLane.cpp:378
MSLane * getParallelOpposite() const
return the opposite direction lane of this lanes edge or nullptr
Definition: MSLane.cpp:4011
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:713
double getWidth() const
Returns the lane's width.
Definition: MSLane.h:590
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:1599
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:77
const std::vector< double > & getFurtherLanesPosLat() const
Definition: MSVehicle.h:842
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:6239
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:5367
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
Definition: MSVehicle.cpp:6808
void fixPosition()
repair errors in vehicle position after changing between internal edges
Definition: MSVehicle.cpp:6047
Position getPosition(const double offset=0) const
Return current position (x/y, cartesian)
Definition: MSVehicle.cpp:1208
double lateralDistanceToLane(const int offset) const
Get the minimal lateral distance required to move fully onto the lane at given offset.
Definition: MSVehicle.cpp:6394
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:5281
void switchOffSignal(int signal)
Switches the given signal off.
Definition: MSVehicle.h:1182
@ VEH_SIGNAL_BLINKER_RIGHT
Right blinker lights are switched on.
Definition: MSVehicle.h:1121
@ VEH_SIGNAL_BLINKER_LEFT
Left blinker lights are switched on.
Definition: MSVehicle.h:1123
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:577
void enterLaneAtLaneChange(MSLane *enteredLane)
Update when the vehicle enters a new lane in the laneChange step.
Definition: MSVehicle.cpp:5107
Influencer & getInfluencer()
Definition: MSVehicle.cpp:6773
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:4536
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
Definition: MSVehicle.h:416
bool congested() const
Definition: MSVehicle.cpp:1393
double getSpeed() const
Returns the vehicle's current speed.
Definition: MSVehicle.h:486
const std::vector< MSLane * > & getFurtherLanes() const
Definition: MSVehicle.h:838
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition: MSVehicle.h:966
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:6450
bool hasInfluencer() const
whether the vehicle is individually influenced (via TraCI or special parameters)
Definition: MSVehicle.h:1690
void switchOnSignal(int signal)
Switches the given signal on.
Definition: MSVehicle.h:1174
void updateDriveItems()
Check whether the drive items (myLFLinkLanes) are up to date, and update them if required.
Definition: MSVehicle.cpp:3640
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:251
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