Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSLane.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-2026 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/****************************************************************************/
27// Representation of a lane in the micro simulation
28/****************************************************************************/
29#include <config.h>
30
31#include <cmath>
32#include <bitset>
33#include <iostream>
34#include <cassert>
35#include <functional>
36#include <algorithm>
37#include <iterator>
38#include <exception>
39#include <climits>
40#include <set>
45#ifdef HAVE_FOX
47#endif
60#include <mesosim/MELoop.h>
61#include "MSNet.h"
62#include "MSVehicleType.h"
63#include "MSEdge.h"
64#include "MSEdgeControl.h"
65#include "MSJunction.h"
66#include "MSLogicJunction.h"
67#include "MSLink.h"
68#include "MSLane.h"
69#include "MSVehicleTransfer.h"
70#include "MSGlobals.h"
71#include "MSVehicleControl.h"
72#include "MSInsertionControl.h"
73#include "MSVehicleControl.h"
74#include "MSLeaderInfo.h"
75#include "MSVehicle.h"
76#include "MSStop.h"
77
78//#define DEBUG_INSERTION
79//#define DEBUG_PLAN_MOVE
80//#define DEBUG_EXEC_MOVE
81//#define DEBUG_CONTEXT
82//#define DEBUG_PARTIALS
83//#define DEBUG_MANEUVER_RESERVATIONS
84//#define DEBUG_OPPOSITE
85//#define DEBUG_VEHICLE_CONTAINER
86//#define DEBUG_COLLISIONS
87//#define DEBUG_JUNCTION_COLLISIONS
88//#define DEBUG_PEDESTRIAN_COLLISIONS
89//#define DEBUG_LANE_SORTER
90//#define DEBUG_NO_CONNECTION
91//#define DEBUG_SURROUNDING
92//#define DEBUG_EXTRAPOLATE_DEPARTPOS
93//#define DEBUG_ITERATOR
94
95//#define DEBUG_COND (false)
96//#define DEBUG_COND (true)
97#define DEBUG_COND (isSelected())
98#define DEBUG_COND2(obj) ((obj != nullptr && (obj)->isSelected()))
99//#define DEBUG_COND (getID() == "ego")
100//#define DEBUG_COND2(obj) ((obj != 0 && (obj)->getID() == "ego"))
101//#define DEBUG_COND2(obj) (true)
102
103
104// ===========================================================================
105// static member definitions
106// ===========================================================================
116std::vector<SumoRNG> MSLane::myRNGs;
119
120
121// ===========================================================================
122// internal class method definitions
123// ===========================================================================
124void
125MSLane::StoringVisitor::add(const MSLane* const l) const {
126 switch (myDomain) {
128 for (const MSVehicle* veh : l->getVehiclesSecure()) {
129 if (myShape.distance2D(veh->getPosition()) <= myRange) {
130 myObjects.insert(veh);
131 }
132 }
133 for (const MSBaseVehicle* veh : l->getParkingVehicles()) {
134 if (myShape.distance2D(veh->getPosition()) <= myRange) {
135 myObjects.insert(veh);
136 }
137 }
138 l->releaseVehicles();
139 }
140 break;
143 std::vector<MSTransportable*> persons = l->getEdge().getSortedPersons(MSNet::getInstance()->getCurrentTimeStep(), true);
144 for (auto p : persons) {
145 if (myShape.distance2D(p->getPosition()) <= myRange) {
146 myObjects.insert(p);
147 }
148 }
149 l->releaseVehicles();
150 }
151 break;
153 if (myShape.size() != 1 || l->getShape().distance2D(myShape[0]) <= myRange) {
154 myObjects.insert(&l->getEdge());
155 }
156 }
157 break;
159 if (myShape.size() != 1 || l->getShape().distance2D(myShape[0]) <= myRange) {
160 myObjects.insert(l);
161 }
162 }
163 break;
164 default:
165 break;
166
167 }
168}
169
170
173 if (nextIsMyVehicles()) {
174 if (myI1 != myI1End) {
175 myI1 += myDirection;
176 } else if (myI3 != myI3End) {
177 myI3 += myDirection;
178 }
179 // else: already at end
180 } else {
181 myI2 += myDirection;
182 }
183 //if (DEBUG_COND2(myLane)) std::cout << SIMTIME << " AnyVehicleIterator::operator++ lane=" << myLane->getID() << " myI1=" << myI1 << " myI2=" << myI2 << "\n";
184 return *this;
185}
186
187
188const MSVehicle*
190 if (nextIsMyVehicles()) {
191 if (myI1 != myI1End) {
192 return myLane->myVehicles[myI1];
193 } else if (myI3 != myI3End) {
194 return myLane->myTmpVehicles[myI3];
195 } else {
196 assert(myI2 == myI2End);
197 return nullptr;
198 }
199 } else {
200 return myLane->myPartialVehicles[myI2];
201 }
202}
203
204
205bool
207#ifdef DEBUG_ITERATOR
208 if (DEBUG_COND2(myLane)) std::cout << SIMTIME << " AnyVehicleIterator::nextIsMyVehicles lane=" << myLane->getID()
209 << " myDownstream=" << myDownstream
210 << " myI1=" << myI1
211 << " myI1End=" << myI1End
212 << " myI2=" << myI2
213 << " myI2End=" << myI2End
214 << " myI3=" << myI3
215 << " myI3End=" << myI3End
216 << "\n";
217#endif
218 if (myI1 == myI1End && myI3 == myI3End) {
219 if (myI2 != myI2End) {
220 return false;
221 } else {
222 return true; // @note. must be caught
223 }
224 } else {
225 if (myI2 == myI2End) {
226 return true;
227 } else {
228 MSVehicle* cand = myI1 == myI1End ? myLane->myTmpVehicles[myI3] : myLane->myVehicles[myI1];
229#ifdef DEBUG_ITERATOR
230 if (DEBUG_COND2(myLane)) std::cout << " "
231 << " veh1=" << cand->getID()
232 << " isTmp=" << (myI1 == myI1End)
233 << " veh2=" << myLane->myPartialVehicles[myI2]->getID()
234 << " pos1=" << cand->getPositionOnLane(myLane)
235 << " pos2=" << myLane->myPartialVehicles[myI2]->getPositionOnLane(myLane)
236 << "\n";
237#endif
238 if (cand->getPositionOnLane() < myLane->myPartialVehicles[myI2]->getPositionOnLane(myLane)) {
239 return myDownstream;
240 } else {
241 return !myDownstream;
242 }
243 }
244 }
245}
246
247
248// ===========================================================================
249// member method definitions
250// ===========================================================================
251#ifdef _MSC_VER
252#pragma warning(push)
253#pragma warning(disable: 4355) // mask warning about "this" in initializers
254#endif
255MSLane::MSLane(const std::string& id, double maxSpeed, double friction, double length, MSEdge* const edge,
256 int numericalID, const PositionVector& shape, double width,
257 SVCPermissions permissions,
258 SVCPermissions changeLeft, SVCPermissions changeRight,
259 int index, bool isRampAccel,
260 const std::string& type,
261 const PositionVector& outlineShape) :
262 Named(id),
263 myNumericalID(numericalID), myShape(shape), myIndex(index),
264 myVehicles(), myLength(length), myWidth(width),
265 myEdge(edge), myMaxSpeed(maxSpeed),
266 myFrictionCoefficient(friction),
267 mySpeedModified(false),
268 myPermissions(permissions),
269 myChangeLeft(changeLeft),
270 myChangeRight(changeRight),
271 myOriginalPermissions(permissions),
278 myLeaderInfo(width, nullptr, 0.),
279 myFollowerInfo(width, nullptr, 0.),
282 myLengthGeometryFactor(MAX2(POSITION_EPS, myShape.length()) / myLength), // factor should not be 0
283 myIsRampAccel(isRampAccel),
284 myLaneType(type),
285 myRightSideOnEdge(0), // initialized in MSEdge::initialize
288 myOpposite(nullptr),
289 myBidiLane(nullptr),
290#ifdef HAVE_FOX
291 mySimulationTask(*this, 0),
292#endif
293 myStopWatch(3) {
294 // initialized in MSEdge::initialize
295 initRestrictions();// may be reloaded again from initialized in MSEdge::closeBuilding
296 assert(myRNGs.size() > 0);
297 myRNGIndex = numericalID % myRNGs.size();
298 if (outlineShape.size() > 0) {
299 myOutlineShape = new PositionVector(outlineShape);
300 }
301}
302#ifdef _MSC_VER
303#pragma warning(pop)
304#endif
305
306
308 for (MSLink* const l : myLinks) {
309 delete l;
310 }
311 delete myOutlineShape;
312}
313
314
315void
317 // simplify unit testing without MSNet instance
319}
320
321
322void
324 if (MSGlobals::gNumSimThreads <= 1) {
326// } else {
327// this is an idea for better memory locality, lanes with nearby numerical ids get the same rng and thus the same thread
328// first tests show no visible effect though
329// myRNGIndex = myNumericalID * myRNGs.size() / dictSize();
330 }
331}
332
333
334void
336 myLinks.push_back(link);
337}
338
339
340void
342 myOpposite = oppositeLane;
343 if (myOpposite != nullptr && getLength() > myOpposite->getLength()) {
344 WRITE_WARNINGF(TL("Unequal lengths of neigh lane '%' and lane '%' (% != %)."), getID(), myOpposite->getID(), getLength(), myOpposite->getLength());
345 }
346}
347
348void
350 myBidiLane = bidiLane;
351 if (myBidiLane != nullptr && getLength() > myBidiLane->getLength()) {
353 WRITE_WARNINGF(TL("Unequal lengths of bidi lane '%' and lane '%' (% != %)."), getID(), myBidiLane->getID(), getLength(), myBidiLane->getLength());
354 }
355 }
356}
357
358
359
360// ------ interaction with MSMoveReminder ------
361void
362MSLane::addMoveReminder(MSMoveReminder* rem, bool addToVehicles) {
363 myMoveReminders.push_back(rem);
364 if (addToVehicles) {
365 for (MSVehicle* const veh : myVehicles) {
366 veh->addReminder(rem);
367 }
368 }
369 // XXX: Here, the partial occupators are ignored!? Refs. #3255
370}
371
372
373void
375 auto it = std::find(myMoveReminders.begin(), myMoveReminders.end(), rem);
376 if (it != myMoveReminders.end()) {
377 myMoveReminders.erase(it);
378 for (MSVehicle* const veh : myVehicles) {
379 veh->removeReminder(rem);
380 }
381 }
382}
383
384
385double
387 // multithreading: there are concurrent writes to myNeedsCollisionCheck but all of them should set it to true
388 myNeedsCollisionCheck = true; // always check
389#ifdef DEBUG_PARTIALS
390 if (DEBUG_COND2(v)) {
391 std::cout << SIMTIME << " setPartialOccupation. lane=" << getID() << " veh=" << v->getID() << "\n";
392 }
393#endif
394 // XXX update occupancy here?
395#ifdef HAVE_FOX
396 ScopedLocker<> lock(myPartialOccupatorMutex, MSGlobals::gNumSimThreads > 1);
397#endif
398 //assert(std::find(myPartialVehicles.begin(), myPartialVehicles.end(), v) == myPartialVehicles.end());
399 myPartialVehicles.push_back(v);
400 return myLength;
401}
402
403
404void
406#ifdef HAVE_FOX
407 ScopedLocker<> lock(myPartialOccupatorMutex, MSGlobals::gNumSimThreads > 1);
408#endif
409#ifdef DEBUG_PARTIALS
410 if (DEBUG_COND2(v)) {
411 std::cout << SIMTIME << " resetPartialOccupation. lane=" << getID() << " veh=" << v->getID() << "\n";
412 }
413#endif
414 for (VehCont::iterator i = myPartialVehicles.begin(); i != myPartialVehicles.end(); ++i) {
415 if (v == *i) {
416 myPartialVehicles.erase(i);
417 // XXX update occupancy here?
418 //std::cout << " removed from myPartialVehicles\n";
419 return;
420 }
421 }
422 // bluelight eqipped vehicle can teleport onto the intersection without using a connection
423 assert(false || MSGlobals::gClearState || v->getLaneChangeModel().hasBlueLight());
424}
425
426
427void
429#ifdef DEBUG_MANEUVER_RESERVATIONS
430 if (DEBUG_COND2(v)) {
431 std::cout << SIMTIME << " setManeuverReservation. lane=" << getID() << " veh=" << v->getID() << "\n";
432 }
433#endif
434 myManeuverReservations.push_back(v);
435}
436
437
438void
440#ifdef DEBUG_MANEUVER_RESERVATIONS
441 if (DEBUG_COND2(v)) {
442 std::cout << SIMTIME << " resetManeuverReservation(): lane=" << getID() << " veh=" << v->getID() << "\n";
443 }
444#endif
445 for (VehCont::iterator i = myManeuverReservations.begin(); i != myManeuverReservations.end(); ++i) {
446 if (v == *i) {
447 myManeuverReservations.erase(i);
448 return;
449 }
450 }
451 assert(false);
452}
453
454
455// ------ Vehicle emission ------
456void
457MSLane::incorporateVehicle(MSVehicle* veh, double pos, double speed, double posLat, const MSLane::VehCont::iterator& at, MSMoveReminder::Notification notification) {
459 assert(pos <= myLength || notification == MSMoveReminder::NOTIFICATION_LOAD_STATE);
460 bool wasInactive = myVehicles.size() == 0;
461 veh->enterLaneAtInsertion(this, pos, speed, posLat, notification);
462 if (at == myVehicles.end()) {
463 // vehicle will be the first on the lane
464 myVehicles.push_back(veh);
465 } else {
466 myVehicles.insert(at, veh);
467 }
471 if (wasInactive) {
473 }
474 if (getBidiLane() != nullptr && (!isRailway(veh->getVClass()) || (getPermissions() & ~SVC_RAIL_CLASSES) != 0)) {
475 // railways don't need to "see" each other when moving in opposite directions on the same track (efficiency)
477 }
478}
479
480
481bool
482MSLane::lastInsertion(MSVehicle& veh, double mspeed, double posLat, bool patchSpeed) {
483 double pos = getLength() - POSITION_EPS;
484 MSVehicle* leader = getLastAnyVehicle();
485 // back position of leader relative to this lane
486 double leaderBack;
487 if (leader == nullptr) {
489 veh.setTentativeLaneAndPosition(this, pos, posLat);
490 veh.updateBestLanes(false, this);
491 std::pair<MSVehicle* const, double> leaderInfo = getLeader(&veh, pos, veh.getBestLanesContinuation(), veh.getCarFollowModel().brakeGap(mspeed));
492 leader = leaderInfo.first;
493 leaderBack = pos + leaderInfo.second + veh.getVehicleType().getMinGap();
494 } else {
495 leaderBack = leader->getBackPositionOnLane(this);
496 //std::cout << " leaderPos=" << leader->getPositionOnLane(this) << " leaderBack=" << leader->getBackPositionOnLane(this) << " leaderLane=" << leader->getLane()->getID() << "\n";
497 }
498 if (leader == nullptr) {
499 // insert at the end of this lane
500 return isInsertionSuccess(&veh, mspeed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED);
501 } else {
502 // try to insert behind the leader
503 const double frontGapNeeded = veh.getCarFollowModel().getSecureGap(&veh, leader, mspeed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()) + veh.getVehicleType().getMinGap() + POSITION_EPS;
504 if (leaderBack >= frontGapNeeded) {
505 pos = MIN2(pos, leaderBack - frontGapNeeded);
506 bool result = isInsertionSuccess(&veh, mspeed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED);
507 //if (!result) std::cout << " insertLast failed for " << veh.getID() << " pos=" << pos << " leaderBack=" << leaderBack << " frontGapNeeded=" << frontGapNeeded << "\n";
508 return result;
509 }
510 //std::cout << " insertLast failed for " << veh.getID() << " pos=" << pos << " leaderBack=" << leaderBack << " frontGapNeeded=" << frontGapNeeded << "\n";
511 }
512 return false;
513}
514
515
516bool
517MSLane::freeInsertion(MSVehicle& veh, double mspeed, double posLat,
518 MSMoveReminder::Notification notification) {
519 // try to insert teleporting vehicles fully on this lane
520 double maxPos = myLength;
521 if (veh.hasStops() && veh.getNextStop().edge == veh.getCurrentRouteEdge()) {
522 maxPos = MAX2(0.0, veh.getNextStop().getEndPos(veh));
523 }
524 const double minPos = (notification == MSMoveReminder::NOTIFICATION_TELEPORT ?
525 MIN2(maxPos, veh.getVehicleType().getLength()) : 0);
526 veh.setTentativeLaneAndPosition(this, minPos, 0);
527 if (myVehicles.size() == 0) {
528 // ensure sufficient gap to followers on predecessor lanes
529 const double backOffset = minPos - veh.getVehicleType().getLength();
530 const double missingRearGap = getMissingRearGap(&veh, backOffset, mspeed);
531 if (missingRearGap > 0) {
532 if (minPos + missingRearGap <= maxPos) {
533 // @note. The rear gap is tailored to mspeed. If it changes due
534 // to a leader vehicle (on subsequent lanes) insertion will
535 // still fail. Under the right combination of acceleration and
536 // deceleration values there might be another insertion
537 // positions that would be successful be we do not look for it.
538 //std::cout << SIMTIME << " freeInsertion lane=" << getID() << " veh=" << veh.getID() << " unclear @(340)\n";
539 return isInsertionSuccess(&veh, mspeed, minPos + missingRearGap, posLat, true, notification);
540 }
541 return false;
542 } else {
543 return isInsertionSuccess(&veh, mspeed, minPos, posLat, true, notification);
544 }
545
546 } else {
547 // check whether the vehicle can be put behind the last one if there is such
548 const MSVehicle* const leader = myVehicles.back(); // @todo reproduction of bogus old behavior. see #1961
549 const double leaderPos = leader->getBackPositionOnLane(this);
550 const double speed = leader->getSpeed();
551 const double frontGapNeeded = veh.getCarFollowModel().getSecureGap(&veh, leader, speed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()) + veh.getVehicleType().getMinGap();
552 if (leaderPos >= frontGapNeeded) {
553 const double tspeed = MIN2(veh.getCarFollowModel().insertionFollowSpeed(&veh, mspeed, frontGapNeeded, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel(), leader), mspeed);
554 // check whether we can insert our vehicle behind the last vehicle on the lane
555 if (isInsertionSuccess(&veh, tspeed, minPos, posLat, true, notification)) {
556 //std::cout << SIMTIME << " freeInsertion lane=" << getID() << " veh=" << veh.getID() << " pos=" << minPos<< " speed=" << speed << " tspeed=" << tspeed << " frontGapNeeded=" << frontGapNeeded << " lead=" << leader->getID() << " lPos=" << leaderPos << "\n vehsOnLane=" << toString(myVehicles) << " @(358)\n";
557 return true;
558 }
559 }
560 }
561 // go through the lane, look for free positions (starting after the last vehicle)
562 MSLane::VehCont::iterator predIt = myVehicles.begin();
563 while (predIt != myVehicles.end()) {
564 // get leader (may be zero) and follower
565 // @todo compute secure position in regard to sublane-model
566 const MSVehicle* leader = predIt != myVehicles.end() - 1 ? *(predIt + 1) : nullptr;
567 if (leader == nullptr && myPartialVehicles.size() > 0) {
568 leader = myPartialVehicles.front();
569 }
570 const MSVehicle* follower = *predIt;
571
572 // patch speed if allowed
573 double speed = mspeed;
574 if (leader != nullptr) {
575 speed = MIN2(leader->getSpeed(), mspeed);
576 }
577
578 // compute the space needed to not collide with leader
579 double frontMax = maxPos;
580 if (leader != nullptr) {
581 double leaderRearPos = leader->getBackPositionOnLane(this);
582 double frontGapNeeded = veh.getCarFollowModel().getSecureGap(&veh, leader, speed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()) + veh.getVehicleType().getMinGap();
583 frontMax = MIN2(maxPos, leaderRearPos - frontGapNeeded);
584 }
585 // compute the space needed to not let the follower collide
586 const double followPos = follower->getPositionOnLane() + follower->getVehicleType().getMinGap();
587 const double backGapNeeded = follower->getCarFollowModel().getSecureGap(follower, &veh, follower->getSpeed(), veh.getSpeed(), veh.getCarFollowModel().getMaxDecel());
588 const double backMin = followPos + backGapNeeded + veh.getVehicleType().getLength();
589
590 // check whether there is enough room (given some extra space for rounding errors)
591 if (frontMax > minPos && backMin + POSITION_EPS < frontMax) {
592 // try to insert vehicle (should be always ok)
593 if (isInsertionSuccess(&veh, speed, backMin + POSITION_EPS, posLat, true, notification)) {
594 //std::cout << SIMTIME << " freeInsertion lane=" << getID() << " veh=" << veh.getID() << " @(393)\n";
595 return true;
596 }
597 }
598 ++predIt;
599 }
600 // first check at lane's begin
601 //std::cout << SIMTIME << " freeInsertion lane=" << getID() << " veh=" << veh.getID() << " fail final\n";
602 return false;
603}
604
605
606double
607MSLane::getDepartSpeed(const MSVehicle& veh, bool& patchSpeed) {
608 double speed = 0;
609 const SUMOVehicleParameter& pars = veh.getParameter();
613 if (dsd == DepartSpeedDefinition::GIVEN) {
614 speed = myDefaultDepartSpeed;
615 }
616 } else if (dsd == DepartSpeedDefinition::GIVEN) {
617 speed = pars.departSpeed;;
618 }
619 switch (dsd) {
621 patchSpeed = false;
622 break;
625 patchSpeed = true;
626 break;
628 speed = getVehicleMaxSpeed(&veh);
629 patchSpeed = true;
630 break;
632 speed = getVehicleMaxSpeed(&veh);
633 patchSpeed = false;
634 break;
636 speed = getVehicleMaxSpeed(&veh) / veh.getChosenSpeedFactor();
637 patchSpeed = false;
638 break;
641 speed = getVehicleMaxSpeed(&veh);
642 if (last != nullptr) {
643 speed = MIN2(speed, last->getSpeed());
644 patchSpeed = false;
645 }
646 break;
647 }
649 speed = MIN2(getVehicleMaxSpeed(&veh), getMeanSpeed());
650 if (getLastAnyVehicle() != nullptr) {
651 patchSpeed = false;
652 }
653 break;
654 }
656 default:
657 // speed = 0 was set before
658 patchSpeed = false; // @todo check
659 break;
660 }
661 return speed;
662}
663
664
665double
667 const SUMOVehicleParameter& pars = veh.getParameter();
668 switch (pars.departPosLatProcedure) {
670 return pars.departPosLat;
672 return -getWidth() * 0.5 + veh.getVehicleType().getWidth() * 0.5;
674 return getWidth() * 0.5 - veh.getVehicleType().getWidth() * 0.5;
676 const double raw = RandHelper::rand(getWidth() - veh.getVehicleType().getWidth()) - getWidth() * 0.5 + veh.getVehicleType().getWidth() * 0.5;
677 return roundDecimal(raw, gPrecisionRandom);
678 }
681 // @note:
682 // case DepartPosLatDefinition::FREE
683 // case DepartPosLatDefinition::RANDOM_FREE
684 // are not handled here because they involve multiple insertion attempts
685 default:
686 return 0;
687 }
688}
689
690
691bool
693 double pos = 0;
694 bool patchSpeed = true; // whether the speed shall be adapted to infrastructure/traffic in front
695 const SUMOVehicleParameter& pars = veh.getParameter();
696 double speed = getDepartSpeed(veh, patchSpeed);
697 double posLat = getDepartPosLat(veh);
698
699 // determine the position
700 switch (pars.departPosProcedure) {
702 pos = pars.departPos;
703 if (pos < 0.) {
704 pos += myLength;
705 }
706 break;
709 break;
711 for (int i = 0; i < 10; i++) {
712 // we will try some random positions ...
714 posLat = getDepartPosLat(veh); // could be random as well
715 if (isInsertionSuccess(&veh, speed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED)) {
717 return true;
718 }
719 }
720 // ... and if that doesn't work, we put the vehicle to the free position
721 bool success = freeInsertion(veh, speed, posLat);
722 if (success) {
724 }
725 return success;
726 }
728 return freeInsertion(veh, speed, posLat);
730 return lastInsertion(veh, speed, posLat, patchSpeed);
732 if (veh.hasStops() && veh.getNextStop().edge == veh.getCurrentRouteEdge()) {
733 // getLastFreePos of stopping place could return negative position to avoid blocking the stop
734 pos = MAX2(0.0, veh.getNextStop().getEndPos(veh));
735 break;
736 }
741 default:
743 pos = getLength();
744 // find the vehicle from which we are splitting off (should only be a single lane to check)
746 for (AnyVehicleIterator it = anyVehiclesBegin(); it != end; ++it) {
747 const MSVehicle* cand = *it;
748 if (cand->isStopped() && cand->getNextStopParameter()->split == veh.getID()) {
750 pos = cand->getPositionOnLane() + cand->getVehicleType().getMinGap() + veh.getLength();
751 } else {
752 pos = cand->getBackPositionOnLane() - veh.getVehicleType().getMinGap();
753 }
754 break;
755 }
756 }
757 } else {
758 pos = veh.basePos(myEdge);
759 }
760 break;
761 }
762 // determine the lateral position for special cases
764 switch (pars.departPosLatProcedure) {
766 for (int i = 0; i < 10; i++) {
767 // we will try some random positions ...
768 posLat = RandHelper::rand(getWidth()) - getWidth() * 0.5;
769 if (isInsertionSuccess(&veh, speed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED)) {
770 return true;
771 }
772 }
774 }
775 // no break! continue with DepartPosLatDefinition::FREE
777 // systematically test all positions until a free lateral position is found
778 double posLatMin = -getWidth() * 0.5 + veh.getVehicleType().getWidth() * 0.5;
779 double posLatMax = getWidth() * 0.5 - veh.getVehicleType().getWidth() * 0.5;
780 for (posLat = posLatMin; posLat < posLatMax; posLat += MSGlobals::gLateralResolution) {
781 if (isInsertionSuccess(&veh, speed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED)) {
782 return true;
783 }
784 }
785 return false;
786 }
787 default:
788 break;
789 }
790 }
791 // try to insert
792 const bool success = isInsertionSuccess(&veh, speed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED);
793#ifdef DEBUG_EXTRAPOLATE_DEPARTPOS
794 if (DEBUG_COND2(&veh)) {
795 std::cout << SIMTIME << " veh=" << veh.getID() << " success=" << success << " extrapolate=" << myExtrapolateSubstepDepart << " delay=" << veh.getDepartDelay() << " speed=" << speed << "\n";
796 }
797#endif
798 if (success && myExtrapolateSubstepDepart && veh.getDepartDelay() > 0) {
799 SUMOTime relevantDelay = MIN2(DELTA_T, veh.getDepartDelay());
800 // try to compensate sub-step depart delay by moving the vehicle forward
801 speed = veh.getSpeed(); // may have been adapted in isInsertionSuccess
802 double dist = speed * STEPS2TIME(relevantDelay);
803 std::pair<MSVehicle* const, double> leaderInfo = getLeader(&veh, pos, veh.getBestLanesContinuation());
804 if (leaderInfo.first != nullptr) {
805 MSVehicle* leader = leaderInfo.first;
806 const double frontGapNeeded = veh.getCarFollowModel().getSecureGap(&veh, leader, speed, leader->getSpeed(),
807 leader->getCarFollowModel().getMaxDecel());
808 dist = MIN2(dist, leaderInfo.second - frontGapNeeded);
809 }
810 if (dist > 0) {
811 veh.executeFractionalMove(dist);
812 }
813 }
814 return success;
815}
816
817
818bool
819MSLane::checkFailure(const MSVehicle* aVehicle, double& speed, double& dist, const double nspeed, const bool patchSpeed, const std::string errorMsg, InsertionCheck check) const {
820 if (nspeed < speed) {
821 if (patchSpeed) {
822 speed = MIN2(nspeed, speed);
823 dist = aVehicle->getCarFollowModel().brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
824 } else if (speed > 0) {
825 if ((aVehicle->getInsertionChecks() & (int)check) == 0) {
826 return false;
827 }
829 // Check whether vehicle can stop at the given distance when applying emergency braking
830 double emergencyBrakeGap = 0.5 * speed * speed / aVehicle->getCarFollowModel().getEmergencyDecel();
831 if (emergencyBrakeGap <= dist) {
832 // Vehicle may stop in time with emergency deceleration
833 // still, emit a warning
834 WRITE_WARNINGF(TL("Vehicle '%' is inserted in an emergency situation, time=%."), aVehicle->getID(), time2string(SIMSTEP));
835 return false;
836 }
837 }
838
839 if (errorMsg != "") {
840 WRITE_ERRORF(TL("Vehicle '%' will not be able to depart on lane '%' with speed % (%), time=%."),
841 aVehicle->getID(), getID(), speed, errorMsg, time2string(SIMSTEP));
843 }
844 return true;
845 }
846 }
847 return false;
848}
849
850
851bool
853 double speed, double pos, double posLat, bool patchSpeed,
854 MSMoveReminder::Notification notification) {
855 int insertionChecks = aVehicle->getInsertionChecks();
856 if (pos < 0 || pos > myLength) {
857 // we may not start there
858 WRITE_WARNINGF(TL("Invalid departPos % given for vehicle '%', time=%. Inserting at lane end instead."),
859 pos, aVehicle->getID(), time2string(SIMSTEP));
860 pos = myLength;
861 }
862
863#ifdef DEBUG_INSERTION
864 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
865 std::cout << "\nIS_INSERTION_SUCCESS\n"
866 << SIMTIME << " lane=" << getID()
867 << " veh '" << aVehicle->getID()
868 << " bestLanes=" << toString(aVehicle->getBestLanesContinuation(this))
869 << " pos=" << pos
870 << " speed=" << speed
871 << " patchSpeed=" << patchSpeed
872 << "'\n";
873 }
874#endif
875
876 aVehicle->setTentativeLaneAndPosition(this, pos, posLat);
877 aVehicle->updateBestLanes(false, this);
878 const MSCFModel& cfModel = aVehicle->getCarFollowModel();
879 const std::vector<MSLane*>& bestLaneConts = aVehicle->getBestLanesContinuation(this);
880 std::vector<MSLane*>::const_iterator ri = bestLaneConts.begin();
881 double seen = getLength() - pos; // == distance from insertion position until the end of the currentLane
882 double dist = cfModel.brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
883 const bool isRail = aVehicle->isRail();
884 if (isRail && insertionChecks != (int)InsertionCheck::NONE
888 const MSDriveWay* dw = MSDriveWay::getDepartureDriveway(aVehicle);
889 MSEdgeVector occupied;
890 bool dwBlocked = false;
891#ifdef DEBUG_INSERTION
892 gDebugFlag4 = DEBUG_COND2(aVehicle) || DEBUG_COND;
893#endif
894 if (dw->foeDriveWayOccupied(false, aVehicle, occupied)) {
895 dwBlocked = true;
896#ifdef DEBUG_INSERTION
897 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
898 std::cout << " foe of driveway " + dw->getID() + " has occupied edges " + toString(occupied) << "\n";
899 }
900#endif
901 } else if (dw->sidingDeadlock(aVehicle)) {
902 dwBlocked = true;
903#ifdef DEBUG_INSERTION
904 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
905 std::cout << " insertion on driveway " + dw->getID() + " would cause deadlock\n";
906 }
907#endif
908 }
909#ifdef DEBUG_INSERTION
910 gDebugFlag4 = false;
911#endif
912 if (dwBlocked) {
913 setParameter("insertionBlocked:" + aVehicle->getID(), dw->getID());
914 return false;
915 }
916 }
917 if (getBidiLane() != nullptr && isRail) {
918 // do not insert if the bidirectional edge is occupied
919 if (getBidiLane()->getVehicleNumberWithPartials() > 0 && (insertionChecks & (int)InsertionCheck::BIDI) != 0) {
920#ifdef DEBUG_INSERTION
921 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
922 std::cout << " bidi-lane occupied\n";
923 }
924#endif
925 return false;
926 }
927 // do not insert the back of the train would be put onto an occupied bidi-lane
928 double backLength = aVehicle->getLength() - pos;
929 if (backLength > 0 && (insertionChecks & (int)InsertionCheck::BIDI) != 0) {
931 MSLane* bidi = pred == nullptr ? nullptr : pred->getBidiLane();
932 while (backLength > 0 && bidi != nullptr) {
933 if (bidi->getVehicleNumberWithPartials() > 0) {
934#ifdef DEBUG_INSERTION
935 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
936 std::cout << " bidi-lane furtherLanes occupied\n";
937 }
938#endif
939 return false;
940 }
941 backLength -= bidi->getLength();
942 pred = pred->getLogicalPredecessorLane();
943 bidi = pred == nullptr ? nullptr : pred->getBidiLane();
944 }
945 }
946 }
947 MSLink* firstRailSignal = nullptr;
948 double firstRailSignalDist = -1;
949 // whether speed may be patched for unavoidable reasons (stops, speedLimits, ...)
950 const bool patchSpeedSpecial = patchSpeed || aVehicle->getParameter().departSpeedProcedure != DepartSpeedDefinition::GIVEN;
951
952 // before looping through the continuation lanes, check if a stop is scheduled on this lane
953 // (the code is duplicated in the loop)
954 if (aVehicle->hasStops()) {
955 const MSStop& nextStop = aVehicle->getNextStop();
956 if (nextStop.lane == this) {
957 std::stringstream msg;
958 double distToStop, safeSpeed;
959 if (nextStop.pars.speed > 0) {
960 msg << "scheduled waypoint on lane '" << myID << "' too close";
961 distToStop = MAX2(0.0, nextStop.pars.startPos - pos);
962 safeSpeed = cfModel.freeSpeed(aVehicle, speed, distToStop, nextStop.pars.speed, true, MSCFModel::CalcReason::FUTURE);
963 } else {
964 msg << "scheduled stop on lane '" << myID << "' too close";
965 distToStop = nextStop.pars.endPos - pos;
966 safeSpeed = cfModel.stopSpeed(aVehicle, speed, distToStop, MSCFModel::CalcReason::FUTURE);
967 }
968 if (checkFailure(aVehicle, speed, dist, MAX2(0.0, safeSpeed), patchSpeedSpecial, msg.str(), InsertionCheck::STOP)) {
969 // we may not drive with the given velocity - we cannot stop at the stop
970 return false;
971 }
972 }
973 }
974 // check leader vehicle first because it could have influenced the departSpeed (for departSpeed=avg)
975 // get the pointer to the vehicle next in front of the given position
976 const MSLeaderInfo leaders = getLastVehicleInformation(aVehicle, 0, pos);
977 //if (aVehicle->getID() == "disabled") std::cout << " leaders=" << leaders.toString() << "\n";
978 const double nspeed = safeInsertionSpeed(aVehicle, -pos, leaders, speed);
979 if (nspeed == INVALID_SPEED || checkFailure(aVehicle, speed, dist, nspeed, patchSpeed, "", InsertionCheck::LEADER_GAP)) {
980 // we may not drive with the given velocity - we crash into the leader
981#ifdef DEBUG_INSERTION
982 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
983 std::cout << SIMTIME << " isInsertionSuccess lane=" << getID()
984 << " veh=" << aVehicle->getID()
985 << " pos=" << pos
986 << " posLat=" << posLat
987 << " patchSpeed=" << patchSpeed
988 << " speed=" << speed
989 << " nspeed=" << nspeed
990 << " leaders=" << leaders.toString()
991 << " failed (@700)!\n";
992 }
993#endif
994 return false;
995 }
996#ifdef DEBUG_INSERTION
997 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
998 std::cout << SIMTIME << " speed = " << speed << " nspeed = " << nspeed << " leaders=" << leaders.toString() << "\n";
999 }
1000#endif
1001
1002 const MSRoute& r = aVehicle->getRoute();
1003 MSRouteIterator ce = r.begin();
1004 int nRouteSuccs = 1;
1005 MSLane* currentLane = this;
1006 MSLane* nextLane = this;
1008 while ((seen < dist || (isRail && firstRailSignal == nullptr)) && ri != bestLaneConts.end()) {
1009 // get the next link used...
1010 std::vector<MSLink*>::const_iterator link = succLinkSec(*aVehicle, nRouteSuccs, *currentLane, bestLaneConts);
1011 // get the next used lane (including internal)
1012 if (currentLane->isLinkEnd(link)) {
1013 if (&currentLane->getEdge() == r.getLastEdge()) {
1014 // reached the end of the route
1016 const double remaining = seen + aVehicle->getArrivalPos() - currentLane->getLength();
1017 const double fspeed = cfModel.freeSpeed(aVehicle, speed, remaining, aVehicle->getParameter().arrivalSpeed, true, MSCFModel::CalcReason::FUTURE);
1018 if (checkFailure(aVehicle, speed, dist, fspeed,
1019 patchSpeedSpecial, "arrival speed too low", InsertionCheck::ARRIVAL_SPEED)) {
1020 // we may not drive with the given velocity - we cannot match the specified arrival speed
1021 return false;
1022 }
1023 }
1024 if (mayContinue(aVehicle) && hasUnsafeLink()) {
1025 // since the route is likely to continue we must be prepared for braking
1026 if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, seen),
1027 patchSpeedSpecial, "junction '" + currentLane->getEdge().getToJunction()->getID() + "' too close", InsertionCheck::JUNCTION)) {
1028 // we may not drive with the given velocity - we cannot stop at the junction
1029 return false;
1030 }
1031 }
1032 } else {
1033 // lane does not continue
1034 if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, seen),
1035 patchSpeedSpecial, "junction '" + currentLane->getEdge().getToJunction()->getID() + "' too close", InsertionCheck::JUNCTION)) {
1036 // we may not drive with the given velocity - we cannot stop at the junction
1037 return false;
1038 }
1039 }
1040 break;
1041 }
1042 if (isRail && firstRailSignal == nullptr) {
1043 std::string constraintInfo;
1044 bool isInsertionOrder;
1045 if (MSRailSignal::hasInsertionConstraint(*link, aVehicle, constraintInfo, isInsertionOrder)) {
1046 setParameter((isInsertionOrder ? "insertionOrder" : "insertionConstraint:")
1047 + aVehicle->getID(), constraintInfo);
1048#ifdef DEBUG_INSERTION
1049 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1050 std::cout << " insertion constraint at link " << (*link)->getDescription() << " not cleared \n";
1051 }
1052#endif
1053 return false;
1054 }
1055 }
1056
1057 // might also by a regular traffic_light instead of a rail_signal
1058 if (firstRailSignal == nullptr && (*link)->getTLLogic() != nullptr) {
1059 firstRailSignal = *link;
1060 firstRailSignalDist = seen;
1061 }
1062 nextLane = (*link)->getViaLaneOrLane();
1063 if (!(*link)->opened(arrivalTime, speed, speed, aVehicle->getVehicleType().getLength(), aVehicle->getImpatience(),
1064 cfModel.getMaxDecel(), 0, posLat, nullptr, false, aVehicle)
1065 || (*link)->railSignalWasPassed()
1066 || !(*link)->havePriority()
1067 || (*link)->getState() == LINKSTATE_ZIPPER) {
1068 // have to stop at junction
1069 std::string errorMsg = "";
1070 const LinkState state = (*link)->getState();
1071 if (state == LINKSTATE_MINOR
1072 || state == LINKSTATE_EQUAL
1073 || state == LINKSTATE_STOP
1074 || state == LINKSTATE_ALLWAY_STOP) {
1075 // no sense in trying later
1076 errorMsg = "unpriorised junction too close";
1077 } else if ((*link)->getTLLogic() != nullptr && !(*link)->getTLLogic()->getsMajorGreen((*link)->getTLIndex())) {
1078 // traffic light never turns 'G'?
1079 errorMsg = "tlLogic '" + (*link)->getTLLogic()->getID() + "' link " + toString((*link)->getTLIndex()) + " never switches to 'G'";
1080 }
1081 const double laneStopOffset = MAX2(getVehicleStopOffset(aVehicle),
1082 aVehicle->getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_STOPLINE_CROSSING_GAP, MSPModel::SAFETY_GAP) - (*link)->getDistToFoePedCrossing());
1083 const double remaining = seen - laneStopOffset;
1084 if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, remaining),
1085 patchSpeedSpecial, errorMsg, InsertionCheck::JUNCTION)) {
1086 // we may not drive with the given velocity - we cannot stop at the junction in time
1087#ifdef DEBUG_INSERTION
1088 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1089 std::cout << SIMTIME << " isInsertionSuccess lane=" << getID()
1090 << " veh=" << aVehicle->getID()
1091 << " patchSpeed=" << patchSpeed
1092 << " speed=" << speed
1093 << " remaining=" << remaining
1094 << " leader=" << currentLane->getLastVehicleInformation(aVehicle, 0, 0).toString()
1095 << " last=" << Named::getIDSecure(getLastAnyVehicle())
1096 << " meanSpeed=" << getMeanSpeed()
1097 << " failed (@926)!\n";
1098 }
1099#endif
1100 return false;
1101 }
1102#ifdef DEBUG_INSERTION
1103 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1104 std::cout << "trying insertion before minor link: "
1105 << "insertion speed = " << speed << " dist=" << dist
1106 << "\n";
1107 }
1108#endif
1109 if (seen >= aVehicle->getVehicleType().getMinGap()) {
1110 break;
1111 }
1112 } else if (nextLane->isInternal()) {
1113 double tmp = 0;
1114 bool dummyReq = true;
1115#ifdef DEBUG_INSERTION
1116 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1117 std::cout << "checking linkLeader for lane '" << nextLane->getID() << "'\n";
1118 gDebugFlag1 = true;
1119 }
1120#endif
1121 double nSpeed = speed;
1122 aVehicle->checkLinkLeader(nextLane->getLinkCont()[0], nextLane, seen + nextLane->getLength(), nullptr, nSpeed, tmp, tmp, dummyReq);
1123#ifdef DEBUG_INSERTION
1124 gDebugFlag1 = false;
1125#endif
1126 if (checkFailure(aVehicle, speed, dist, nSpeed, patchSpeed, "", InsertionCheck::LEADER_GAP)) {
1127 // we may not drive with the given velocity - there is a junction leader
1128#ifdef DEBUG_INSERTION
1129 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1130 std::cout << " linkLeader nSpeed=" << nSpeed << " failed (@1058)!\n";
1131 }
1132#endif
1133 return false;
1134 }
1135 }
1136 // check how next lane affects the journey
1137 if (nextLane != nullptr) {
1138
1139 // do not insert if the bidirectional edge is occupied before a railSignal has been encountered
1140 if (firstRailSignal == nullptr && nextLane->getBidiLane() != nullptr && nextLane->getBidiLane()->getVehicleNumberWithPartials() > 0) {
1141 if ((insertionChecks & (int)InsertionCheck::ONCOMING_TRAIN) != 0) {
1142#ifdef DEBUG_INSERTION
1143 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1144 std::cout << " nextLane=" << nextLane->getID() << " occupiedBidi\n";
1145 }
1146#endif
1147 return false;
1148 }
1149 }
1150
1151 // check if there are stops on the next lane that should be regarded
1152 // (this block is duplicated before the loop to deal with the insertion lane)
1153 if (aVehicle->hasStops()) {
1154 const MSStop& nextStop = aVehicle->getNextStop();
1155 if (nextStop.lane == nextLane) {
1156 std::stringstream msg;
1157 msg << "scheduled stop on lane '" << nextStop.lane->getID() << "' too close";
1158 const double distToStop = seen + nextStop.pars.endPos;
1159 if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, distToStop),
1160 patchSpeedSpecial, msg.str(), InsertionCheck::STOP)) {
1161 // we may not drive with the given velocity - we cannot stop at the stop
1162 return false;
1163 }
1164 }
1165 }
1166
1167 // check leader on next lane
1168 const MSLeaderInfo nextLeaders = nextLane->getLastVehicleInformation(aVehicle, 0, 0);
1169 if (nextLeaders.hasVehicles()) {
1170 const double nextLaneSpeed = nextLane->safeInsertionSpeed(aVehicle, seen, nextLeaders, speed);
1171#ifdef DEBUG_INSERTION
1172 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1173 std::cout << SIMTIME << " leader on lane '" << nextLane->getID() << "': " << nextLeaders.toString() << " nspeed=" << nextLaneSpeed << "\n";
1174 }
1175#endif
1176 if (nextLaneSpeed == INVALID_SPEED || checkFailure(aVehicle, speed, dist, nextLaneSpeed, patchSpeed, "", InsertionCheck::LEADER_GAP)) {
1177 // we may not drive with the given velocity - we crash into the leader
1178#ifdef DEBUG_INSERTION
1179 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1180 std::cout << " isInsertionSuccess lane=" << getID()
1181 << " veh=" << aVehicle->getID()
1182 << " pos=" << pos
1183 << " posLat=" << posLat
1184 << " patchSpeed=" << patchSpeed
1185 << " speed=" << speed
1186 << " nspeed=" << nextLaneSpeed
1187 << " nextLane=" << nextLane->getID()
1188 << " lead=" << nextLeaders.toString()
1189 << " failed (@641)!\n";
1190 }
1191#endif
1192 return false;
1193 }
1194 }
1195 if (!nextLane->checkForPedestrians(aVehicle, speed, dist, -seen, patchSpeed)) {
1196 return false;
1197 }
1198 // check next lane's maximum velocity
1199 const double freeSpeed = cfModel.freeSpeed(aVehicle, speed, seen, nextLane->getVehicleMaxSpeed(aVehicle), true, MSCFModel::CalcReason::FUTURE);
1200 if (freeSpeed < speed) {
1201 if (patchSpeedSpecial) {
1202 speed = freeSpeed;
1203 dist = cfModel.brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
1204 } else {
1205 if ((insertionChecks & (int)InsertionCheck::SPEED_LIMIT) != 0) {
1207 WRITE_WARNINGF(TL("Vehicle '%' is inserted too fast and will violate the speed limit on a lane '%', time=%."),
1208 aVehicle->getID(), nextLane->getID(), time2string(SIMSTEP));
1209 } else {
1210 // we may not drive with the given velocity - we would be too fast on the next lane
1211 WRITE_ERRORF(TL("Vehicle '%' will not be able to depart using the given velocity (slow lane ahead), time=%."), aVehicle->getID(), time2string(SIMSTEP));
1213 return false;
1214 }
1215 }
1216 }
1217 }
1218 // check traffic on next junction
1219 // we cannot use (*link)->opened because a vehicle without priority
1220 // may already be comitted to blocking the link and unable to stop
1221 const SUMOTime leaveTime = (*link)->getLeaveTime(arrivalTime, speed, speed, aVehicle->getVehicleType().getLength());
1222 if ((*link)->hasApproachingFoe(arrivalTime, leaveTime, speed, cfModel.getMaxDecel())) {
1223 if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, seen), patchSpeed, "", InsertionCheck::JUNCTION)) {
1224 // we may not drive with the given velocity - we crash at the junction
1225 return false;
1226 }
1227 }
1228 arrivalTime += TIME2STEPS(nextLane->getLength() / MAX2(speed, NUMERICAL_EPS));
1229 seen += nextLane->getLength();
1230 currentLane = nextLane;
1231 if ((*link)->getViaLane() == nullptr) {
1232 nRouteSuccs++;
1233 ++ce;
1234 ++ri;
1235 }
1236 }
1237 }
1238
1239 const MSLeaderDistanceInfo& followers = getFollowersOnConsecutive(aVehicle, aVehicle->getBackPositionOnLane(), false);
1240 for (int i = 0; i < followers.numSublanes(); ++i) {
1241 const MSVehicle* follower = followers[i].first;
1242 if (follower != nullptr) {
1243 const double backGapNeeded = follower->getCarFollowModel().getSecureGap(follower, aVehicle, follower->getSpeed(), speed, cfModel.getMaxDecel());
1244 if (followers[i].second < backGapNeeded
1245 && ((insertionChecks & (int)InsertionCheck::FOLLOWER_GAP) != 0
1246 || (followers[i].second < 0 && (insertionChecks & (int)InsertionCheck::COLLISION) != 0))) {
1247 // too close to the follower on this lane
1248#ifdef DEBUG_INSERTION
1249 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1250 std::cout << SIMTIME << " isInsertionSuccess lane=" << getID()
1251 << " veh=" << aVehicle->getID()
1252 << " pos=" << pos
1253 << " posLat=" << posLat
1254 << " speed=" << speed
1255 << " nspeed=" << nspeed
1256 << " follower=" << follower->getID()
1257 << " backGapNeeded=" << backGapNeeded
1258 << " gap=" << followers[i].second
1259 << " failure (@719)!\n";
1260 }
1261#endif
1262 return false;
1263 }
1264 }
1265 }
1266
1267 if (!checkForPedestrians(aVehicle, speed, dist, pos, patchSpeed)) {
1268 return false;
1269 }
1270
1271 MSLane* shadowLane = aVehicle->getLaneChangeModel().getShadowLane(this);
1272#ifdef DEBUG_INSERTION
1273 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1274 std::cout << " shadowLane=" << Named::getIDSecure(shadowLane) << "\n";
1275 }
1276#endif
1277 if (shadowLane != nullptr) {
1278 const MSLeaderDistanceInfo& shadowFollowers = shadowLane->getFollowersOnConsecutive(aVehicle, aVehicle->getBackPositionOnLane(), false);
1279 for (int i = 0; i < shadowFollowers.numSublanes(); ++i) {
1280 const MSVehicle* follower = shadowFollowers[i].first;
1281 if (follower != nullptr) {
1282 const double backGapNeeded = follower->getCarFollowModel().getSecureGap(follower, aVehicle, follower->getSpeed(), speed, cfModel.getMaxDecel());
1283 if (shadowFollowers[i].second < backGapNeeded
1284 && ((insertionChecks & (int)InsertionCheck::FOLLOWER_GAP) != 0
1285 || (shadowFollowers[i].second < 0 && (insertionChecks & (int)InsertionCheck::COLLISION) != 0))) {
1286 // too close to the follower on this lane
1287#ifdef DEBUG_INSERTION
1288 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1289 std::cout << SIMTIME
1290 << " isInsertionSuccess shadowlane=" << shadowLane->getID()
1291 << " veh=" << aVehicle->getID()
1292 << " pos=" << pos
1293 << " posLat=" << posLat
1294 << " speed=" << speed
1295 << " nspeed=" << nspeed
1296 << " follower=" << follower->getID()
1297 << " backGapNeeded=" << backGapNeeded
1298 << " gap=" << shadowFollowers[i].second
1299 << " failure (@812)!\n";
1300 }
1301#endif
1302 return false;
1303 }
1304 }
1305 }
1306 const MSLeaderInfo& ahead = shadowLane->getLastVehicleInformation(nullptr, 0, aVehicle->getPositionOnLane(), false);
1307 for (int i = 0; i < ahead.numSublanes(); ++i) {
1308 const MSVehicle* veh = ahead[i];
1309 if (veh != nullptr) {
1310 const double gap = veh->getBackPositionOnLane(shadowLane) - aVehicle->getPositionOnLane() - aVehicle->getVehicleType().getMinGap();
1311 const double gapNeeded = aVehicle->getCarFollowModel().getSecureGap(aVehicle, veh, speed, veh->getSpeed(), veh->getCarFollowModel().getMaxDecel());
1312 if (gap < gapNeeded
1313 && ((insertionChecks & (int)InsertionCheck::LEADER_GAP) != 0
1314 || (gap < 0 && (insertionChecks & (int)InsertionCheck::COLLISION) != 0))) {
1315 // too close to the shadow leader
1316#ifdef DEBUG_INSERTION
1317 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1318 std::cout << SIMTIME
1319 << " isInsertionSuccess shadowlane=" << shadowLane->getID()
1320 << " veh=" << aVehicle->getID()
1321 << " pos=" << pos
1322 << " posLat=" << posLat
1323 << " speed=" << speed
1324 << " nspeed=" << nspeed
1325 << " leader=" << veh->getID()
1326 << " gapNeeded=" << gapNeeded
1327 << " gap=" << gap
1328 << " failure (@842)!\n";
1329 }
1330#endif
1331 return false;
1332 }
1333 }
1334 }
1335 }
1336 if (followers.numFreeSublanes() > 0) {
1337 // check approaching vehicles to prevent rear-end collisions
1338 const double backOffset = pos - aVehicle->getVehicleType().getLength();
1339 const double missingRearGap = getMissingRearGap(aVehicle, backOffset, speed);
1340 if (missingRearGap > 0
1341 && (insertionChecks & (int)InsertionCheck::LEADER_GAP) != 0) {
1342 // too close to a follower
1343#ifdef DEBUG_INSERTION
1344 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1345 std::cout << SIMTIME
1346 << " isInsertionSuccess lane=" << getID()
1347 << " veh=" << aVehicle->getID()
1348 << " pos=" << pos
1349 << " posLat=" << posLat
1350 << " speed=" << speed
1351 << " nspeed=" << nspeed
1352 << " missingRearGap=" << missingRearGap
1353 << " failure (@728)!\n";
1354 }
1355#endif
1356 return false;
1357 }
1358 }
1359 if (insertionChecks == (int)InsertionCheck::NONE) {
1360 speed = MAX2(0.0, speed);
1361 }
1362 // may got negative while adaptation
1363 if (speed < 0) {
1364#ifdef DEBUG_INSERTION
1365 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1366 std::cout << SIMTIME
1367 << " isInsertionSuccess lane=" << getID()
1368 << " veh=" << aVehicle->getID()
1369 << " pos=" << pos
1370 << " posLat=" << posLat
1371 << " speed=" << speed
1372 << " nspeed=" << nspeed
1373 << " failed (@733)!\n";
1374 }
1375#endif
1376 return false;
1377 }
1378 const int bestLaneOffset = aVehicle->getBestLaneOffset();
1379 const double extraReservation = aVehicle->getLaneChangeModel().getExtraReservation(bestLaneOffset);
1380 if (extraReservation > 0) {
1381 std::stringstream msg;
1382 msg << "too many lane changes required on lane '" << myID << "'";
1383 // we need to take into acount one extra actionStep of delay due to #3665
1384 double distToStop = aVehicle->getBestLaneDist() - pos - extraReservation - speed * aVehicle->getActionStepLengthSecs();
1385 if (distToStop >= 0) {
1386 double stopSpeed = cfModel.stopSpeed(aVehicle, speed, distToStop, MSCFModel::CalcReason::FUTURE);
1387#ifdef DEBUG_INSERTION
1388 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1389 std::cout << "\nIS_INSERTION_SUCCESS\n"
1390 << SIMTIME << " veh=" << aVehicle->getID() << " bestLaneOffset=" << bestLaneOffset << " bestLaneDist=" << aVehicle->getBestLaneDist() << " extraReservation=" << extraReservation
1391 << " distToStop=" << distToStop << " v=" << speed << " v2=" << stopSpeed << "\n";
1392 }
1393#endif
1394 if (checkFailure(aVehicle, speed, distToStop, MAX2(0.0, stopSpeed),
1395 patchSpeedSpecial, msg.str(), InsertionCheck::LANECHANGE)) {
1396 // we may not drive with the given velocity - we cannot reserve enough space for lane changing
1397 return false;
1398 }
1399 }
1400 }
1401 // enter
1402 incorporateVehicle(aVehicle, pos, speed, posLat, find_if(myVehicles.begin(), myVehicles.end(), [&](MSVehicle * const v) {
1403 return v->getPositionOnLane() >= pos;
1404 }), notification);
1405#ifdef DEBUG_INSERTION
1406 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1407 std::cout << SIMTIME
1408 << " isInsertionSuccess lane=" << getID()
1409 << " veh=" << aVehicle->getID()
1410 << " pos=" << pos
1411 << " posLat=" << posLat
1412 << " speed=" << speed
1413 << " nspeed=" << nspeed
1414 << "\n myVehicles=" << toString(myVehicles)
1415 << " myPartial=" << toString(myPartialVehicles)
1416 << " myManeuverReservations=" << toString(myManeuverReservations)
1417 << "\n success!\n";
1418 }
1419#endif
1420 if (isRail) {
1421 unsetParameter("insertionConstraint:" + aVehicle->getID());
1422 unsetParameter("insertionOrder:" + aVehicle->getID());
1423 unsetParameter("insertionBlocked:" + aVehicle->getID());
1424 // rail_signal (not traffic_light) requires approach information for
1425 // switching correctly at the start of the next simulation step
1426 if (firstRailSignal != nullptr && firstRailSignal->getJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
1427 aVehicle->registerInsertionApproach(firstRailSignal, firstRailSignalDist);
1428 }
1429 }
1430 return true;
1431}
1432
1433
1434void
1435MSLane::forceVehicleInsertion(MSVehicle* veh, double pos, MSMoveReminder::Notification notification, double posLat) {
1436 veh->updateBestLanes(true, this);
1437 bool dummy;
1438 const double speed = veh->hasDeparted() ? veh->getSpeed() : getDepartSpeed(*veh, dummy);
1439 incorporateVehicle(veh, pos, speed, posLat, find_if(myVehicles.begin(), myVehicles.end(), [&](MSVehicle * const v) {
1440 return v->getPositionOnLane() >= pos;
1441 }), notification);
1442}
1443
1444
1445double
1446MSLane::safeInsertionSpeed(const MSVehicle* veh, double seen, const MSLeaderInfo& leaders, double speed) {
1447 double nspeed = speed;
1448#ifdef DEBUG_INSERTION
1449 if (DEBUG_COND2(veh)) {
1450 std::cout << SIMTIME << " safeInsertionSpeed veh=" << veh->getID() << " speed=" << speed << "\n";
1451 }
1452#endif
1453 for (int i = 0; i < leaders.numSublanes(); ++i) {
1454 const MSVehicle* leader = leaders[i];
1455 if (leader != nullptr) {
1456 double gap = leader->getBackPositionOnLane(this) + seen - veh->getVehicleType().getMinGap();
1457 if (leader->getLane() == getBidiLane()) {
1458 // use distance to front position and account for movement
1459 gap -= (leader->getLength() + leader->getBrakeGap(true));
1460 }
1461 if (gap < 0) {
1462#ifdef DEBUG_INSERTION
1463 if (DEBUG_COND2(veh)) {
1464 std::cout << " leader=" << leader->getID() << " bPos=" << leader->getBackPositionOnLane(this) << " gap=" << gap << "\n";
1465 }
1466#endif
1467 if ((veh->getInsertionChecks() & (int)InsertionCheck::COLLISION) != 0) {
1468 return INVALID_SPEED;
1469 } else {
1470 return 0;
1471 }
1472 }
1473 nspeed = MIN2(nspeed,
1474 veh->getCarFollowModel().insertionFollowSpeed(veh, speed, gap, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel(), leader));
1475#ifdef DEBUG_INSERTION
1476 if (DEBUG_COND2(veh)) {
1477 std::cout << " leader=" << leader->getID() << " bPos=" << leader->getBackPositionOnLane(this) << " gap=" << gap << " nspeed=" << nspeed << "\n";
1478 }
1479#endif
1480 }
1481 }
1482 return nspeed;
1483}
1484
1485
1486// ------ Handling vehicles lapping into lanes ------
1487const MSLeaderInfo
1488MSLane::getLastVehicleInformation(const MSVehicle* ego, double latOffset, double minPos, bool allowCached, const MSVehicle* ignore) const {
1489#ifdef DEBUG_SURROUNDING
1490 if (DEBUG_COND2(ego) || DEBUG_COND) {
1491 std::cout << " getLastVehicleInformation lane=" << getID() << " ego=" << Named::getIDSecure(ego) << " latOffset=" << latOffset << " minPos=" << minPos << " allowCached=" << allowCached
1492 << " hasCache=" << (myLeaderInfoTime >= MSNet::getInstance()->getCurrentTimeStep()) << "\n";
1493 }
1494#endif
1495 if (myLeaderInfoTime < MSNet::getInstance()->getCurrentTimeStep() || ego != nullptr || minPos > 0 || !allowCached) {
1496 MSLeaderInfo leaderTmp(myWidth, ego, latOffset);
1498 int freeSublanes = 1; // number of sublanes for which no leader was found
1499 //if (ego->getID() == "disabled" && SIMTIME == 58) {
1500 // std::cout << "DEBUG\n";
1501 //}
1502 const MSVehicle* veh = *last;
1503 while (freeSublanes > 0 && veh != nullptr) {
1504#ifdef DEBUG_PLAN_MOVE
1505 if (DEBUG_COND2(ego) || DEBUG_COND) {
1506 gDebugFlag1 = true;
1507 std::cout << " getLastVehicleInformation lane=" << getID() << " minPos=" << minPos << " veh=" << veh->getID() << " pos=" << veh->getPositionOnLane(this) << "\n";
1508 }
1509#endif
1510 if (veh != ego && veh != ignore && MAX2(0.0, veh->getPositionOnLane(this)) >= minPos) {
1511 const double vehLatOffset = veh->getLatOffset(this);
1512 freeSublanes = leaderTmp.addLeader(veh, true, vehLatOffset);
1513#ifdef DEBUG_PLAN_MOVE
1514 if (DEBUG_COND2(ego) || DEBUG_COND) {
1515 std::cout << " latOffset=" << vehLatOffset << " newLeaders=" << leaderTmp.toString() << "\n";
1516 }
1517#endif
1518 }
1519 veh = *(++last);
1520 }
1521 if (ego == nullptr && minPos == 0) {
1522#ifdef HAVE_FOX
1523 ScopedLocker<> lock(myLeaderInfoMutex, MSGlobals::gNumSimThreads > 1);
1524#endif
1525 // update cached value
1526 myLeaderInfo = leaderTmp;
1528 }
1529#ifdef DEBUG_PLAN_MOVE
1530 //if (DEBUG_COND2(ego)) std::cout << SIMTIME
1531 // << " getLastVehicleInformation lane=" << getID()
1532 // << " ego=" << Named::getIDSecure(ego)
1533 // << "\n"
1534 // << " vehicles=" << toString(myVehicles)
1535 // << " partials=" << toString(myPartialVehicles)
1536 // << "\n"
1537 // << " result=" << leaderTmp.toString()
1538 // << " cached=" << myLeaderInfo.toString()
1539 // << " myLeaderInfoTime=" << myLeaderInfoTime
1540 // << "\n";
1541 gDebugFlag1 = false;
1542#endif
1543 return leaderTmp;
1544 }
1545 return myLeaderInfo;
1546}
1547
1548
1549const MSLeaderInfo
1550MSLane::getFirstVehicleInformation(const MSVehicle* ego, double latOffset, bool onlyFrontOnLane, double maxPos, bool allowCached) const {
1551#ifdef HAVE_FOX
1552 ScopedLocker<> lock(myFollowerInfoMutex, MSGlobals::gNumSimThreads > 1);
1553#endif
1554 if (myFollowerInfoTime < MSNet::getInstance()->getCurrentTimeStep() || ego != nullptr || maxPos < myLength || !allowCached || onlyFrontOnLane) {
1555 // XXX separate cache for onlyFrontOnLane = true
1556 MSLeaderInfo followerTmp(myWidth, ego, latOffset);
1558 int freeSublanes = 1; // number of sublanes for which no leader was found
1559 const MSVehicle* veh = *first;
1560 while (freeSublanes > 0 && veh != nullptr) {
1561#ifdef DEBUG_PLAN_MOVE
1562 if (DEBUG_COND2(ego)) {
1563 std::cout << " veh=" << veh->getID() << " pos=" << veh->getPositionOnLane(this) << " maxPos=" << maxPos << "\n";
1564 }
1565#endif
1566 if (veh != ego && veh->getPositionOnLane(this) <= maxPos
1567 && (!onlyFrontOnLane || veh->isFrontOnLane(this))) {
1568 //const double vehLatOffset = veh->getLane()->getRightSideOnEdge() - getRightSideOnEdge();
1569 const double vehLatOffset = veh->getLatOffset(this);
1570#ifdef DEBUG_PLAN_MOVE
1571 if (DEBUG_COND2(ego)) {
1572 std::cout << " veh=" << veh->getID() << " latOffset=" << vehLatOffset << "\n";
1573 }
1574#endif
1575 freeSublanes = followerTmp.addLeader(veh, true, vehLatOffset);
1576 }
1577 veh = *(++first);
1578 }
1579 if (ego == nullptr && maxPos == std::numeric_limits<double>::max()) {
1580 // update cached value
1581 myFollowerInfo = followerTmp;
1583 }
1584#ifdef DEBUG_PLAN_MOVE
1585 //if (DEBUG_COND2(ego)) std::cout << SIMTIME
1586 // << " getFirstVehicleInformation lane=" << getID()
1587 // << " ego=" << Named::getIDSecure(ego)
1588 // << "\n"
1589 // << " vehicles=" << toString(myVehicles)
1590 // << " partials=" << toString(myPartialVehicles)
1591 // << "\n"
1592 // << " result=" << followerTmp.toString()
1593 // //<< " cached=" << myFollowerInfo.toString()
1594 // << " myLeaderInfoTime=" << myLeaderInfoTime
1595 // << "\n";
1596#endif
1597 return followerTmp;
1598 }
1599 return myFollowerInfo;
1600}
1601
1602
1603// ------ ------
1604void
1606 assert(myVehicles.size() != 0);
1607 double cumulatedVehLength = 0.;
1608 MSLeaderInfo leaders(myWidth);
1609
1610 // iterate over myVehicles, myPartialVehicles, and myManeuverReservations merge-sort style
1611 VehCont::reverse_iterator veh = myVehicles.rbegin();
1612 VehCont::reverse_iterator vehPart = myPartialVehicles.rbegin();
1613 VehCont::reverse_iterator vehRes = myManeuverReservations.rbegin();
1614#ifdef DEBUG_PLAN_MOVE
1615 if (DEBUG_COND) std::cout
1616 << "\n"
1617 << SIMTIME
1618 << " planMovements() lane=" << getID()
1619 << "\n vehicles=" << toString(myVehicles)
1620 << "\n partials=" << toString(myPartialVehicles)
1621 << "\n reservations=" << toString(myManeuverReservations)
1622 << "\n";
1623#endif
1625 for (; veh != myVehicles.rend(); ++veh) {
1626#ifdef DEBUG_PLAN_MOVE
1627 if (DEBUG_COND2((*veh))) {
1628 std::cout << " plan move for: " << (*veh)->getID();
1629 }
1630#endif
1631 updateLeaderInfo(*veh, vehPart, vehRes, leaders); // 36ns with 8 threads, 9ns with 1
1632#ifdef DEBUG_PLAN_MOVE
1633 if (DEBUG_COND2((*veh))) {
1634 std::cout << " leaders=" << leaders.toString() << "\n";
1635 }
1636#endif
1637 (*veh)->planMove(t, leaders, cumulatedVehLength); // 4800ns with 8 threads, 3100 with 1
1638 cumulatedVehLength += (*veh)->getVehicleType().getLengthWithGap();
1639 leaders.addLeader(*veh, false, 0);
1640 }
1641}
1642
1643
1644void
1646 for (MSVehicle* const veh : myVehicles) {
1647 veh->setApproachingForAllLinks();
1648 }
1649}
1650
1651
1652void
1653MSLane::updateLeaderInfo(const MSVehicle* veh, VehCont::reverse_iterator& vehPart, VehCont::reverse_iterator& vehRes, MSLeaderInfo& ahead) const {
1654 bool morePartialVehsAhead = vehPart != myPartialVehicles.rend();
1655 bool moreReservationsAhead = vehRes != myManeuverReservations.rend();
1656 bool nextToConsiderIsPartial;
1657
1658 // Determine relevant leaders for veh
1659 while (moreReservationsAhead || morePartialVehsAhead) {
1660 if ((!moreReservationsAhead || (*vehRes)->getPositionOnLane(this) <= veh->getPositionOnLane())
1661 && (!morePartialVehsAhead || (*vehPart)->getPositionOnLane(this) <= veh->getPositionOnLane())) {
1662 // All relevant downstream vehicles have been collected.
1663 break;
1664 }
1665
1666 // Check whether next farthest relevant vehicle downstream is a partial vehicle or a maneuver reservation
1667 if (moreReservationsAhead && !morePartialVehsAhead) {
1668 nextToConsiderIsPartial = false;
1669 } else if (morePartialVehsAhead && !moreReservationsAhead) {
1670 nextToConsiderIsPartial = true;
1671 } else {
1672 assert(morePartialVehsAhead && moreReservationsAhead);
1673 // Add farthest downstream vehicle first
1674 nextToConsiderIsPartial = (*vehPart)->getPositionOnLane(this) > (*vehRes)->getPositionOnLane(this);
1675 }
1676 // Add appropriate leader information
1677 if (nextToConsiderIsPartial) {
1678 const double latOffset = (*vehPart)->getLatOffset(this);
1679#ifdef DEBUG_PLAN_MOVE
1680 if (DEBUG_COND) {
1681 std::cout << " partial ahead: " << (*vehPart)->getID() << " latOffset=" << latOffset << "\n";
1682 }
1683#endif
1684 if (!(MSGlobals::gLaneChangeDuration > 0 && (*vehPart)->getLaneChangeModel().isOpposite()
1685 && !(*vehPart)->getLaneChangeModel().isChangingLanes())) {
1686 ahead.addLeader(*vehPart, false, latOffset);
1687 }
1688 ++vehPart;
1689 morePartialVehsAhead = vehPart != myPartialVehicles.rend();
1690 } else {
1691 const double latOffset = (*vehRes)->getLatOffset(this);
1692#ifdef DEBUG_PLAN_MOVE
1693 if (DEBUG_COND) {
1694 std::cout << " reservation ahead: " << (*vehRes)->getID() << " latOffset=" << latOffset << "\n";
1695 }
1696#endif
1697 ahead.addLeader(*vehRes, false, latOffset);
1698 ++vehRes;
1699 moreReservationsAhead = vehRes != myManeuverReservations.rend();
1700 }
1701 }
1702}
1703
1704
1705void
1706MSLane::detectCollisions(SUMOTime timestep, const std::string& stage) {
1707 myNeedsCollisionCheck = false;
1708#ifdef DEBUG_COLLISIONS
1709 if (DEBUG_COND) {
1710 std::vector<const MSVehicle*> all;
1711 for (AnyVehicleIterator last = anyVehiclesBegin(); last != anyVehiclesEnd(); ++last) {
1712 all.push_back(*last);
1713 }
1714 std::cout << SIMTIME << " detectCollisions stage=" << stage << " lane=" << getID() << ":\n"
1715 << " vehs=" << toString(myVehicles) << "\n"
1716 << " part=" << toString(myPartialVehicles) << "\n"
1717 << " all=" << toString(all) << "\n"
1718 << "\n";
1719 }
1720#endif
1721
1723 return;
1724 }
1725
1726 std::set<const MSVehicle*, ComparatorNumericalIdLess> toRemove;
1727 std::set<const MSVehicle*, ComparatorNumericalIdLess> toTeleport;
1729 myNeedsCollisionCheck = true; // always check
1730#ifdef DEBUG_JUNCTION_COLLISIONS
1731 if (DEBUG_COND) {
1732 std::cout << SIMTIME << " detect junction Collisions stage=" << stage << " lane=" << getID() << ":\n"
1733 << " vehs=" << toString(myVehicles) << "\n"
1734 << " part=" << toString(myPartialVehicles) << "\n"
1735 << "\n";
1736 }
1737#endif
1738 assert(myLinks.size() == 1);
1739 const std::vector<const MSLane*>& foeLanes = myLinks.front()->getFoeLanes();
1740 // save the iterator, it might get modified, see #8842
1742 for (AnyVehicleIterator veh = anyVehiclesBegin(); veh != end; ++veh) {
1743 const MSVehicle* const collider = *veh;
1744 //std::cout << " collider " << collider->getID() << "\n";
1745 PositionVector colliderBoundary = collider->getBoundingBox(myCheckJunctionCollisionMinGap);
1746 for (const MSLane* const foeLane : foeLanes) {
1747#ifdef DEBUG_JUNCTION_COLLISIONS
1748 if (DEBUG_COND) {
1749 std::cout << " foeLane " << foeLane->getID()
1750 << " foeVehs=" << toString(foeLane->myVehicles)
1751 << " foePart=" << toString(foeLane->myPartialVehicles) << "\n";
1752 }
1753#endif
1754 MSLane::AnyVehicleIterator foeEnd = foeLane->anyVehiclesEnd();
1755 for (MSLane::AnyVehicleIterator it_veh = foeLane->anyVehiclesBegin(); it_veh != foeEnd; ++it_veh) {
1756 const MSVehicle* const victim = *it_veh;
1757 if (victim == collider) {
1758 // may happen if the vehicles lane and shadow lane are siblings
1759 continue;
1760 }
1761#ifdef DEBUG_JUNCTION_COLLISIONS
1762 if (DEBUG_COND && DEBUG_COND2(collider)) {
1763 std::cout << SIMTIME << " foe=" << victim->getID()
1764 << " bound=" << colliderBoundary << " foeBound=" << victim->getBoundingBox()
1765 << " overlaps=" << colliderBoundary.overlapsWith(victim->getBoundingBox())
1766 << " poly=" << collider->getBoundingPoly()
1767 << " foePoly=" << victim->getBoundingPoly()
1768 << " overlaps2=" << collider->getBoundingPoly().overlapsWith(victim->getBoundingPoly())
1769 << "\n";
1770 }
1771#endif
1772 if (MSGlobals::gIgnoreJunctionBlocker < std::numeric_limits<SUMOTime>::max()) {
1775 // ignored vehicles should not tigger collision
1776 continue;
1777 }
1778 }
1779
1780 if (colliderBoundary.overlapsWith(victim->getBoundingBox())) {
1781 // make a detailed check
1782 PositionVector boundingPoly = collider->getBoundingPoly();
1784 // junction leader is the victim (collider must still be on junction)
1785 assert(isInternal());
1786 if (victim->getLane()->isInternal() && victim->isLeader(myLinks.front(), collider, -1)) {
1787 foeLane->handleCollisionBetween(timestep, stage, victim, collider, -1, 0, toRemove, toTeleport);
1788 } else {
1789 handleCollisionBetween(timestep, stage, collider, victim, -1, 0, toRemove, toTeleport);
1790 }
1791 }
1792 }
1793 }
1794 detectPedestrianJunctionCollision(collider, colliderBoundary, foeLane, timestep, stage, toRemove, toTeleport);
1795 }
1796 if (myLinks.front()->getWalkingAreaFoe() != nullptr) {
1797 detectPedestrianJunctionCollision(collider, colliderBoundary, myLinks.front()->getWalkingAreaFoe(), timestep, stage, toRemove, toTeleport);
1798 }
1799 if (myLinks.front()->getWalkingAreaFoeExit() != nullptr) {
1800 detectPedestrianJunctionCollision(collider, colliderBoundary, myLinks.front()->getWalkingAreaFoeExit(), timestep, stage, toRemove, toTeleport);
1801 }
1802 }
1803 }
1804
1805
1807#ifdef DEBUG_PEDESTRIAN_COLLISIONS
1808 if (DEBUG_COND) {
1809 std::cout << SIMTIME << " detect pedestrian collisions stage=" << stage << " lane=" << getID() << "\n";
1810 }
1811#endif
1813 for (AnyVehicleIterator it_v = anyVehiclesBegin(); it_v != v_end; ++it_v) {
1814 const MSVehicle* v = *it_v;
1815 double back = v->getBackPositionOnLane(this);
1816 const double length = v->getVehicleType().getLength();
1817 const double right = v->getRightSideOnEdge(this) - getRightSideOnEdge();
1818 if (v->getLane() == getBidiLane()) {
1819 // use the front position for checking
1820 back -= length;
1821 }
1822 PersonDist leader = nextBlocking(back, right, right + v->getVehicleType().getWidth());
1823#ifdef DEBUG_PEDESTRIAN_COLLISIONS
1824 if (DEBUG_COND && DEBUG_COND2(v)) {
1825 std::cout << SIMTIME << " back=" << back << " right=" << right << " person=" << Named::getIDSecure(leader.first)
1826 << " dist=" << leader.second << " jammed=" << (leader.first == nullptr ? false : leader.first->isJammed()) << "\n";
1827 }
1828#endif
1829 if (leader.first != 0 && leader.second < length && !leader.first->isJammed()) {
1831 // aircraft wings and body are above walking level
1832 continue;
1833 }
1834 const double gap = leader.second - length;
1835 handleIntermodalCollisionBetween(timestep, stage, v, leader.first, gap, "sharedLane", toRemove, toTeleport);
1836 }
1837 }
1838 }
1839
1840 if (myVehicles.size() == 0) {
1841 return;
1842 }
1843 if (!MSGlobals::gSublane) {
1844 // no sublanes
1845 VehCont::reverse_iterator lastVeh = myVehicles.rend() - 1;
1846 for (VehCont::reverse_iterator pred = myVehicles.rbegin(); pred != lastVeh; ++pred) {
1847 VehCont::reverse_iterator veh = pred + 1;
1848 detectCollisionBetween(timestep, stage, *veh, *pred, toRemove, toTeleport);
1849 }
1850 if (myPartialVehicles.size() > 0) {
1851 detectCollisionBetween(timestep, stage, *lastVeh, myPartialVehicles.front(), toRemove, toTeleport);
1852 }
1853 if (getBidiLane() != nullptr) {
1854 // bidirectional railway
1855 MSLane* bidiLane = getBidiLane();
1856 if (bidiLane->getVehicleNumberWithPartials() > 0) {
1857 for (auto veh = myVehicles.begin(); veh != myVehicles.end(); ++veh) {
1858 double high = (*veh)->getPositionOnLane(this);
1859 double low = (*veh)->getBackPositionOnLane(this);
1860 if (stage == MSNet::STAGE_MOVEMENTS) {
1861 // use previous back position to catch trains that
1862 // "jump" through each other
1863 low -= SPEED2DIST((*veh)->getSpeed());
1864 }
1865 for (AnyVehicleIterator veh2 = bidiLane->anyVehiclesBegin(); veh2 != bidiLane->anyVehiclesEnd(); ++veh2) {
1866 // self-collisions might legitemately occur when a long train loops back on itself
1867 if (*veh == *veh2 && !(*veh)->isRail()) {
1868 continue;
1869 }
1870 if ((*veh)->getLane() == (*veh2)->getLane() ||
1871 (*veh)->getLane() == (*veh2)->getBackLane() ||
1872 (*veh)->getBackLane() == (*veh2)->getLane()) {
1873 // vehicles are not in a bidi relation
1874 continue;
1875 }
1876 double low2 = myLength - (*veh2)->getPositionOnLane(bidiLane);
1877 double high2 = myLength - (*veh2)->getBackPositionOnLane(bidiLane);
1878 if (stage == MSNet::STAGE_MOVEMENTS) {
1879 // use previous back position to catch trains that
1880 // "jump" through each other
1881 high2 += SPEED2DIST((*veh2)->getSpeed());
1882 }
1883 if (!(high < low2 || high2 < low)) {
1884#ifdef DEBUG_COLLISIONS
1885 if (DEBUG_COND) {
1886 std::cout << SIMTIME << " bidi-collision veh=" << (*veh)->getID() << " bidiVeh=" << (*veh2)->getID()
1887 << " vehFurther=" << toString((*veh)->getFurtherLanes())
1888 << " high=" << high << " low=" << low << " high2=" << high2 << " low2=" << low2 << "\n";
1889 }
1890#endif
1891 // the faster vehicle is at fault
1892 MSVehicle* collider = const_cast<MSVehicle*>(*veh);
1893 MSVehicle* victim = const_cast<MSVehicle*>(*veh2);
1894 if (collider->getSpeed() < victim->getSpeed()) {
1895 std::swap(victim, collider);
1896 }
1897 handleCollisionBetween(timestep, stage, collider, victim, -1, 0, toRemove, toTeleport);
1898 }
1899 }
1900 }
1901 }
1902 }
1903 } else {
1904 // in the sublane-case it is insufficient to check the vehicles ordered
1905 // by their front position as there might be more than 2 vehicles next to each
1906 // other on the same lane
1907 // instead, a moving-window approach is used where all vehicles that
1908 // overlap in the longitudinal direction receive pairwise checks
1909 // XXX for efficiency, all lanes of an edge should be checked together
1910 // (lanechanger-style)
1911
1912 // XXX quick hack: check each in myVehicles against all others
1913 for (AnyVehicleIterator veh = anyVehiclesBegin(); veh != anyVehiclesEnd(); ++veh) {
1914 MSVehicle* follow = (MSVehicle*)*veh;
1915 for (AnyVehicleIterator veh2 = anyVehiclesBegin(); veh2 != anyVehiclesEnd(); ++veh2) {
1916 MSVehicle* lead = (MSVehicle*)*veh2;
1917 if (lead == follow) {
1918 continue;
1919 }
1920 if (lead->getPositionOnLane(this) < follow->getPositionOnLane(this)) {
1921 continue;
1922 }
1923 if (detectCollisionBetween(timestep, stage, follow, lead, toRemove, toTeleport)) {
1924 // XXX what about collisions with multiple leaders at once?
1925 break;
1926 }
1927 }
1928 }
1929 }
1930
1931
1932 for (std::set<const MSVehicle*, ComparatorNumericalIdLess>::iterator it = toRemove.begin(); it != toRemove.end(); ++it) {
1933 MSVehicle* veh = const_cast<MSVehicle*>(*it);
1934 MSLane* vehLane = veh->getMutableLane();
1936 if (toTeleport.count(veh) > 0) {
1937 MSVehicleTransfer::getInstance()->add(timestep, veh);
1938 } else {
1941 }
1942 }
1943}
1944
1945
1946void
1947MSLane::detectPedestrianJunctionCollision(const MSVehicle* collider, const PositionVector& colliderBoundary, const MSLane* foeLane,
1948 SUMOTime timestep, const std::string& stage,
1949 std::set<const MSVehicle*, ComparatorNumericalIdLess>& toRemove,
1950 std::set<const MSVehicle*, ComparatorNumericalIdLess>& toTeleport) {
1951 if (myIntermodalCollisionAction != COLLISION_ACTION_NONE && foeLane->getEdge().getPersons().size() > 0 && foeLane->hasPedestrians()) {
1952#ifdef DEBUG_PEDESTRIAN_COLLISIONS
1953 if (DEBUG_COND) {
1954 std::cout << SIMTIME << " detect pedestrian junction collisions stage=" << stage << " lane=" << getID() << " foeLane=" << foeLane->getID() << "\n";
1955 }
1956#endif
1957 const std::vector<MSTransportable*>& persons = foeLane->getEdge().getSortedPersons(timestep);
1958 for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
1959#ifdef DEBUG_PEDESTRIAN_COLLISIONS
1960 if (DEBUG_COND) {
1961 std::cout << " collider=" << collider->getID()
1962 << " ped=" << (*it_p)->getID()
1963 << " jammed=" << (*it_p)->isJammed()
1964 << " colliderBoundary=" << colliderBoundary
1965 << " pedBoundary=" << (*it_p)->getBoundingBox()
1966 << "\n";
1967 }
1968#endif
1969 if ((*it_p)->isJammed()) {
1970 continue;
1971 }
1972 if (colliderBoundary.overlapsWith((*it_p)->getBoundingBox())
1973 && collider->getBoundingPoly().overlapsWith((*it_p)->getBoundingBox())) {
1974 std::string collisionType = "junctionPedestrian";
1975 if (foeLane->isCrossing()) {
1976 collisionType = "crossing";
1977 } else if (foeLane->isWalkingArea()) {
1978 collisionType = "walkingarea";
1979 }
1980 handleIntermodalCollisionBetween(timestep, stage, collider, *it_p, 0, collisionType, toRemove, toTeleport);
1981 }
1982 }
1983 }
1984}
1985
1986
1987bool
1988MSLane::detectCollisionBetween(SUMOTime timestep, const std::string& stage, MSVehicle* collider, MSVehicle* victim,
1989 std::set<const MSVehicle*, ComparatorNumericalIdLess>& toRemove,
1990 std::set<const MSVehicle*, ComparatorNumericalIdLess>& toTeleport) const {
1991 if (myCollisionAction == COLLISION_ACTION_TELEPORT && ((victim->hasInfluencer() && victim->getInfluencer().isRemoteAffected(timestep)) ||
1992 (collider->hasInfluencer() && collider->getInfluencer().isRemoteAffected(timestep)))) {
1993 return false;
1994 }
1995
1996 // No self-collisions! (This is assumed to be ensured at caller side)
1997 if (collider == victim) {
1998 return false;
1999 }
2000
2001 const bool colliderOpposite = collider->getLaneChangeModel().isOpposite() || collider->isBidiOn(this);
2002 const bool victimOpposite = victim->getLaneChangeModel().isOpposite() || victim->isBidiOn(this);
2003 const bool bothOpposite = victimOpposite && colliderOpposite;
2004 if (bothOpposite) {
2005 std::swap(victim, collider);
2006 }
2007 const double colliderPos = colliderOpposite && !bothOpposite ? collider->getBackPositionOnLane(this) : collider->getPositionOnLane(this);
2008 const double minGapFactor = myCollisionMinGapFactor >= 0 ? myCollisionMinGapFactor : collider->getCarFollowModel().getCollisionMinGapFactor();
2009 double victimBack = victimOpposite && !bothOpposite ? victim->getPositionOnLane(this) : victim->getBackPositionOnLane(this);
2010 if (victim->getLateralOverlap() > 0 || collider->getLateralOverlap() > 0) {
2011 if (&collider->getLane()->getEdge() == myEdge && collider->getLane()->getLength() > getLength()) {
2012 // interpret victim position on the longer lane
2013 victimBack *= collider->getLane()->getLength() / getLength();
2014 }
2015 }
2016 double gap = victimBack - colliderPos - minGapFactor * collider->getVehicleType().getMinGap();
2017 if (bothOpposite) {
2018 gap = colliderPos - victimBack - minGapFactor * collider->getVehicleType().getMinGap();
2019 } else if (colliderOpposite) {
2020 // vehicles are back to back so (frontal) minGap doesn't apply
2021 gap += minGapFactor * collider->getVehicleType().getMinGap();
2022 }
2023#ifdef DEBUG_COLLISIONS
2024 if (DEBUG_COND && (DEBUG_COND2(collider) || DEBUG_COND2(victim))) {
2025 std::cout << SIMTIME
2026 << " thisLane=" << getID()
2027 << " collider=" << collider->getID()
2028 << " victim=" << victim->getID()
2029 << " colOpposite=" << colliderOpposite
2030 << " vicOpposite=" << victimOpposite
2031 << " colLane=" << collider->getLane()->getID()
2032 << " vicLane=" << victim->getLane()->getID()
2033 << " colPos=" << colliderPos
2034 << " vicBack=" << victimBack
2035 << " colLat=" << collider->getCenterOnEdge(this)
2036 << " vicLat=" << victim->getCenterOnEdge(this)
2037 << " minGap=" << collider->getVehicleType().getMinGap()
2038 << " minGapFactor=" << minGapFactor
2039 << " gap=" << gap
2040 << "\n";
2041 }
2042#endif
2043 if (victimOpposite && gap < -(collider->getLength() + victim->getLength())) {
2044 // already past each other
2045 return false;
2046 }
2047 if (gap < -NUMERICAL_EPS) {
2048 double latGap = 0;
2049 if (MSGlobals::gSublane) {
2050 latGap = (fabs(victim->getCenterOnEdge(this) - collider->getCenterOnEdge(this))
2051 - 0.5 * fabs(victim->getVehicleType().getWidth() + collider->getVehicleType().getWidth()));
2052 if (latGap + NUMERICAL_EPS > 0) {
2053 return false;
2054 }
2055 // account for ambiguous gap computation related to partial
2056 // occupation of lanes with different lengths
2057 if (isInternal() && getEdge().getNumLanes() > 1 && victim->getLane() != collider->getLane()) {
2058 double gapDelta = 0;
2059 const MSVehicle* otherLaneVeh = collider->getLane() == this ? victim : collider;
2060 if (otherLaneVeh->getLaneChangeModel().getShadowLane() == this) {
2061 gapDelta = getLength() - otherLaneVeh->getLane()->getLength();
2062 } else {
2063 for (const MSLane* cand : otherLaneVeh->getFurtherLanes()) {
2064 if (&cand->getEdge() == &getEdge()) {
2065 gapDelta = getLength() - cand->getLength();
2066 break;
2067 }
2068 }
2069 }
2070 if (gap + gapDelta >= 0) {
2071 return false;
2072 }
2073 }
2074 }
2076 && collider->getLaneChangeModel().isChangingLanes()
2077 && victim->getLaneChangeModel().isChangingLanes()
2078 && victim->getLane() != this) {
2079 // synchroneous lane change maneuver
2080 return false;
2081 }
2082#ifdef DEBUG_COLLISIONS
2083 if (DEBUG_COND && (DEBUG_COND2(collider) || DEBUG_COND2(victim))) {
2084 std::cout << SIMTIME << " detectedCollision gap=" << gap << " latGap=" << latGap << "\n";
2085 }
2086#endif
2087 handleCollisionBetween(timestep, stage, collider, victim, gap, latGap, toRemove, toTeleport);
2088 return true;
2089 }
2090 return false;
2091}
2092
2093
2094void
2095MSLane::handleCollisionBetween(SUMOTime timestep, const std::string& stage, const MSVehicle* collider, const MSVehicle* victim,
2096 double gap, double latGap, std::set<const MSVehicle*, ComparatorNumericalIdLess>& toRemove,
2097 std::set<const MSVehicle*, ComparatorNumericalIdLess>& toTeleport) const {
2098 if (collider->ignoreCollision() || victim->ignoreCollision()) {
2099 return;
2100 }
2101 std::string collisionType;
2102 std::string collisionText;
2103 if (isFrontalCollision(collider, victim)) {
2104 collisionType = "frontal";
2105 collisionText = TL("frontal collision");
2106 } else if (stage == MSNet::STAGE_LANECHANGE) {
2107 collisionType = "side";
2108 collisionText = TL("side collision");
2109 } else if (isInternal()) {
2110 collisionType = "junction";
2111 collisionText = TL("junction collision");
2112 } else {
2113 collisionType = "collision";
2114 collisionText = TL("collision");
2115 }
2116
2117 // in frontal collisions the opposite vehicle is the collider
2118 if (victim->getLaneChangeModel().isOpposite() && !collider->getLaneChangeModel().isOpposite()) {
2119 std::swap(collider, victim);
2120 }
2121 std::string prefix = TLF("Vehicle '%'; % with vehicle '%", collider->getID(), collisionText, victim->getID());
2122 if (myCollisionStopTime > 0) {
2123 if (collider->collisionStopTime() >= 0 && victim->collisionStopTime() >= 0) {
2124 return;
2125 }
2126 std::string dummyError;
2130 const double collisionAngle = RAD2DEG(fabs(GeomHelper::angleDiff(victim->getAngle(), collider->getAngle())));
2131 // determine new speeds from collision angle (@todo account for vehicle mass)
2132 double victimSpeed = victim->getSpeed();
2133 double colliderSpeed = collider->getSpeed();
2134 // double victimOrigSpeed = victim->getSpeed();
2135 // double colliderOrigSpeed = collider->getSpeed();
2136 if (collisionAngle < 45) {
2137 // rear-end collisions
2138 colliderSpeed = MIN2(colliderSpeed, victimSpeed);
2139 } else if (collisionAngle < 135) {
2140 // side collision
2141 colliderSpeed /= 2;
2142 victimSpeed /= 2;
2143 } else {
2144 // frontal collision
2145 colliderSpeed = 0;
2146 victimSpeed = 0;
2147 }
2148 const double victimStopPos = MIN2(victim->getLane()->getLength(),
2149 victim->getPositionOnLane() + victim->getCarFollowModel().brakeGap(victimSpeed, victim->getCarFollowModel().getEmergencyDecel(), 0));
2150 if (victim->collisionStopTime() < 0) {
2151 stop.collision = true;
2152 stop.lane = victim->getLane()->getID();
2153 // @todo: push victim forward?
2154 stop.startPos = victimStopPos;
2155 stop.endPos = stop.startPos;
2157 ((MSBaseVehicle*)victim)->addStop(stop, dummyError, 0);
2158 }
2159 if (collider->collisionStopTime() < 0) {
2160 stop.collision = true;
2161 stop.lane = collider->getLane()->getID();
2162 stop.startPos = MIN2(collider->getPositionOnLane() + collider->getCarFollowModel().brakeGap(colliderSpeed, collider->getCarFollowModel().getEmergencyDecel(), 0),
2163 MAX3(0.0, victimStopPos - 0.75 * victim->getVehicleType().getLength(),
2164 collider->getPositionOnLane() - SPEED2DIST(collider->getSpeed())));
2165 stop.endPos = stop.startPos;
2167 ((MSBaseVehicle*)collider)->addStop(stop, dummyError, 0);
2168 }
2169 //std::cout << " collisionAngle=" << collisionAngle
2170 // << "\n vPos=" << victim->getPositionOnLane() << " vStop=" << victimStopPos << " vSpeed=" << victimOrigSpeed << " vSpeed2=" << victimSpeed << " vSpeed3=" << victim->getSpeed()
2171 // << "\n cPos=" << collider->getPositionOnLane() << " cStop=" << stop.startPos << " cSpeed=" << colliderOrigSpeed << " cSpeed2=" << colliderSpeed << " cSpeed3=" << collider->getSpeed()
2172 // << "\n";
2173 } else {
2174 switch (myCollisionAction) {
2176 break;
2178 prefix = TLF("Teleporting vehicle '%'; % with vehicle '%", collider->getID(), collisionText, victim->getID());
2179 toRemove.insert(collider);
2180 toTeleport.insert(collider);
2181 break;
2183 prefix = TLF("Removing % participants: vehicle '%', vehicle '%", collisionText, collider->getID(), victim->getID());
2184 bool removeCollider = true;
2185 bool removeVictim = true;
2186 removeVictim = !(victim->hasInfluencer() && victim->getInfluencer()->isRemoteAffected(timestep));
2187 removeCollider = !(collider->hasInfluencer() && collider->getInfluencer()->isRemoteAffected(timestep));
2188 if (removeVictim) {
2189 toRemove.insert(victim);
2190 }
2191 if (removeCollider) {
2192 toRemove.insert(collider);
2193 }
2194 if (!removeVictim) {
2195 if (!removeCollider) {
2196 prefix = TLF("Keeping remote-controlled % participants: vehicle '%', vehicle '%", collisionText, collider->getID(), victim->getID());
2197 } else {
2198 prefix = TLF("Removing % participant: vehicle '%', keeping remote-controlled vehicle '%", collisionText, collider->getID(), victim->getID());
2199 }
2200 } else if (!removeCollider) {
2201 prefix = TLF("Keeping remote-controlled % participant: vehicle '%', removing vehicle '%", collisionText, collider->getID(), victim->getID());
2202 }
2203 break;
2204 }
2205 default:
2206 break;
2207 }
2208 }
2209 const bool newCollision = MSNet::getInstance()->registerCollision(collider, victim, collisionType, this, collider->getPositionOnLane(this));
2210 if (newCollision) {
2211 WRITE_WARNINGF(prefix + "', lane='%', gap=%%, time=%, stage=%.",
2212 getID(), toString(gap), (MSGlobals::gSublane ? TL(", latGap=") + toString(latGap) : ""),
2213 time2string(timestep), stage);
2217 }
2218#ifdef DEBUG_COLLISIONS
2219 if (DEBUG_COND2(collider)) {
2220 toRemove.erase(collider);
2221 toTeleport.erase(collider);
2222 }
2223 if (DEBUG_COND2(victim)) {
2224 toRemove.erase(victim);
2225 toTeleport.erase(victim);
2226 }
2227#endif
2228}
2229
2230
2231void
2232MSLane::handleIntermodalCollisionBetween(SUMOTime timestep, const std::string& stage, const MSVehicle* collider, const MSTransportable* victim,
2233 double gap, const std::string& collisionType,
2234 std::set<const MSVehicle*, ComparatorNumericalIdLess>& toRemove,
2235 std::set<const MSVehicle*, ComparatorNumericalIdLess>& toTeleport) const {
2236 if (collider->ignoreCollision()) {
2237 return;
2238 }
2239 std::string prefix = TLF("Vehicle '%'", collider->getID());
2241 if (collider->collisionStopTime() >= 0) {
2242 return;
2243 }
2244 std::string dummyError;
2248 // determine new speeds from collision angle (@todo account for vehicle mass)
2249 double colliderSpeed = collider->getSpeed();
2250 const double victimStopPos = victim->getEdgePos();
2251 // double victimOrigSpeed = victim->getSpeed();
2252 // double colliderOrigSpeed = collider->getSpeed();
2253 if (collider->collisionStopTime() < 0) {
2254 stop.collision = true;
2255 stop.lane = collider->getLane()->getID();
2256 stop.startPos = MIN2(collider->getPositionOnLane() + collider->getCarFollowModel().brakeGap(colliderSpeed, collider->getCarFollowModel().getEmergencyDecel(), 0),
2257 MAX3(0.0, victimStopPos - 0.75 * victim->getVehicleType().getLength(),
2258 collider->getPositionOnLane() - SPEED2DIST(collider->getSpeed())));
2259 stop.endPos = stop.startPos;
2261 ((MSBaseVehicle*)collider)->addStop(stop, dummyError, 0);
2262 }
2263 } else {
2266 break;
2268 prefix = TLF("Teleporting vehicle '%' after", collider->getID());
2269 toRemove.insert(collider);
2270 toTeleport.insert(collider);
2271 break;
2273 prefix = TLF("Removing vehicle '%' after", collider->getID());
2274 bool removeCollider = true;
2275 removeCollider = !(collider->hasInfluencer() && collider->getInfluencer()->isRemoteAffected(timestep));
2276 if (!removeCollider) {
2277 prefix = TLF("Keeping remote-controlled vehicle '%' after", collider->getID());
2278 } else {
2279 toRemove.insert(collider);
2280 }
2281 break;
2282 }
2283 default:
2284 break;
2285 }
2286 }
2287 const bool newCollision = MSNet::getInstance()->registerCollision(collider, victim, collisionType, this, victim->getEdgePos());
2288 if (newCollision) {
2289 if (gap != 0) {
2290 WRITE_WARNING(prefix + TLF(" collision with person '%', lane='%', gap=%, time=%, stage=%.",
2291 victim->getID(), getID(), gap, time2string(timestep), stage));
2292 } else {
2293 WRITE_WARNING(prefix + TLF(" collision with person '%', lane='%', time=%, stage=%.",
2294 victim->getID(), getID(), time2string(timestep), stage));
2295 }
2298 }
2299#ifdef DEBUG_COLLISIONS
2300 if (DEBUG_COND2(collider)) {
2301 toRemove.erase(collider);
2302 toTeleport.erase(collider);
2303 }
2304#endif
2305}
2306
2307
2308bool
2309MSLane::isFrontalCollision(const MSVehicle* collider, const MSVehicle* victim) {
2310 if (collider->getLaneChangeModel().isOpposite() != victim->getLaneChangeModel().isOpposite()) {
2311 return true;
2312 } else {
2313 const MSEdge* victimBidi = victim->getLane()->getEdge().getBidiEdge();
2314 if (&collider->getLane()->getEdge() == victimBidi) {
2315 return true;
2316 } else {
2317 for (MSLane* further : collider->getFurtherLanes()) {
2318 if (&further->getEdge() == victimBidi) {
2319 return true;
2320 }
2321 }
2322 }
2323 }
2324 return false;
2325}
2326
2327void
2329 // multithreading: there are concurrent writes to myNeedsCollisionCheck but all of them should set it to true
2330 myNeedsCollisionCheck = true;
2331 MSLane* bidi = getBidiLane();
2332 if (bidi != nullptr && bidi->getVehicleNumber() == 0) {
2334 }
2335 MSVehicle* firstNotStopped = nullptr;
2336 // iterate over vehicles in reverse so that move reminders will be called in the correct order
2337 for (VehCont::reverse_iterator i = myVehicles.rbegin(); i != myVehicles.rend();) {
2338 MSVehicle* veh = *i;
2339 // length is needed later when the vehicle may not exist anymore
2340 const double length = veh->getVehicleType().getLengthWithGap();
2341 const double nettoLength = veh->getVehicleType().getLength();
2342 const bool moved = veh->executeMove();
2343 MSLane* const target = veh->getMutableLane();
2344 if (veh->hasArrived()) {
2345 // vehicle has reached its arrival position
2346#ifdef DEBUG_EXEC_MOVE
2347 if DEBUG_COND2(veh) {
2348 std::cout << SIMTIME << " veh " << veh->getID() << " has arrived." << std::endl;
2349 }
2350#endif
2353 } else if (target != nullptr && moved) {
2354 if (target->getEdge().isVaporizing()) {
2355 // vehicle has reached a vaporizing edge
2358 } else {
2359 // vehicle has entered a new lane (leaveLane and workOnMoveReminders were already called in MSVehicle::executeMove)
2360 target->myVehBuffer.push_back(veh);
2362 if (MSGlobals::gSublane && veh->getLaneChangeModel().getShadowLane() != nullptr) {
2363 // trigger sorting of partial vehicles as their order may have changed (lane might not be active and only contain partial vehicles)
2365 }
2366 }
2367 } else if (veh->isParking()) {
2368 // vehicle started to park
2370 myParkingVehicles.insert(veh);
2371 } else if (veh->brokeDown()) {
2372 veh->resumeFromStopping();
2373 WRITE_WARNINGF(TL("Removing vehicle '%' after breaking down, lane='%', time=%."),
2374 veh->getID(), veh->getLane()->getID(), time2string(t));
2377 } else if (veh->isJumping()) {
2378 // vehicle jumps to next route edge
2380 } else if (veh->getPositionOnLane() > getLength()) {
2381 // for any reasons the vehicle is beyond its lane...
2382 // this should never happen because it is handled in MSVehicle::executeMove
2383 assert(false);
2384 WRITE_WARNINGF(TL("Teleporting vehicle '%'; beyond end of lane, target lane='%', time=%."),
2385 veh->getID(), getID(), time2string(t));
2388
2389 } else if (veh->collisionStopTime() == 0) {
2390 veh->resumeFromStopping();
2392 WRITE_WARNINGF(TL("Removing vehicle '%' after earlier collision, lane='%', time=%."),
2393 veh->getID(), veh->getLane()->getID(), time2string(t));
2397 WRITE_WARNINGF(TL("Teleporting vehicle '%' after earlier collision, lane='%', time=%."),
2398 veh->getID(), veh->getLane()->getID(), time2string(t));
2400 } else {
2401 if (firstNotStopped == nullptr && !(*i)->isStopped() && (*i)->getLane() == this) {
2402 firstNotStopped = *i;
2403 }
2404 ++i;
2405 continue;
2406 }
2407 } else {
2408 if (firstNotStopped == nullptr && !(*i)->isStopped() && (*i)->getLane() == this) {
2409 firstNotStopped = *i;
2410 }
2411 ++i;
2412 continue;
2413 }
2415 myNettoVehicleLengthSumToRemove += nettoLength;
2416 ++i;
2417 i = VehCont::reverse_iterator(myVehicles.erase(i.base()));
2418 }
2419 if (firstNotStopped != nullptr) {
2423 const bool wrongLane = !appropriate(firstNotStopped);
2424 const bool disconnected = (MSGlobals::gTimeToTeleportDisconnected >= 0
2425 && firstNotStopped->succEdge(1) != nullptr
2426 && firstNotStopped->getEdge()->allowedLanes(*firstNotStopped->succEdge(1), firstNotStopped->getVClass()) == nullptr);
2427
2428 const bool r1 = ttt > 0 && firstNotStopped->getWaitingTime() > ttt && !disconnected
2429 // never teleport a taxi on the last edge of it's route (where it would exit the simulation)
2430 && (firstNotStopped->getDevice(typeid(MSDevice_Taxi)) == nullptr || firstNotStopped->getRoutePosition() < (firstNotStopped->getRoute().size() - 1));
2431 const bool r2 = !r1 && MSGlobals::gTimeToGridlockHighways > 0
2434 && !disconnected;
2435 const bool r3 = disconnected && firstNotStopped->getWaitingTime() > MSGlobals::gTimeToTeleportDisconnected;
2436 const bool r4 = !r1 && !r2 && !r3 && tttb > 0
2437 && firstNotStopped->getWaitingTime() > tttb && getBidiLane() && !disconnected;
2438 const bool r5 = MSGlobals::gTimeToTeleportRSDeadlock > 0 && MSRailSignalControl::hasInstance() && !r1 && !r2 && !r3 && !r4
2440 if (r1 || r2 || r3 || r4 || r5) {
2441 const std::vector<MSLink*>::const_iterator link = succLinkSec(*firstNotStopped, 1, *this, firstNotStopped->getBestLanesContinuation());
2442 const bool minorLink = !wrongLane && (link != myLinks.end()) && !((*link)->havePriority());
2443 std::string reason = (wrongLane ? " (wrong lane" : (minorLink ? " (yield" : " (jam"));
2446 if (firstNotStopped == myVehicles.back()) {
2447 myVehicles.pop_back();
2448 } else {
2449 myVehicles.erase(std::find(myVehicles.begin(), myVehicles.end(), firstNotStopped));
2450 reason = " (blocked";
2451 }
2452 WRITE_WARNINGF("Teleporting vehicle '%'; waited too long" + reason
2453 + (r2 ? ", highway" : "")
2454 + (r3 ? ", disconnected" : "")
2455 + (r4 ? ", bidi" : "")
2456 + (r5 ? ", railSignal" : "")
2457 + "), lane='%', time=%.", firstNotStopped->getID(), getID(), time2string(t));
2458 if (wrongLane) {
2460 } else if (minorLink) {
2462 } else {
2464 }
2468 } else {
2469 MSVehicleTransfer::getInstance()->add(t, firstNotStopped);
2470 }
2471 }
2472 }
2473 }
2474 if (MSGlobals::gSublane) {
2475 // trigger sorting of vehicles as their order may have changed
2477 }
2478}
2479
2480
2481void
2485
2486
2487void
2493 if (myVehicles.empty()) {
2494 // avoid numerical instability
2497 } else if (myRecalculateBruttoSum) {
2499 for (VehCont::const_iterator i = myVehicles.begin(); i != myVehicles.end(); ++i) {
2500 myBruttoVehicleLengthSum += (*i)->getVehicleType().getLengthWithGap();
2501 }
2502 myRecalculateBruttoSum = false;
2503 }
2504}
2505
2506
2507void
2511
2512
2513const MSEdge*
2515 return myEdge->getNormalSuccessor();
2516}
2517
2518
2519const MSLane*
2521 if (!this->isInternal()) {
2522 return nullptr;
2523 }
2524 offset = 0.;
2525 const MSLane* firstInternal = this;
2527 while (pred != nullptr && pred->isInternal()) {
2528 firstInternal = pred;
2529 offset += pred->getLength();
2530 pred = firstInternal->getCanonicalPredecessorLane();
2531 }
2532 return firstInternal;
2533}
2534
2535
2536// ------ Static (sic!) container methods ------
2537bool
2538MSLane::dictionary(const std::string& id, MSLane* ptr) {
2539 const DictType::iterator it = myDict.lower_bound(id);
2540 if (it == myDict.end() || it->first != id) {
2541 // id not in myDict
2542 myDict.emplace_hint(it, id, ptr);
2543 return true;
2544 }
2545 return false;
2546}
2547
2548
2549MSLane*
2550MSLane::dictionary(const std::string& id) {
2551 const DictType::iterator it = myDict.find(id);
2552 if (it == myDict.end()) {
2553 // id not in myDict
2554 return nullptr;
2555 }
2556 return it->second;
2557}
2558
2559
2560void
2562 for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
2563 delete (*i).second;
2564 }
2565 myDict.clear();
2566}
2567
2568
2569void
2570MSLane::insertIDs(std::vector<std::string>& into) {
2571 for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
2572 into.push_back((*i).first);
2573 }
2574}
2575
2576
2577template<class RTREE> void
2578MSLane::fill(RTREE& into) {
2579 for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
2580 MSLane* l = (*i).second;
2581 Boundary b = l->getShape().getBoxBoundary();
2582 b.grow(3.);
2583 const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
2584 const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
2585 into.Insert(cmin, cmax, l);
2586 }
2587}
2588
2589template void MSLane::fill<NamedRTree>(NamedRTree& into);
2590template void MSLane::fill<LANE_RTREE_QUAL>(LANE_RTREE_QUAL& into);
2591
2592// ------ ------
2593bool
2595 if (veh->getLaneChangeModel().isOpposite()) {
2596 return false;
2597 }
2598 if (myEdge->isInternal()) {
2599 return true;
2600 }
2601 if (veh->succEdge(1) == nullptr) {
2602 assert((int)veh->getBestLanes().size() > veh->getLaneIndex());
2603 if (veh->getBestLanes()[veh->getLaneIndex()].bestLaneOffset == 0) {
2604 return true;
2605 } else {
2606 return false;
2607 }
2608 }
2609 std::vector<MSLink*>::const_iterator link = succLinkSec(*veh, 1, *this, veh->getBestLanesContinuation());
2610 return (link != myLinks.end());
2611}
2612
2613
2614void
2616 myNeedsCollisionCheck = true;
2617 std::vector<MSVehicle*>& buffered = myVehBuffer.getContainer();
2618 sort(buffered.begin(), buffered.end(), vehicle_position_sorter(this));
2619 for (MSVehicle* const veh : buffered) {
2620 assert(veh->getLane() == this);
2621 myVehicles.insert(myVehicles.begin(), veh);
2622 myBruttoVehicleLengthSum += veh->getVehicleType().getLengthWithGap();
2623 myNettoVehicleLengthSum += veh->getVehicleType().getLength();
2624 //if (true) std::cout << SIMTIME << " integrateNewVehicle lane=" << getID() << " veh=" << veh->getID() << " (on lane " << veh->getLane()->getID() << ") into lane=" << getID() << " myBrutto=" << myBruttoVehicleLengthSum << "\n";
2626 }
2627 buffered.clear();
2629 //std::cout << SIMTIME << " integrateNewVehicle lane=" << getID() << " myVehicles1=" << toString(myVehicles);
2630 if (MSGlobals::gLateralResolution > 0 || myOpposite != nullptr) {
2631 sort(myVehicles.begin(), myVehicles.end(), vehicle_natural_position_sorter(this));
2632 }
2634#ifdef DEBUG_VEHICLE_CONTAINER
2635 if (DEBUG_COND) std::cout << SIMTIME << " integrateNewVehicle lane=" << getID()
2636 << " vehicles=" << toString(myVehicles) << " partials=" << toString(myPartialVehicles) << "\n";
2637#endif
2638}
2639
2640
2641void
2643 if (myPartialVehicles.size() > 1) {
2645 }
2646}
2647
2648
2649void
2651 if (myManeuverReservations.size() > 1) {
2652#ifdef DEBUG_CONTEXT
2653 if (DEBUG_COND) {
2654 std::cout << "sortManeuverReservations on lane " << getID()
2655 << "\nBefore sort: " << toString(myManeuverReservations) << std::endl;
2656 }
2657#endif
2659#ifdef DEBUG_CONTEXT
2660 if (DEBUG_COND) {
2661 std::cout << "After sort: " << toString(myManeuverReservations) << std::endl;
2662 }
2663#endif
2664 }
2665}
2666
2667
2668bool
2670 return myEdge->isInternal();
2671}
2672
2673
2674bool
2676 return myEdge->isNormal();
2677}
2678
2679
2680bool
2682 return myEdge->isCrossing();
2683}
2684
2685
2686bool
2688 return isCrossing() && getIncomingLanes()[0].viaLink->getOffState() == LINKSTATE_MAJOR;
2689}
2690
2691
2692bool
2694 return myEdge->isWalkingArea();
2695}
2696
2697
2698MSVehicle*
2700 if (myVehicles.size() == 0) {
2701 return nullptr;
2702 }
2703 return myVehicles.front();
2704}
2705
2706
2707MSVehicle*
2709 if (myVehicles.size() == 0) {
2710 return nullptr;
2711 }
2712 return myVehicles.back();
2713}
2714
2715
2716MSVehicle*
2718 // all vehicles in myVehicles should have positions smaller or equal to
2719 // those in myPartialVehicles (unless we're on a bidi-lane)
2720 if (myVehicles.size() > 0) {
2721 if (myBidiLane != nullptr && myPartialVehicles.size() > 0) {
2722 if (myVehicles.front()->getPositionOnLane() > myPartialVehicles.front()->getPositionOnLane(this)) {
2723 return myPartialVehicles.front();
2724 }
2725 }
2726 return myVehicles.front();
2727 }
2728 if (myPartialVehicles.size() > 0) {
2729 return myPartialVehicles.front();
2730 }
2731 return nullptr;
2732}
2733
2734
2735MSVehicle*
2737 MSVehicle* result = nullptr;
2738 if (myVehicles.size() > 0) {
2739 result = myVehicles.back();
2740 }
2741 if (myPartialVehicles.size() > 0
2742 && (result == nullptr || result->getPositionOnLane(this) < myPartialVehicles.back()->getPositionOnLane(this))) {
2743 result = myPartialVehicles.back();
2744 }
2745 return result;
2746}
2747
2748
2749std::vector<MSLink*>::const_iterator
2750MSLane::succLinkSec(const SUMOVehicle& veh, int nRouteSuccs,
2751 const MSLane& succLinkSource, const std::vector<MSLane*>& conts) {
2752 const MSEdge* nRouteEdge = veh.succEdge(nRouteSuccs);
2753 // check whether the vehicle tried to look beyond its route
2754 if (nRouteEdge == nullptr) {
2755 // return end (no succeeding link) if so
2756 return succLinkSource.myLinks.end();
2757 }
2758 // if we are on an internal lane there should only be one link and it must be allowed
2759 if (succLinkSource.isInternal()) {
2760 assert(succLinkSource.myLinks.size() == 1);
2761 // could have been disallowed dynamically with a rerouter or via TraCI
2762 // assert(succLinkSource.myLinks[0]->getLane()->allowsVehicleClass(veh.getVehicleType().getVehicleClass()));
2763 return succLinkSource.myLinks.begin();
2764 }
2765 // a link may be used if
2766 // 1) there is a destination lane ((*link)->getLane()!=0)
2767 // 2) the destination lane belongs to the next edge in route ((*link)->getLane()->myEdge == nRouteEdge)
2768 // 3) the destination lane allows the vehicle's class ((*link)->getLane()->allowsVehicleClass(veh.getVehicleClass()))
2769
2770 // there should be a link which leads to the next desired lane our route in "conts" (built in "getBestLanes")
2771 // "conts" stores the best continuations of our current lane
2772 // we should never return an arbitrary link since this may cause collisions
2773
2774 if (nRouteSuccs < (int)conts.size()) {
2775 // we go through the links in our list and return the matching one
2776 for (std::vector<MSLink*>::const_iterator link = succLinkSource.myLinks.begin(); link != succLinkSource.myLinks.end(); ++link) {
2777 if ((*link)->getLane() != nullptr && (*link)->getLane()->myEdge == nRouteEdge
2778 && (*link)->getLane()->allowsVehicleClass(veh.getVClass())
2779 && ((*link)->getViaLane() == nullptr || (*link)->getViaLane()->allowsVehicleClass(veh.getVClass()))) {
2780 // we should use the link if it connects us to the best lane
2781 if ((*link)->getLane() == conts[nRouteSuccs]) {
2782 return link;
2783 }
2784 }
2785 }
2786 } else {
2787 // the source lane is a dead end (no continuations exist)
2788 return succLinkSource.myLinks.end();
2789 }
2790 // the only case where this should happen is for a disconnected route (deliberately ignored)
2791#ifdef DEBUG_NO_CONNECTION
2792 // the "'" around the ids are missing intentionally in the message below because it slows messaging down, resulting in test timeouts
2793 WRITE_WARNING("Could not find connection between lane " + succLinkSource.getID() + " and lane " + conts[nRouteSuccs]->getID() +
2794 " for vehicle " + veh.getID() + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
2795#endif
2796 return succLinkSource.myLinks.end();
2797}
2798
2799
2800const MSLink*
2801MSLane::getLinkTo(const MSLane* const target) const {
2802 const bool internal = target->isInternal();
2803 for (const MSLink* const l : myLinks) {
2804 if ((internal && l->getViaLane() == target) || (!internal && l->getLane() == target)) {
2805 return l;
2806 }
2807 }
2808 return nullptr;
2809}
2810
2811
2812const MSLane*
2813MSLane::getInternalFollowingLane(const MSLane* const target) const {
2814 for (const MSLink* const l : myLinks) {
2815 if (l->getLane() == target) {
2816 return l->getViaLane();
2817 }
2818 }
2819 return nullptr;
2820}
2821
2822
2823const MSLink*
2825 if (!isInternal()) {
2826 return nullptr;
2827 }
2828 const MSLane* internal = this;
2829 const MSLane* lane = this->getCanonicalPredecessorLane();
2830 assert(lane != nullptr);
2831 while (lane->isInternal()) {
2832 internal = lane;
2833 lane = lane->getCanonicalPredecessorLane();
2834 assert(lane != nullptr);
2835 }
2836 return lane->getLinkTo(internal);
2837}
2838
2839
2840void
2841MSLane::setMaxSpeed(const double val, const bool modified, const double jamThreshold) {
2842 myMaxSpeed = val;
2843 mySpeedModified = modified;
2847 while (first != nullptr) {
2848 first->setSpeed(val, SIMSTEP, jamThreshold, myIndex);
2849 first = first->getNextSegment();
2850 }
2851 }
2852}
2853
2854
2855void
2860
2861
2862void
2864 myLength = val;
2866}
2867
2868
2869void
2871 //if (getID() == "disabled_lane") std::cout << SIMTIME << " swapAfterLaneChange lane=" << getID() << " myVehicles=" << toString(myVehicles) << " myTmpVehicles=" << toString(myTmpVehicles) << "\n";
2873 myTmpVehicles.clear();
2874 // this needs to be done after finishing lane-changing for all lanes on the
2875 // current edge (MSLaneChanger::updateLanes())
2877 if (MSGlobals::gSublane && getOpposite() != nullptr) {
2879 }
2880 if (myBidiLane != nullptr) {
2882 }
2883}
2884
2885
2886MSVehicle*
2887MSLane::removeVehicle(MSVehicle* remVehicle, MSMoveReminder::Notification notification, bool notify) {
2888 assert(remVehicle->getLane() == this);
2889 for (MSLane::VehCont::iterator it = myVehicles.begin(); it < myVehicles.end(); it++) {
2890 if (remVehicle == *it) {
2891 if (notify) {
2892 remVehicle->leaveLane(notification);
2893 }
2894 myVehicles.erase(it);
2897 break;
2898 }
2899 }
2900 return remVehicle;
2901}
2902
2903
2904MSLane*
2905MSLane::getParallelLane(int offset, bool includeOpposite) const {
2906 return myEdge->parallelLane(this, offset, includeOpposite);
2907}
2908
2909
2910void
2912 IncomingLaneInfo ili;
2913 ili.lane = lane;
2914 ili.viaLink = viaLink;
2915 ili.length = lane->getLength();
2916 myIncomingLanes.push_back(ili);
2917}
2918
2919
2920void
2921MSLane::addApproachingLane(MSLane* lane, bool warnMultiCon) {
2922 MSEdge* approachingEdge = &lane->getEdge();
2923 if (myApproachingLanes.find(approachingEdge) == myApproachingLanes.end()) {
2924 myApproachingLanes[approachingEdge] = std::vector<MSLane*>();
2925 } else if (!approachingEdge->isInternal() && warnMultiCon) {
2926 // whenever a normal edge connects twice, there is a corresponding
2927 // internal edge which connects twice, one warning is sufficient
2928 WRITE_WARNINGF(TL("Lane '%' is approached multiple times from edge '%'. This may cause collisions."),
2929 getID(), approachingEdge->getID());
2930 }
2931 myApproachingLanes[approachingEdge].push_back(lane);
2932}
2933
2934
2935bool
2937 for (MSLink* link : lane->getLinkCont()) {
2938 if (link->getLane() == this && (link->getPermissions() & svc) == svc) {
2939 return true;
2940 }
2941 }
2942 return false;
2943}
2944
2945
2946double MSLane::getMissingRearGap(const MSVehicle* leader, double backOffset, double leaderSpeed) const {
2947 // this follows the same logic as getFollowerOnConsecutive. we do a tree
2948 // search and check for the vehicle with the largest missing rear gap within
2949 // relevant range
2950 double result = 0;
2951 const double leaderDecel = leader->getCarFollowModel().getMaxDecel();
2952 CLeaderDist followerInfo = getFollowersOnConsecutive(leader, backOffset, false)[0];
2953 const MSVehicle* v = followerInfo.first;
2954 if (v != nullptr) {
2955 result = v->getCarFollowModel().getSecureGap(v, leader, v->getSpeed(), leaderSpeed, leaderDecel) - followerInfo.second;
2956 }
2957 return result;
2958}
2959
2960
2961double
2964 const double maxSpeed = getSpeedLimit() * vc.getMaxSpeedFactor();
2965 // NOTE: For the euler update this is an upper bound on the actual braking distance (see ticket #860)
2966 // impose a hard bound due to visibility / common sense to avoid unnecessary computation if there are strange vehicles in the fleet
2967 const double minDecel = isRailway(myPermissions) ? vc.getMinDecelerationRail() : vc.getMinDeceleration();
2968 return MIN2(maxSpeed * maxSpeed * 0.5 / minDecel + vc.getMaxMinGap(),
2969 myPermissions == SVC_SHIP ? 10000.0 : 1000.0);
2970}
2971
2972
2973std::pair<MSVehicle* const, double>
2974MSLane::getLeader(const MSVehicle* veh, const double vehPos, const std::vector<MSLane*>& bestLaneConts, double dist, bool checkTmpVehicles) const {
2975 // get the leading vehicle for (shadow) veh
2976 // XXX this only works as long as all lanes of an edge have equal length
2977#ifdef DEBUG_CONTEXT
2978 if (DEBUG_COND2(veh)) {
2979 std::cout << " getLeader lane=" << getID() << " ego=" << veh->getID() << " vehs=" << toString(myVehicles) << " tmpVehs=" << toString(myTmpVehicles) << "\n";
2980 }
2981#endif
2982 if (checkTmpVehicles) {
2983 for (VehCont::const_iterator last = myTmpVehicles.begin(); last != myTmpVehicles.end(); ++last) {
2984 // XXX refactor leaderInfo to use a const vehicle all the way through the call hierarchy
2985 MSVehicle* pred = (MSVehicle*)*last;
2986 if (pred == veh) {
2987 continue;
2988 }
2989#ifdef DEBUG_CONTEXT
2990 if (DEBUG_COND2(veh)) {
2991 std::cout << std::setprecision(gPrecision) << " getLeader lane=" << getID() << " ego=" << veh->getID() << " egoPos=" << vehPos << " pred=" << pred->getID() << " predPos=" << pred->getPositionOnLane() << "\n";
2992 }
2993#endif
2994 if (pred->getPositionOnLane() >= vehPos) {
2995 return std::pair<MSVehicle* const, double>(pred, pred->getBackPositionOnLane(this) - veh->getVehicleType().getMinGap() - vehPos);
2996 }
2997 }
2998 } else {
2999 for (AnyVehicleIterator last = anyVehiclesBegin(); last != anyVehiclesEnd(); ++last) {
3000 // XXX refactor leaderInfo to use a const vehicle all the way through the call hierarchy
3001 MSVehicle* pred = (MSVehicle*)*last;
3002 if (pred == veh) {
3003 continue;
3004 }
3005#ifdef DEBUG_CONTEXT
3006 if (DEBUG_COND2(veh)) {
3007 std::cout << " getLeader lane=" << getID() << " ego=" << veh->getID() << " egoPos=" << vehPos
3008 << " pred=" << pred->getID() << " predPos=" << pred->getPositionOnLane(this) << " predBack=" << pred->getBackPositionOnLane(this) << "\n";
3009 }
3010#endif
3011 if (pred->getPositionOnLane(this) >= vehPos) {
3013 && pred->getLaneChangeModel().isOpposite()
3015 && pred->getLaneChangeModel().getShadowLane() == this) {
3016 // skip non-overlapping shadow
3017 continue;
3018 }
3019 return std::pair<MSVehicle* const, double>(pred, pred->getBackPositionOnLane(this) - veh->getVehicleType().getMinGap() - vehPos);
3020 }
3021 }
3022 }
3023 // XXX from here on the code mirrors MSLaneChanger::getRealLeader
3024 if (bestLaneConts.size() > 0) {
3025 double seen = getLength() - vehPos;
3026 double speed = veh->getSpeed();
3027 if (dist < 0) {
3028 dist = veh->getCarFollowModel().brakeGap(speed) + veh->getVehicleType().getMinGap();
3029 }
3030#ifdef DEBUG_CONTEXT
3031 if (DEBUG_COND2(veh)) {
3032 std::cout << " getLeader lane=" << getID() << " seen=" << seen << " dist=" << dist << "\n";
3033 }
3034#endif
3035 if (seen > dist) {
3036 return std::pair<MSVehicle* const, double>(static_cast<MSVehicle*>(nullptr), -1);
3037 }
3038 return getLeaderOnConsecutive(dist, seen, speed, *veh, bestLaneConts);
3039 } else {
3040 return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
3041 }
3042}
3043
3044
3045std::pair<MSVehicle* const, double>
3046MSLane::getLeaderOnConsecutive(double dist, double seen, double speed, const MSVehicle& veh,
3047 const std::vector<MSLane*>& bestLaneConts, bool considerCrossingFoes) const {
3048#ifdef DEBUG_CONTEXT
3049 if (DEBUG_COND2(&veh)) {
3050 std::cout << " getLeaderOnConsecutive lane=" << getID() << " ego=" << veh.getID() << " seen=" << seen << " dist=" << dist << " conts=" << toString(bestLaneConts) << "\n";
3051 }
3052#endif
3053 if (seen > dist && !isInternal()) {
3054 return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
3055 }
3056 int view = 1;
3057 // loop over following lanes
3058 if (myPartialVehicles.size() > 0) {
3059 // XXX
3060 MSVehicle* pred = myPartialVehicles.front();
3061 const double gap = seen - (getLength() - pred->getBackPositionOnLane(this)) - veh.getVehicleType().getMinGap();
3062#ifdef DEBUG_CONTEXT
3063 if (DEBUG_COND2(&veh)) {
3064 std::cout << " predGap=" << gap << " partials=" << toString(myPartialVehicles) << "\n";
3065 }
3066#endif
3067 // make sure pred is really a leader and not doing continous lane-changing behind ego
3068 if (gap > 0) {
3069 return std::pair<MSVehicle* const, double>(pred, gap);
3070 }
3071 }
3072#ifdef DEBUG_CONTEXT
3073 if (DEBUG_COND2(&veh)) {
3074 gDebugFlag1 = true;
3075 }
3076#endif
3077 const MSLane* nextLane = this;
3078 do {
3079 nextLane->getVehiclesSecure(); // lock against running sim when called from GUI for time gap coloring
3080 // get the next link used
3081 std::vector<MSLink*>::const_iterator link = succLinkSec(veh, view, *nextLane, bestLaneConts);
3082 if (nextLane->isLinkEnd(link) && view < veh.getRoute().size() - veh.getRoutePosition()) {
3083 const MSEdge* nextEdge = *(veh.getCurrentRouteEdge() + view);
3084 if (nextEdge->getNumLanes() == 1) {
3085 // lanes are unambiguous on the next route edge, continue beyond bestLaneConts
3086 for (link = nextLane->getLinkCont().begin(); link < nextLane->getLinkCont().end(); link++) {
3087 if ((*link)->getLane() == nextEdge->getLanes().front()) {
3088 break;
3089 }
3090 }
3091 }
3092 }
3093 if (nextLane->isLinkEnd(link)) {
3094#ifdef DEBUG_CONTEXT
3095 if (DEBUG_COND2(&veh)) {
3096 std::cout << " cannot continue after nextLane=" << nextLane->getID() << "\n";
3097 }
3098#endif
3099 nextLane->releaseVehicles();
3100 break;
3101 }
3102 // check for link leaders
3103 const bool laneChanging = veh.getLane() != this;
3104 const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(&veh, seen);
3105 nextLane->releaseVehicles();
3106 if (linkLeaders.size() > 0) {
3107 std::pair<MSVehicle*, double> result;
3108 double shortestGap = std::numeric_limits<double>::max();
3109 for (auto ll : linkLeaders) {
3110 double gap = ll.vehAndGap.second;
3111 MSVehicle* lVeh = ll.vehAndGap.first;
3112 if (lVeh != nullptr) {
3113 // leader is a vehicle, not a pedestrian
3114 gap += lVeh->getCarFollowModel().brakeGap(lVeh->getSpeed(), lVeh->getCarFollowModel().getMaxDecel(), 0);
3115 }
3116#ifdef DEBUG_CONTEXT
3117 if (DEBUG_COND2(&veh)) {
3118 std::cout << " linkLeader candidate " << Named::getIDSecure(lVeh)
3119 << " isLeader=" << veh.isLeader(*link, lVeh, ll.vehAndGap.second)
3120 << " gap=" << ll.vehAndGap.second
3121 << " gap+brakeing=" << gap
3122 << "\n";
3123 }
3124#endif
3125 // skip vehicles which do not share the outgoing edge (to get only real leader vehicles in TraCI #13842)
3126 if (!considerCrossingFoes && !ll.sameTarget()) {
3127 continue;
3128 }
3129 // in the context of lane-changing, all candidates are leaders
3130 if (lVeh != nullptr && !laneChanging && !veh.isLeader(*link, lVeh, ll.vehAndGap.second)) {
3131 continue;
3132 }
3133 if (gap < shortestGap) {
3134 shortestGap = gap;
3135 if (ll.vehAndGap.second < 0 && !MSGlobals::gComputeLC) {
3136 // can always continue up to the stop line or crossing point
3137 // @todo: figure out whether this should also impact lane changing
3138 ll.vehAndGap.second = MAX2(seen - nextLane->getLength(), ll.distToCrossing);
3139 }
3140 result = ll.vehAndGap;
3141 }
3142 }
3143 if (shortestGap != std::numeric_limits<double>::max()) {
3144#ifdef DEBUG_CONTEXT
3145 if (DEBUG_COND2(&veh)) {
3146 std::cout << " found linkLeader after nextLane=" << nextLane->getID() << "\n";
3147 gDebugFlag1 = false;
3148 }
3149#endif
3150 return result;
3151 }
3152 }
3153 bool nextInternal = (*link)->getViaLane() != nullptr;
3154 nextLane = (*link)->getViaLaneOrLane();
3155 if (nextLane == nullptr) {
3156 break;
3157 }
3158 nextLane->getVehiclesSecure(); // lock against running sim when called from GUI for time gap coloring
3159 MSVehicle* leader = nextLane->getLastAnyVehicle();
3160 if (leader != nullptr) {
3161#ifdef DEBUG_CONTEXT
3162 if (DEBUG_COND2(&veh)) {
3163 std::cout << " found leader " << leader->getID() << " on nextLane=" << nextLane->getID() << "\n";
3164 }
3165#endif
3166 const double leaderDist = seen + leader->getBackPositionOnLane(nextLane) - veh.getVehicleType().getMinGap();
3167 nextLane->releaseVehicles();
3168 return std::make_pair(leader, leaderDist);
3169 }
3170 nextLane->releaseVehicles();
3171 if (nextLane->getVehicleMaxSpeed(&veh) < speed) {
3172 dist = veh.getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(&veh));
3173 }
3174 seen += nextLane->getLength();
3175 if (!nextInternal) {
3176 view++;
3177 }
3178 } while (seen <= dist || nextLane->isInternal());
3179#ifdef DEBUG_CONTEXT
3180 gDebugFlag1 = false;
3181#endif
3182 return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
3183}
3184
3185
3186std::pair<MSVehicle* const, double>
3187MSLane::getCriticalLeader(double dist, double seen, double speed, const MSVehicle& veh) const {
3188#ifdef DEBUG_CONTEXT
3189 if (DEBUG_COND2(&veh)) {
3190 std::cout << SIMTIME << " getCriticalLeader. lane=" << getID() << " veh=" << veh.getID() << "\n";
3191 }
3192#endif
3193 const std::vector<MSLane*>& bestLaneConts = veh.getBestLanesContinuation(this);
3194 std::pair<MSVehicle*, double> result = std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
3195 double safeSpeed = std::numeric_limits<double>::max();
3196 int view = 1;
3197 // loop over following lanes
3198 // @note: we don't check the partial occupator for this lane since it was
3199 // already checked in MSLaneChanger::getRealLeader()
3200 const MSLane* nextLane = this;
3201 SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / MAX2(speed, NUMERICAL_EPS));
3202 do {
3203 // get the next link used
3204 std::vector<MSLink*>::const_iterator link = succLinkSec(veh, view, *nextLane, bestLaneConts);
3205 if (nextLane->isLinkEnd(link) || !(*link)->opened(arrivalTime, speed, speed, veh.getVehicleType().getLength(),
3206 veh.getImpatience(), veh.getCarFollowModel().getMaxDecel(), 0, veh.getLateralPositionOnLane(), nullptr, false, &veh) || (*link)->haveRed()) {
3207 return result;
3208 }
3209 // check for link leaders
3210#ifdef DEBUG_CONTEXT
3211 if (DEBUG_COND2(&veh)) {
3212 gDebugFlag1 = true; // See MSLink::getLeaderInfo
3213 }
3214#endif
3215 const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(&veh, seen);
3216#ifdef DEBUG_CONTEXT
3217 if (DEBUG_COND2(&veh)) {
3218 gDebugFlag1 = false; // See MSLink::getLeaderInfo
3219 }
3220#endif
3221 for (MSLink::LinkLeaders::const_iterator it = linkLeaders.begin(); it != linkLeaders.end(); ++it) {
3222 const MSVehicle* leader = (*it).vehAndGap.first;
3223 if (leader != nullptr && leader != result.first) {
3224 // XXX ignoring pedestrians here!
3225 // XXX ignoring the fact that the link leader may alread by following us
3226 // XXX ignoring the fact that we may drive up to the crossing point
3227 double tmpSpeed = safeSpeed;
3228 veh.adaptToJunctionLeader((*it).vehAndGap, seen, nullptr, nextLane, tmpSpeed, tmpSpeed, (*it).distToCrossing);
3229#ifdef DEBUG_CONTEXT
3230 if (DEBUG_COND2(&veh)) {
3231 std::cout << " linkLeader=" << leader->getID() << " gap=" << result.second << " tmpSpeed=" << tmpSpeed << " safeSpeed=" << safeSpeed << "\n";
3232 }
3233#endif
3234 if (tmpSpeed < safeSpeed) {
3235 safeSpeed = tmpSpeed;
3236 result = (*it).vehAndGap;
3237 }
3238 }
3239 }
3240 bool nextInternal = (*link)->getViaLane() != nullptr;
3241 nextLane = (*link)->getViaLaneOrLane();
3242 if (nextLane == nullptr) {
3243 break;
3244 }
3245 MSVehicle* leader = nextLane->getLastAnyVehicle();
3246 if (leader != nullptr && leader != result.first) {
3247 const double gap = seen + leader->getBackPositionOnLane(nextLane) - veh.getVehicleType().getMinGap();
3248 const double tmpSpeed = veh.getCarFollowModel().insertionFollowSpeed(&veh, speed, gap, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel(), leader);
3249 if (tmpSpeed < safeSpeed) {
3250 safeSpeed = tmpSpeed;
3251 result = std::make_pair(leader, gap);
3252 }
3253 }
3254 if (nextLane->getVehicleMaxSpeed(&veh) < speed) {
3255 dist = veh.getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(&veh));
3256 }
3257 seen += nextLane->getLength();
3258 if (seen <= dist) {
3259 // delaying the update of arrivalTime and making it conditional to avoid possible integer overflows
3260 arrivalTime += TIME2STEPS(nextLane->getLength() / MAX2(speed, NUMERICAL_EPS));
3261 }
3262 if (!nextInternal) {
3263 view++;
3264 }
3265 } while (seen <= dist || nextLane->isInternal());
3266 return result;
3267}
3268
3269
3270MSLane*
3272 if (myLogicalPredecessorLane == nullptr) {
3274 // get only those edges which connect to this lane
3275 for (MSEdgeVector::iterator i = pred.begin(); i != pred.end();) {
3276 std::vector<IncomingLaneInfo>::const_iterator j = find_if(myIncomingLanes.begin(), myIncomingLanes.end(), edge_finder(*i));
3277 if (j == myIncomingLanes.end() || myEdge->getBidiEdge() == *i || ((*i)->isInternal() && myEdge->getBidiEdge() == (*i)->getNormalBefore())) {
3278 i = pred.erase(i);
3279 } else {
3280 ++i;
3281 }
3282 }
3283 // get the lane with the "straightest" connection
3284 if (pred.size() != 0) {
3285 std::sort(pred.begin(), pred.end(), by_connections_to_sorter(&getEdge()));
3286 MSEdge* best = *pred.begin();
3287 std::vector<IncomingLaneInfo>::const_iterator j = find_if(myIncomingLanes.begin(), myIncomingLanes.end(), edge_finder(best));
3288 myLogicalPredecessorLane = j->lane;
3289 }
3290 }
3292}
3293
3294
3295const MSLane*
3297 if (isInternal()) {
3299 } else {
3300 return this;
3301 }
3302}
3303
3304
3305const MSLane*
3307 if (isInternal()) {
3309 } else {
3310 return this;
3311 }
3312}
3313
3314
3315MSLane*
3317 for (const IncomingLaneInfo& cand : myIncomingLanes) {
3318 if (&(cand.lane->getEdge()) == &fromEdge) {
3319 return cand.lane;
3320 }
3321 }
3322 return nullptr;
3323}
3324
3325
3326MSLane*
3328 if (myCanonicalPredecessorLane != nullptr) {
3330 }
3331 if (myIncomingLanes.empty()) {
3332 return nullptr;
3333 }
3334 // myCanonicalPredecessorLane has not yet been determined and there exist incoming lanes
3335 // get the lane with the priorized (or if this does not apply the "straightest") connection
3336 const auto bestLane = std::min_element(myIncomingLanes.begin(), myIncomingLanes.end(), incoming_lane_priority_sorter(this));
3337 {
3338#ifdef HAVE_FOX
3339 ScopedLocker<> lock(myLeaderInfoMutex, MSGlobals::gNumSimThreads > 1);
3340#endif
3341 myCanonicalPredecessorLane = bestLane->lane;
3342 }
3343#ifdef DEBUG_LANE_SORTER
3344 std::cout << "\nBest predecessor lane for lane '" << myID << "': '" << myCanonicalPredecessorLane->getID() << "'" << std::endl;
3345#endif
3347}
3348
3349
3350MSLane*
3352 if (myCanonicalSuccessorLane != nullptr) {
3354 }
3355 if (myLinks.empty()) {
3356 return nullptr;
3357 }
3358 // myCanonicalSuccessorLane has not yet been determined and there exist outgoing links
3359 std::vector<MSLink*> candidateLinks = myLinks;
3360 // get the lane with the priorized (or if this does not apply the "straightest") connection
3361 std::sort(candidateLinks.begin(), candidateLinks.end(), outgoing_lane_priority_sorter(this));
3362 MSLane* best = (*candidateLinks.begin())->getViaLaneOrLane();
3363#ifdef DEBUG_LANE_SORTER
3364 std::cout << "\nBest successor lane for lane '" << myID << "': '" << best->getID() << "'" << std::endl;
3365#endif
3368}
3369
3370
3373 const MSLane* const pred = getLogicalPredecessorLane();
3374 if (pred == nullptr) {
3375 return LINKSTATE_DEADEND;
3376 } else {
3377 return pred->getLinkTo(this)->getState();
3378 }
3379}
3380
3381
3382const std::vector<std::pair<const MSLane*, const MSEdge*> >
3384 std::vector<std::pair<const MSLane*, const MSEdge*> > result;
3385 for (const MSLink* link : myLinks) {
3386 assert(link->getLane() != nullptr);
3387 result.push_back(std::make_pair(link->getLane(), link->getViaLane() == nullptr ? nullptr : &link->getViaLane()->getEdge()));
3388 }
3389 return result;
3390}
3391
3392std::vector<const MSLane*>
3394 std::vector<const MSLane*> result = {};
3395 for (std::map<MSEdge*, std::vector<MSLane*> >::const_iterator it = myApproachingLanes.begin(); it != myApproachingLanes.end(); ++it) {
3396 for (std::vector<MSLane*>::const_iterator it_lane = (*it).second.begin(); it_lane != (*it).second.end(); ++it_lane) {
3397 if (!((*it_lane)->isInternal())) {
3398 result.push_back(*it_lane);
3399 }
3400 }
3401 }
3402 return result;
3403}
3404
3405
3406void
3411
3412
3413void
3418
3419
3420int
3422 for (std::vector<MSLink*>::const_iterator i = myLinks.begin(); i != myLinks.end(); ++i) {
3423 if ((*i)->getLane()->isCrossing()) {
3424 return (int)(i - myLinks.begin());
3425 }
3426 }
3427 return -1;
3428}
3429
3430// ------------ Current state retrieval
3431double
3433 double sum = 0;
3434 if (myPartialVehicles.size() > 0) {
3435 const MSLane* bidi = getBidiLane();
3436 for (MSVehicle* cand : myPartialVehicles) {
3437 if (MSGlobals::gSublane && cand->getLaneChangeModel().getShadowLane() == this) {
3438 continue;
3439 }
3440 if (cand->getLane() == bidi) {
3441 sum += (brutto ? cand->getVehicleType().getLengthWithGap() : cand->getVehicleType().getLength());
3442 } else {
3443 sum += myLength - cand->getBackPositionOnLane(this);
3444 }
3445 }
3446 }
3447 return sum;
3448}
3449
3450double
3453 double fractions = getFractionalVehicleLength(true);
3454 if (myVehicles.size() != 0) {
3455 MSVehicle* lastVeh = myVehicles.front();
3456 if (lastVeh->getPositionOnLane() < lastVeh->getVehicleType().getLength()) {
3457 fractions -= (lastVeh->getVehicleType().getLength() - lastVeh->getPositionOnLane());
3458 }
3459 }
3461 return MIN2(1., (myBruttoVehicleLengthSum + fractions) / myLength);
3462}
3463
3464
3465double
3468 double fractions = getFractionalVehicleLength(false);
3469 if (myVehicles.size() != 0) {
3470 MSVehicle* lastVeh = myVehicles.front();
3471 if (lastVeh->getPositionOnLane() < lastVeh->getVehicleType().getLength()) {
3472 fractions -= (lastVeh->getVehicleType().getLength() - lastVeh->getPositionOnLane());
3473 }
3474 }
3476 return (myNettoVehicleLengthSum + fractions) / myLength;
3477}
3478
3479
3480double
3482 if (myVehicles.size() == 0) {
3483 return 0;
3484 }
3485 double wtime = 0;
3486 for (VehCont::const_iterator i = myVehicles.begin(); i != myVehicles.end(); ++i) {
3487 wtime += (*i)->getWaitingSeconds();
3488 }
3489 return wtime;
3490}
3491
3492
3493double
3495 if (myVehicles.size() == 0) {
3496 return myMaxSpeed;
3497 }
3498 double v = 0;
3499 int numVehs = 0;
3500 for (const MSVehicle* const veh : getVehiclesSecure()) {
3501 if (!veh->isStopped() || !myEdge->hasLaneChanger()) {
3502 v += veh->getSpeed();
3503 numVehs++;
3504 }
3505 }
3507 if (numVehs == 0) {
3508 return myMaxSpeed;
3509 }
3510 return v / numVehs;
3511}
3512
3513
3514double
3516 // @note: redundant code with getMeanSpeed to avoid extra checks in a function that is called very often
3517 if (myVehicles.size() == 0) {
3518 return myMaxSpeed;
3519 }
3520 double v = 0;
3521 int numBikes = 0;
3522 for (MSVehicle* veh : getVehiclesSecure()) {
3523 if (veh->getVClass() == SVC_BICYCLE) {
3524 v += veh->getSpeed();
3525 numBikes++;
3526 }
3527 }
3528 double ret;
3529 if (numBikes > 0) {
3530 ret = v / (double) myVehicles.size();
3531 } else {
3532 ret = myMaxSpeed;
3533 }
3535 return ret;
3536}
3537
3538
3539double
3541 double ret = 0;
3542 const MSLane::VehCont& vehs = getVehiclesSecure();
3543 if (vehs.size() == 0) {
3545 return 0;
3546 }
3547 for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
3548 double sv = (*i)->getHarmonoise_NoiseEmissions();
3549 ret += (double) pow(10., (sv / 10.));
3550 }
3552 return HelpersHarmonoise::sum(ret);
3553}
3554
3555
3556int
3558 const double pos1 = v1->getBackPositionOnLane(myLane);
3559 const double pos2 = v2->getBackPositionOnLane(myLane);
3560 if (pos1 != pos2) {
3561 return pos1 > pos2;
3562 } else {
3563 return v1->getNumericalID() > v2->getNumericalID();
3564 }
3565}
3566
3567
3568int
3570 const double pos1 = v1->getBackPositionOnLane(myLane);
3571 const double pos2 = v2->getBackPositionOnLane(myLane);
3572 if (pos1 != pos2) {
3573 return pos1 < pos2;
3574 } else {
3576 }
3577}
3578
3579
3581 myEdge(e),
3582 myLaneDir(e->getLanes()[0]->getShape().angleAt2D(0)) {
3583}
3584
3585
3586int
3587MSLane::by_connections_to_sorter::operator()(const MSEdge* const e1, const MSEdge* const e2) const {
3588// std::cout << "\nby_connections_to_sorter()";
3589
3590 const std::vector<MSLane*>* ae1 = e1->allowedLanes(*myEdge);
3591 const std::vector<MSLane*>* ae2 = e2->allowedLanes(*myEdge);
3592 double s1 = 0;
3593 if (ae1 != nullptr && ae1->size() != 0) {
3594// std::cout << "\nsize 1 = " << ae1->size()
3595// << " anglediff 1 = " << fabs(GeomHelper::angleDiff((*ae1)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.
3596// << "\nallowed lanes: ";
3597// for (std::vector<MSLane*>::const_iterator j = ae1->begin(); j != ae1->end(); ++j){
3598// std::cout << "\n" << (*j)->getID();
3599// }
3600 s1 = (double) ae1->size() + fabs(GeomHelper::angleDiff((*ae1)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.;
3601 }
3602 double s2 = 0;
3603 if (ae2 != nullptr && ae2->size() != 0) {
3604// std::cout << "\nsize 2 = " << ae2->size()
3605// << " anglediff 2 = " << fabs(GeomHelper::angleDiff((*ae2)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.
3606// << "\nallowed lanes: ";
3607// for (std::vector<MSLane*>::const_iterator j = ae2->begin(); j != ae2->end(); ++j){
3608// std::cout << "\n" << (*j)->getID();
3609// }
3610 s2 = (double) ae2->size() + fabs(GeomHelper::angleDiff((*ae2)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.;
3611 }
3612
3613// std::cout << "\ne1 = " << e1->getID() << " e2 = " << e2->getID()
3614// << "\ns1 = " << s1 << " s2 = " << s2
3615// << std::endl;
3616
3617 return s1 < s2;
3618}
3619
3620
3622 myLane(targetLane),
3623 myLaneDir(targetLane->getShape().angleAt2D(0)) {}
3624
3625int
3627 const MSLane* noninternal1 = laneInfo1.lane;
3628 while (noninternal1->isInternal()) {
3629 assert(noninternal1->getIncomingLanes().size() == 1);
3630 noninternal1 = noninternal1->getIncomingLanes()[0].lane;
3631 }
3632 MSLane* noninternal2 = laneInfo2.lane;
3633 while (noninternal2->isInternal()) {
3634 assert(noninternal2->getIncomingLanes().size() == 1);
3635 noninternal2 = noninternal2->getIncomingLanes()[0].lane;
3636 }
3637
3638 const MSLink* link1 = noninternal1->getLinkTo(myLane);
3639 const MSLink* link2 = noninternal2->getLinkTo(myLane);
3640
3641#ifdef DEBUG_LANE_SORTER
3642 std::cout << "\nincoming_lane_priority sorter()\n"
3643 << "noninternal predecessor for lane '" << laneInfo1.lane->getID()
3644 << "': '" << noninternal1->getID() << "'\n"
3645 << "noninternal predecessor for lane '" << laneInfo2.lane->getID()
3646 << "': '" << noninternal2->getID() << "'\n";
3647#endif
3648
3649 assert(laneInfo1.lane->isInternal() || link1 == laneInfo1.viaLink);
3650 assert(link1 != 0);
3651 assert(link2 != 0);
3652
3653 // check priority between links
3654 bool priorized1 = true;
3655 bool priorized2 = true;
3656
3657#ifdef DEBUG_LANE_SORTER
3658 std::cout << "FoeLinks of '" << noninternal1->getID() << "'" << std::endl;
3659#endif
3660 for (const MSLink* const foeLink : link1->getFoeLinks()) {
3661#ifdef DEBUG_LANE_SORTER
3662 std::cout << foeLink->getLaneBefore()->getID() << std::endl;
3663#endif
3664 if (foeLink == link2) {
3665 priorized1 = false;
3666 break;
3667 }
3668 }
3669
3670#ifdef DEBUG_LANE_SORTER
3671 std::cout << "FoeLinks of '" << noninternal2->getID() << "'" << std::endl;
3672#endif
3673 for (const MSLink* const foeLink : link2->getFoeLinks()) {
3674#ifdef DEBUG_LANE_SORTER
3675 std::cout << foeLink->getLaneBefore()->getID() << std::endl;
3676#endif
3677 // either link1 is priorized, or it should not appear in link2's foes
3678 if (foeLink == link1) {
3679 priorized2 = false;
3680 break;
3681 }
3682 }
3683 // if one link is subordinate, the other must be priorized (except for
3684 // traffic lights where mutual response is permitted to handle stuck-on-red
3685 // situation)
3686 if (priorized1 != priorized2) {
3687 return priorized1;
3688 }
3689
3690 // both are priorized, compare angle difference
3691 double d1 = fabs(GeomHelper::angleDiff(noninternal1->getShape().angleAt2D(0), myLaneDir));
3692 double d2 = fabs(GeomHelper::angleDiff(noninternal2->getShape().angleAt2D(0), myLaneDir));
3693
3694 return d2 > d1;
3695}
3696
3697
3698
3700 myLaneDir(sourceLane->getShape().angleAt2D(0)) {}
3701
3702int
3704 const MSLane* target1 = link1->getLane();
3705 const MSLane* target2 = link2->getLane();
3706 if (target2 == nullptr) {
3707 return true;
3708 }
3709 if (target1 == nullptr) {
3710 return false;
3711 }
3712
3713#ifdef DEBUG_LANE_SORTER
3714 std::cout << "\noutgoing_lane_priority sorter()\n"
3715 << "noninternal successors for lane '" << myLane->getID()
3716 << "': '" << target1->getID() << "' and "
3717 << "'" << target2->getID() << "'\n";
3718#endif
3719
3720 // priority of targets
3721 int priority1 = target1->getEdge().getPriority();
3722 int priority2 = target2->getEdge().getPriority();
3723
3724 if (priority1 != priority2) {
3725 return priority1 > priority2;
3726 }
3727
3728 // if priority of targets coincides, use angle difference
3729
3730 // both are priorized, compare angle difference
3731 double d1 = fabs(GeomHelper::angleDiff(target1->getShape().angleAt2D(0), myLaneDir));
3732 double d2 = fabs(GeomHelper::angleDiff(target2->getShape().angleAt2D(0), myLaneDir));
3733
3734 return d2 > d1;
3735}
3736
3737void
3741
3742
3743void
3747
3748bool
3750 for (const MSLink* link : myLinks) {
3751 if (link->getApproaching().size() > 0) {
3752 return true;
3753 }
3754 }
3755 return false;
3756}
3757
3758void
3760 const bool toRailJunction = myLinks.size() > 0 && (
3763 // foes on the junction are judged by the approach information of the previous step
3764 const bool saveApproaching = toRailJunction || isInternal();
3765 const bool hasVehicles = myVehicles.size() > 0;
3766 if (hasVehicles || (saveApproaching && hasApproaching())) {
3769 if (hasVehicles) {
3772 out.closeTag();
3773 }
3774 if (saveApproaching) {
3775 for (const MSLink* link : myLinks) {
3776 if (link->getApproaching().size() > 0) {
3778 out.writeAttr(SUMO_ATTR_TO, link->getViaLaneOrLane()->getID());
3779 for (auto item : link->getApproaching()) {
3781 out.writeAttr(SUMO_ATTR_ID, item.first->getID());
3782 out.writeAttr(SUMO_ATTR_ARRIVALTIME, item.second.arrivalTime);
3783 out.writeAttr(SUMO_ATTR_ARRIVALSPEED, item.second.arrivalSpeed);
3784 out.writeAttr(SUMO_ATTR_DEPARTSPEED, item.second.leaveSpeed);
3785 out.writeAttr(SUMO_ATTR_REQUEST, item.second.willPass);
3786 out.writeAttr(SUMO_ATTR_ARRIVALSPEEDBRAKING, item.second.arrivalSpeedBraking);
3787 out.writeAttr(SUMO_ATTR_WAITINGTIME, item.second.waitingTime);
3788 out.writeAttr(SUMO_ATTR_DISTANCE, item.second.dist);
3789 if (item.second.latOffset != 0) {
3790 out.writeAttr(SUMO_ATTR_POSITION_LAT, item.second.latOffset);
3791 }
3792 out.closeTag();
3793 }
3794 out.closeTag();
3795 }
3796 }
3797 }
3798 out.closeTag();
3799 }
3800}
3801
3802void
3804 myVehicles.clear();
3805 myParkingVehicles.clear();
3806 myPartialVehicles.clear();
3807 myManeuverReservations.clear();
3814 for (MSLink* link : myLinks) {
3815 link->clearState();
3816 }
3817}
3818
3819void
3820MSLane::loadState(const std::vector<SUMOVehicle*>& vehs) {
3821 for (SUMOVehicle* veh : vehs) {
3822 MSVehicle* v = dynamic_cast<MSVehicle*>(veh);
3823 v->updateBestLanes(false, this);
3824 // incorporateVehicle resets the lastActionTime (which has just been loaded from state) so we must restore it
3825 const SUMOTime lastActionTime = v->getLastActionTime();
3828 v->resetActionOffset(lastActionTime - MSNet::getInstance()->getCurrentTimeStep());
3829 }
3830}
3831
3832
3833double
3835 if (!myLaneStopOffset.isDefined()) {
3836 return 0;
3837 }
3838 if ((myLaneStopOffset.getPermissions() & veh->getVClass()) != 0) {
3839 return myLaneStopOffset.getOffset();
3840 } else {
3841 return 0;
3842 }
3843}
3844
3845
3846const StopOffset&
3850
3851
3852void
3854 myLaneStopOffset = stopOffset;
3855}
3856
3857
3859MSLane::getFollowersOnConsecutive(const MSVehicle* ego, double backOffset,
3860 bool allSublanes, double searchDist, MinorLinkMode mLinkMode, bool maxSearchDist) const {
3861 assert(ego != 0);
3862 // get the follower vehicle on the lane to change to
3863 const double egoPos = backOffset + ego->getVehicleType().getLength();
3864 const double egoLatDist = ego->getLane()->getRightSideOnEdge() - getRightSideOnEdge();
3865 const bool getOppositeLeaders = ((ego->getLaneChangeModel().isOpposite() && ego->getLane() == this)
3866 || (!ego->getLaneChangeModel().isOpposite() && &ego->getLane()->getEdge() != &getEdge()));
3867#ifdef DEBUG_CONTEXT
3868 if (DEBUG_COND2(ego)) {
3869 std::cout << SIMTIME << " getFollowers lane=" << getID() << " ego=" << ego->getID()
3870 << " backOffset=" << backOffset << " pos=" << egoPos
3871 << " allSub=" << allSublanes << " searchDist=" << searchDist << " ignoreMinor=" << mLinkMode
3872 << " maxSearchDist=" << maxSearchDist
3873 << " egoLatDist=" << egoLatDist
3874 << " getOppositeLeaders=" << getOppositeLeaders
3875 << "\n";
3876 }
3877#endif
3878 MSCriticalFollowerDistanceInfo result(myWidth, allSublanes ? nullptr : ego, allSublanes ? 0 : egoLatDist, getOppositeLeaders);
3879 if (MSGlobals::gLateralResolution > 0 && egoLatDist == 0) {
3880 // check whether ego is outside lane bounds far enough so that another vehicle might
3881 // be between itself and the first "actual" sublane
3882 // shift the offset so that we "see" this vehicle
3887 }
3888#ifdef DEBUG_CONTEXT
3889 if (DEBUG_COND2(ego)) {
3890 std::cout << SIMTIME << " getFollowers lane=" << getID() << " ego=" << ego->getID()
3891 << " egoPosLat=" << ego->getLateralPositionOnLane()
3892 << " egoLatDist=" << ego->getLane()->getRightSideOnEdge() - getRightSideOnEdge()
3893 << " extraOffset=" << result.getSublaneOffset()
3894 << "\n";
3895 }
3896#endif
3897 }
3899 for (AnyVehicleIterator last = anyVehiclesBegin(); last != anyVehiclesEnd(); ++last) {
3900 const MSVehicle* veh = *last;
3901#ifdef DEBUG_CONTEXT
3902 if (DEBUG_COND2(ego)) {
3903 std::cout << " veh=" << veh->getID() << " lane=" << veh->getLane()->getID() << " pos=" << veh->getPositionOnLane(this) << "\n";
3904 }
3905#endif
3906 if (veh != ego && veh->getPositionOnLane(this) < egoPos) {
3907 //const double latOffset = veh->getLane()->getRightSideOnEdge() - getRightSideOnEdge();
3908 const double latOffset = veh->getLatOffset(this);
3909 double dist = backOffset - veh->getPositionOnLane(this) - veh->getVehicleType().getMinGap();
3910 if (veh->isBidiOn(this)) {
3911 dist -= veh->getLength();
3912 }
3913 result.addFollower(veh, ego, dist, latOffset);
3914#ifdef DEBUG_CONTEXT
3915 if (DEBUG_COND2(ego)) {
3916 std::cout << " (1) added veh=" << veh->getID() << " latOffset=" << latOffset << " result=" << result.toString() << "\n";
3917 }
3918#endif
3919 }
3920 }
3921#ifdef DEBUG_CONTEXT
3922 if (DEBUG_COND2(ego)) {
3923 std::cout << " result.numFreeSublanes=" << result.numFreeSublanes() << "\n";
3924 }
3925#endif
3926 if (result.numFreeSublanes() > 0) {
3927 // do a tree search among all follower lanes and check for the most
3928 // important vehicle (the one requiring the largest reargap)
3929 // to get a safe bound on the necessary search depth, we need to consider the maximum speed and minimum
3930 // deceleration of potential follower vehicles
3931 if (searchDist == -1) {
3932 searchDist = getMaximumBrakeDist() - backOffset;
3933#ifdef DEBUG_CONTEXT
3934 if (DEBUG_COND2(ego)) {
3935 std::cout << " computed searchDist=" << searchDist << "\n";
3936 }
3937#endif
3938 }
3939 std::set<const MSEdge*> egoFurther;
3940 for (MSLane* further : ego->getFurtherLanes()) {
3941 egoFurther.insert(&further->getEdge());
3942 }
3943 if (ego->getPositionOnLane() < ego->getVehicleType().getLength() && egoFurther.size() == 0
3944 && ego->getLane()->getLogicalPredecessorLane() != nullptr) {
3945 // on insertion
3946 egoFurther.insert(&ego->getLane()->getLogicalPredecessorLane()->getEdge());
3947 }
3948
3949 // avoid loops
3950 std::set<const MSLane*> visited(myEdge->getLanes().begin(), myEdge->getLanes().end());
3951 if (myEdge->getBidiEdge() != nullptr) {
3952 visited.insert(myEdge->getBidiEdge()->getLanes().begin(), myEdge->getBidiEdge()->getLanes().end());
3953 }
3954 std::vector<MSLane::IncomingLaneInfo> newFound;
3955 std::vector<MSLane::IncomingLaneInfo> toExamine = myIncomingLanes;
3956 while (toExamine.size() != 0) {
3957 for (std::vector<MSLane::IncomingLaneInfo>::iterator it = toExamine.begin(); it != toExamine.end(); ++it) {
3958 MSLane* next = (*it).lane;
3959 searchDist = maxSearchDist
3960 ? MAX2(searchDist, next->getMaximumBrakeDist() - backOffset)
3961 : MIN2(searchDist, next->getMaximumBrakeDist() - backOffset);
3962 MSLeaderInfo first = next->getFirstVehicleInformation(nullptr, 0, false, std::numeric_limits<double>::max(), false);
3963 MSLeaderInfo firstFront = next->getFirstVehicleInformation(nullptr, 0, true);
3964#ifdef DEBUG_CONTEXT
3965 if (DEBUG_COND2(ego)) {
3966 std::cout << " next=" << next->getID() << " seen=" << (*it).length << " first=" << first.toString() << " firstFront=" << firstFront.toString() << " backOffset=" << backOffset << "\n";
3967 gDebugFlag1 = true; // for calling getLeaderInfo
3968 }
3969#endif
3970 if (backOffset + (*it).length - next->getLength() < 0
3971 && egoFurther.count(&next->getEdge()) != 0
3972 ) {
3973 // check for junction foes that would interfere with lane changing
3974 // @note: we are passing the back of ego as its front position so
3975 // we need to add this back to the returned gap
3976 const MSLink::LinkLeaders linkLeaders = (*it).viaLink->getLeaderInfo(ego, -backOffset);
3977 for (const auto& ll : linkLeaders) {
3978 if (ll.vehAndGap.first != nullptr) {
3979 const bool bidiFoe = (*it).viaLink->getLane() == ll.vehAndGap.first->getLane()->getNormalPredecessorLane()->getBidiLane();
3980 const bool egoIsLeader = !bidiFoe && ll.vehAndGap.first->isLeader((*it).viaLink, ego, ll.vehAndGap.second);
3981 // if ego is leader the returned gap still assumes that ego follows the leader
3982 // if the foe vehicle follows ego we need to deduce that gap
3983 const double gap = (egoIsLeader
3984 ? -ll.vehAndGap.second - ll.vehAndGap.first->getVehicleType().getLengthWithGap() - ego->getVehicleType().getMinGap()
3985 : ll.vehAndGap.second + ego->getVehicleType().getLength());
3986 result.addFollower(ll.vehAndGap.first, ego, gap);
3987#ifdef DEBUG_CONTEXT
3988 if (DEBUG_COND2(ego)) {
3989 std::cout << SIMTIME << " ego=" << ego->getID() << " link=" << (*it).viaLink->getViaLaneOrLane()->getID()
3990 << " (3) added veh=" << Named::getIDSecure(ll.vehAndGap.first)
3991 << " gap=" << ll.vehAndGap.second << " dtC=" << ll.distToCrossing
3992 << " bidiFoe=" << bidiFoe
3993 << " egoIsLeader=" << egoIsLeader << " gap2=" << gap
3994 << "\n";
3995 }
3996#endif
3997 }
3998 }
3999 }
4000#ifdef DEBUG_CONTEXT
4001 if (DEBUG_COND2(ego)) {
4002 gDebugFlag1 = false;
4003 }
4004#endif
4005
4006 for (int i = 0; i < first.numSublanes(); ++i) {
4007 const MSVehicle* v = first[i] == ego ? firstFront[i] : first[i];
4008 double agap = 0;
4009
4010 if (v != nullptr && v != ego) {
4011 if (!v->isFrontOnLane(next)) {
4012 // the front of v is already on divergent trajectory from the ego vehicle
4013 // for which this method is called (in the context of MSLaneChanger).
4014 // Therefore, technically v is not a follower but only an obstruction and
4015 // the gap is not between the front of v and the back of ego
4016 // but rather between the flank of v and the back of ego.
4017 agap = (*it).length - next->getLength() + backOffset;
4019 // ego should have left the intersection still occupied by v
4020 agap -= v->getVehicleType().getMinGap();
4021 }
4022#ifdef DEBUG_CONTEXT
4023 if (DEBUG_COND2(ego)) {
4024 std::cout << " agap1=" << agap << "\n";
4025 }
4026#endif
4027 const bool differentEdge = &v->getLane()->getEdge() != &ego->getLane()->getEdge();
4028 if (agap > 0 && differentEdge) {
4029 // Only if ego overlaps we treat v as if it were a real follower
4030 // Otherwise we ignore it and look for another follower
4031 if (!getOppositeLeaders) {
4032 // even if the vehicle is not a real
4033 // follower, it still forms a real
4034 // obstruction in opposite direction driving
4035 v = firstFront[i];
4036 if (v != nullptr && v != ego) {
4037 agap = (*it).length - v->getPositionOnLane() + backOffset - v->getVehicleType().getMinGap();
4038 } else {
4039 v = nullptr;
4040 }
4041 }
4042 } else if (differentEdge && result.hasVehicle(v)) {
4043 // ignore this vehicle as it was already seen on another lane
4044 agap = 0;
4045 }
4046 } else {
4047 if (next->getBidiLane() != nullptr && v->isBidiOn(next)) {
4048 agap = v->getPositionOnLane() + backOffset - v->getVehicleType().getLengthWithGap();
4049 } else {
4050 agap = (*it).length - v->getPositionOnLane() + backOffset - v->getVehicleType().getMinGap();
4051 }
4052 if (!(*it).viaLink->havePriority() && egoFurther.count(&(*it).lane->getEdge()) == 0
4053 && ego->isOnRoad() // during insertion, this can lead to collisions because ego's further lanes are not set (see #3053)
4054 && !ego->getLaneChangeModel().isOpposite()
4056 ) {
4057 // if v is stopped on a minor side road it should not block lane changing
4058 agap = MAX2(agap, 0.0);
4059 }
4060 }
4061 result.addFollower(v, ego, agap, 0, i);
4062#ifdef DEBUG_CONTEXT
4063 if (DEBUG_COND2(ego)) {
4064 std::cout << " (2) added veh=" << Named::getIDSecure(v) << " agap=" << agap << " next=" << next->getID() << " result=" << result.toString() << "\n";
4065 }
4066#endif
4067 }
4068 }
4069 if ((*it).length < searchDist) {
4070 const std::vector<MSLane::IncomingLaneInfo>& followers = next->getIncomingLanes();
4071 for (std::vector<MSLane::IncomingLaneInfo>::const_iterator j = followers.begin(); j != followers.end(); ++j) {
4072 if (visited.find((*j).lane) == visited.end() && (((*j).viaLink->havePriority() && !(*j).viaLink->isTurnaround())
4073 || mLinkMode == MinorLinkMode::FOLLOW_ALWAYS
4074 || (mLinkMode == MinorLinkMode::FOLLOW_ONCOMING && (*j).viaLink->getDirection() == LinkDirection::STRAIGHT))) {
4075 visited.insert((*j).lane);
4077 ili.lane = (*j).lane;
4078 ili.length = (*j).length + (*it).length;
4079 ili.viaLink = (*j).viaLink;
4080 newFound.push_back(ili);
4081 }
4082 }
4083 }
4084 }
4085 toExamine.clear();
4086 swap(newFound, toExamine);
4087 }
4088 //return result;
4089
4090 }
4091 return result;
4092}
4093
4094
4095void
4096MSLane::getLeadersOnConsecutive(double dist, double seen, double speed, const MSVehicle* ego,
4097 const std::vector<MSLane*>& bestLaneConts, MSLeaderDistanceInfo& result,
4098 bool oppositeDirection) const {
4099#ifdef DEBUG_CONTEXT
4100 if (DEBUG_COND2(ego)) {
4101 std::cout << " getLeadersOnConsecutive " << getID() << " ego=" << Named::getIDSecure(ego) << " dist=" << dist << " seen=" << seen << "\n";
4102 }
4103#endif
4104 if (seen > dist && !(isInternal() && MSGlobals::gComputeLC)) {
4105 return;
4106 }
4107 // check partial vehicles (they might be on a different route and thus not
4108 // found when iterating along bestLaneConts)
4109 for (VehCont::const_iterator it = myPartialVehicles.begin(); it != myPartialVehicles.end(); ++it) {
4110 MSVehicle* veh = *it;
4111 if (!veh->isFrontOnLane(this)) {
4112 result.addLeader(veh, seen, veh->getLatOffset(this));
4113 } else {
4114 break;
4115 }
4116 }
4117#ifdef DEBUG_CONTEXT
4118 if (DEBUG_COND2(ego)) {
4119 gDebugFlag1 = true;
4120 }
4121#endif
4122 const MSLane* nextLane = this;
4123 int view = 1;
4124 // loop over following lanes
4125 while ((seen < dist && result.numFreeSublanes() > 0) || nextLane->isInternal()) {
4126 if (nextLane != this) {
4127 seen += nextLane->getLength();
4128 }
4129 // get the next link used
4130 bool nextInternal = false;
4131 if (oppositeDirection) {
4132 if (view >= (int)bestLaneConts.size()) {
4133 break;
4134 }
4135 nextLane = bestLaneConts[view];
4136 } else {
4137 std::vector<MSLink*>::const_iterator link = succLinkSec(*ego, view, *nextLane, bestLaneConts);
4138 if (nextLane->isLinkEnd(link)) {
4139 break;
4140 }
4141#ifdef DEBUG_CONTEXT
4142 if (DEBUG_COND2(ego)) {
4143 std::cout << " link=" << (*link)->getDescription() << " debugflag=" << gDebugFlag1 << "\n";
4144 }
4145#endif
4146 // check for link leaders
4147 const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(ego, seen);
4148 for (const MSLink::LinkLeader& ll : linkLeaders) {
4149 MSVehicle* veh = ll.vehAndGap.first;
4150 // in the context of lane changing all junction leader candidates must be respected
4151#ifdef DEBUG_CONTEXT
4152 if (DEBUG_COND2(ego)) {
4153 std::cout << " linkleader=" << veh->getID() << " gap=" << ll.vehAndGap.second << " leaderOffset=" << ll.latOffset << " flags=" << ll.llFlags << "\n";
4154 }
4155#endif
4156 if (veh != 0 && (ego->isLeader(*link, veh, ll.vehAndGap.second)
4159 < veh->getCarFollowModel().brakeGap(veh->getSpeed())))) {
4160 if (ll.sameTarget() || ll.sameSource()) {
4161 result.addLeader(veh, ll.vehAndGap.second, ll.latOffset);
4162#ifdef DEBUG_CONTEXT
4163 if (DEBUG_COND2(ego)) {
4164 std::cout << " added selective: result=" << result.toString() << "\n";
4165 }
4166#endif
4167 } else {
4168 // add link leader to all sublanes and return
4169 for (int i = 0; i < result.numSublanes(); ++i) {
4170 result.addLeader(veh, ll.vehAndGap.second, 0, i);
4171 }
4172#ifdef DEBUG_CONTEXT
4173 if (DEBUG_COND2(ego)) {
4174 std::cout << " added allSublanes: result=" << result.toString() << "\n";
4175 }
4176#endif
4177 }
4178 } // XXX else, deal with pedestrians
4179 }
4180 nextInternal = (*link)->getViaLane() != nullptr;
4181 nextLane = (*link)->getViaLaneOrLane();
4182 if (nextLane == nullptr) {
4183 break;
4184 }
4185 }
4186
4187 MSLeaderInfo leaders = nextLane->getLastVehicleInformation(nullptr, 0, 0, false);
4188#ifdef DEBUG_CONTEXT
4189 if (DEBUG_COND2(ego)) {
4190 std::cout << SIMTIME << " getLeadersOnConsecutive lane=" << getID() << " nextLane=" << nextLane->getID() << " leaders=" << leaders.toString() << "\n";
4191 }
4192#endif
4193 // @todo check alignment issues if the lane width changes
4194 const int iMax = MIN2(leaders.numSublanes(), result.numSublanes());
4195 for (int i = 0; i < iMax; ++i) {
4196 const MSVehicle* veh = leaders[i];
4197 if (veh != nullptr) {
4198#ifdef DEBUG_CONTEXT
4199 if (DEBUG_COND2(ego)) std::cout << " lead=" << veh->getID()
4200 << " seen=" << seen
4201 << " minGap=" << ego->getVehicleType().getMinGap()
4202 << " backPos=" << veh->getBackPositionOnLane(nextLane)
4203 << " gap=" << seen - ego->getVehicleType().getMinGap() + veh->getBackPositionOnLane(nextLane)
4204 << "\n";
4205#endif
4206 result.addLeader(veh, seen - ego->getVehicleType().getMinGap() + veh->getBackPositionOnLane(nextLane), 0, i);
4207 }
4208 }
4209
4210 if (nextLane->getVehicleMaxSpeed(ego) < speed) {
4211 dist = ego->getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(ego));
4212 }
4213#ifdef DEBUG_CONTEXT
4214 if (DEBUG_COND2(ego)) {
4215 std::cout << " newDist=" << dist << " newSeen=" << seen << "\n";
4216 }
4217#endif
4218 if (!nextInternal) {
4219 view++;
4220 }
4221 }
4222#ifdef DEBUG_CONTEXT
4223 gDebugFlag1 = false;
4224#endif
4225}
4226
4227
4228void
4229MSLane::addLeaders(const MSVehicle* vehicle, double vehPos, MSLeaderDistanceInfo& result, bool opposite) {
4230 // if there are vehicles on the target lane with the same position as ego,
4231 // they may not have been added to 'ahead' yet
4232#ifdef DEBUG_SURROUNDING
4233 if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4234 std::cout << " addLeaders lane=" << getID() << " veh=" << vehicle->getID() << " vehPos=" << vehPos << " opposite=" << opposite << "\n";
4235 }
4236#endif
4237 const MSLeaderInfo& aheadSamePos = getLastVehicleInformation(nullptr, 0, vehPos, false, vehicle);
4238 for (int i = 0; i < aheadSamePos.numSublanes(); ++i) {
4239 const MSVehicle* veh = aheadSamePos[i];
4240 if (veh != nullptr && veh != vehicle) {
4241 const double gap = veh->getBackPositionOnLane(this) - vehPos - vehicle->getVehicleType().getMinGap();
4242#ifdef DEBUG_SURROUNDING
4243 if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4244 std::cout << " further lead=" << veh->getID() << " leadBack=" << veh->getBackPositionOnLane(this) << " gap=" << gap << "\n";
4245 }
4246#endif
4247 result.addLeader(veh, gap, 0, i);
4248 }
4249 }
4250
4251 // we must consider linkLeaders (via getLeadersOnConsecutive) while on a junction
4252 if (result.numFreeSublanes() > 0 || isInternal()) {
4253 double seen = vehicle->getLane()->getLength() - vehPos;
4254 double speed = vehicle->getSpeed();
4255 // leader vehicle could be link leader on the next junction
4256 double dist = MAX2(vehicle->getCarFollowModel().brakeGap(speed), 10.0) + vehicle->getVehicleType().getMinGap();
4257 if (getBidiLane() != nullptr) {
4258 dist = MAX2(dist, myMaxSpeed * 20);
4259 }
4260 // check for link leaders when on internal
4261 if (seen > dist && !(isInternal() && MSGlobals::gComputeLC)) {
4262#ifdef DEBUG_SURROUNDING
4263 if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4264 std::cout << " aborting forward search. dist=" << dist << " seen=" << seen << "\n";
4265 }
4266#endif
4267 return;
4268 }
4269#ifdef DEBUG_SURROUNDING
4270 if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4271 std::cout << " add consecutive before=" << result.toString() << " seen=" << seen << " dist=" << dist;
4272 }
4273#endif
4274 if (opposite) {
4275 const std::vector<MSLane*> bestLaneConts = vehicle->getUpstreamOppositeLanes();
4276#ifdef DEBUG_SURROUNDING
4277 if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4278 std::cout << " upstreamOpposite=" << toString(bestLaneConts);
4279 }
4280#endif
4281 getLeadersOnConsecutive(dist, seen, speed, vehicle, bestLaneConts, result, opposite);
4282 } else {
4283 const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation(this);
4284 getLeadersOnConsecutive(dist, seen, speed, vehicle, bestLaneConts, result);
4285 }
4286#ifdef DEBUG_SURROUNDING
4287 if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4288 std::cout << " after=" << result.toString() << "\n";
4289 }
4290#endif
4291 }
4292}
4293
4294
4295MSVehicle*
4297 for (VehCont::const_reverse_iterator i = myPartialVehicles.rbegin(); i != myPartialVehicles.rend(); ++i) {
4298 MSVehicle* veh = *i;
4299 if (veh->isFrontOnLane(this)
4300 && veh != ego
4301 && veh->getPositionOnLane() <= ego->getPositionOnLane()) {
4302#ifdef DEBUG_CONTEXT
4303 if (DEBUG_COND2(ego)) {
4304 std::cout << SIMTIME << " getPartialBehind lane=" << getID() << " ego=" << ego->getID() << " found=" << veh->getID() << "\n";
4305 }
4306#endif
4307 return veh;
4308 }
4309 }
4310#ifdef DEBUG_CONTEXT
4311 if (DEBUG_COND2(ego)) {
4312 std::cout << SIMTIME << " getPartialBehind lane=" << getID() << " ego=" << ego->getID() << " nothing found. partials=" << toString(myPartialVehicles) << "\n";
4313 }
4314#endif
4315 return nullptr;
4316}
4317
4320 MSLeaderInfo result(myWidth);
4321 for (VehCont::const_iterator it = myPartialVehicles.begin(); it != myPartialVehicles.end(); ++it) {
4322 MSVehicle* veh = *it;
4323 if (!veh->isFrontOnLane(this)) {
4324 result.addLeader(veh, false, veh->getLatOffset(this));
4325 } else {
4326 break;
4327 }
4328 }
4329 return result;
4330}
4331
4332
4333std::set<MSVehicle*>
4334MSLane::getSurroundingVehicles(double startPos, double downstreamDist, double upstreamDist, std::shared_ptr<LaneCoverageInfo> checkedLanes) const {
4335 assert(checkedLanes != nullptr);
4336 if (checkedLanes->find(this) != checkedLanes->end()) {
4337#ifdef DEBUG_SURROUNDING
4338 std::cout << "Skipping previously scanned lane: " << getID() << std::endl;
4339#endif
4340 return std::set<MSVehicle*>();
4341 } else {
4342 // Add this lane's coverage to the lane coverage info
4343 (*checkedLanes)[this] = std::make_pair(MAX2(0.0, startPos - upstreamDist), MIN2(startPos + downstreamDist, getLength()));
4344 }
4345#ifdef DEBUG_SURROUNDING
4346 std::cout << "Scanning on lane " << myID << "(downstr. " << downstreamDist << ", upstr. " << upstreamDist << ", startPos " << startPos << "): " << std::endl;
4347#endif
4348 std::set<MSVehicle*> foundVehicles = getVehiclesInRange(MAX2(0., startPos - upstreamDist), MIN2(myLength, startPos + downstreamDist));
4349 if (startPos < upstreamDist) {
4350 // scan incoming lanes
4351 for (const IncomingLaneInfo& incomingInfo : getIncomingLanes()) {
4352 MSLane* incoming = incomingInfo.lane;
4353#ifdef DEBUG_SURROUNDING
4354 std::cout << "Checking on incoming: " << incoming->getID() << std::endl;
4355 if (checkedLanes->find(incoming) != checkedLanes->end()) {
4356 std::cout << "Skipping previous: " << incoming->getID() << std::endl;
4357 }
4358#endif
4359 std::set<MSVehicle*> newVehs = incoming->getSurroundingVehicles(incoming->getLength(), 0.0, upstreamDist - startPos, checkedLanes);
4360 foundVehicles.insert(newVehs.begin(), newVehs.end());
4361 }
4362 }
4363
4364 if (getLength() < startPos + downstreamDist) {
4365 // scan successive lanes
4366 const std::vector<MSLink*>& lc = getLinkCont();
4367 for (MSLink* l : lc) {
4368#ifdef DEBUG_SURROUNDING
4369 std::cout << "Checking on outgoing: " << l->getViaLaneOrLane()->getID() << std::endl;
4370#endif
4371 std::set<MSVehicle*> newVehs = l->getViaLaneOrLane()->getSurroundingVehicles(0.0, downstreamDist - (myLength - startPos), upstreamDist, checkedLanes);
4372 foundVehicles.insert(newVehs.begin(), newVehs.end());
4373 }
4374 }
4375#ifdef DEBUG_SURROUNDING
4376 std::cout << "On lane (2) " << myID << ": \nFound vehicles: " << std::endl;
4377 for (MSVehicle* v : foundVehicles) {
4378 std::cout << v->getID() << " pos = " << v->getPositionOnLane() << std::endl;
4379 }
4380#endif
4381 return foundVehicles;
4382}
4383
4384
4385std::set<MSVehicle*>
4386MSLane::getVehiclesInRange(const double a, const double b) const {
4387 std::set<MSVehicle*> res;
4388 const VehCont& vehs = getVehiclesSecure();
4389
4390 if (!vehs.empty()) {
4391 for (MSVehicle* const veh : vehs) {
4392 if (veh->getPositionOnLane() >= a) {
4393 if (veh->getBackPositionOnLane() > b) {
4394 break;
4395 }
4396 res.insert(veh);
4397 }
4398 }
4399 }
4401 return res;
4402}
4403
4404
4405std::vector<const MSJunction*>
4406MSLane::getUpcomingJunctions(double pos, double range, const std::vector<MSLane*>& contLanes) const {
4407 // set of upcoming junctions and the corresponding conflict links
4408 std::vector<const MSJunction*> junctions;
4409 for (auto l : getUpcomingLinks(pos, range, contLanes)) {
4410 junctions.insert(junctions.end(), l->getJunction());
4411 }
4412 return junctions;
4413}
4414
4415
4416std::vector<const MSLink*>
4417MSLane::getUpcomingLinks(double pos, double range, const std::vector<MSLane*>& contLanes) const {
4418#ifdef DEBUG_SURROUNDING
4419 std::cout << "getUpcoming links on lane '" << getID() << "' with pos=" << pos
4420 << " range=" << range << std::endl;
4421#endif
4422 // set of upcoming junctions and the corresponding conflict links
4423 std::vector<const MSLink*> links;
4424
4425 // Currently scanned lane
4426 const MSLane* lane = this;
4427
4428 // continuation lanes for the vehicle
4429 std::vector<MSLane*>::const_iterator contLanesIt = contLanes.begin();
4430 // scanned distance so far
4431 double dist = 0.0;
4432 // link to be crossed by the vehicle
4433 const MSLink* link = nullptr;
4434 if (lane->isInternal()) {
4435 assert(*contLanesIt == nullptr); // is called with vehicle's bestLane structure
4436 link = lane->getEntryLink();
4437 links.insert(links.end(), link);
4438 dist += link->getInternalLengthsAfter();
4439 // next non-internal lane behind junction
4440 lane = link->getLane();
4441 pos = 0.0;
4442 assert(*(contLanesIt + 1) == lane);
4443 }
4444 while (++contLanesIt != contLanes.end()) {
4445 assert(!lane->isInternal());
4446 dist += lane->getLength() - pos;
4447 pos = 0.;
4448#ifdef DEBUG_SURROUNDING
4449 std::cout << "Distance until end of lane '" << lane->getID() << "' is " << dist << "." << std::endl;
4450#endif
4451 if (dist > range) {
4452 break;
4453 }
4454 link = lane->getLinkTo(*contLanesIt);
4455 if (link != nullptr) {
4456 links.insert(links.end(), link);
4457 }
4458 lane = *contLanesIt;
4459 }
4460 return links;
4461}
4462
4463
4464MSLane*
4466 return myOpposite;
4467}
4468
4469
4470MSLane*
4472 return myEdge->getLanes().back()->getOpposite();
4473}
4474
4475
4476double
4477MSLane::getOppositePos(double pos) const {
4478 return MAX2(0., myLength - pos);
4479}
4480
4481std::pair<MSVehicle* const, double>
4482MSLane::getFollower(const MSVehicle* ego, double egoPos, double dist, MinorLinkMode mLinkMode, bool maxSearchDist) const {
4483 for (AnyVehicleIterator first = anyVehiclesUpstreamBegin(); first != anyVehiclesUpstreamEnd(); ++first) {
4484 // XXX refactor leaderInfo to use a const vehicle all the way through the call hierarchy
4485 MSVehicle* pred = (MSVehicle*)*first;
4486#ifdef DEBUG_CONTEXT
4487 if (DEBUG_COND2(ego)) {
4488 std::cout << " getFollower lane=" << getID() << " egoPos=" << egoPos << " pred=" << pred->getID() << " predPos=" << pred->getPositionOnLane(this) << "\n";
4489 }
4490#endif
4491 if (pred != ego && pred->getPositionOnLane(this) < egoPos) {
4492 return std::pair<MSVehicle* const, double>(pred, egoPos - pred->getPositionOnLane(this) - ego->getVehicleType().getLength() - pred->getVehicleType().getMinGap());
4493 }
4494 }
4495 const double backOffset = egoPos - ego->getVehicleType().getLength();
4496 if (dist > 0 && backOffset > dist) {
4497 return std::make_pair(nullptr, -1);
4498 }
4499 const MSLeaderDistanceInfo followers = getFollowersOnConsecutive(ego, backOffset, true, dist, mLinkMode, maxSearchDist);
4500 CLeaderDist result = followers.getClosest();
4501 return std::make_pair(const_cast<MSVehicle*>(result.first), result.second);
4502}
4503
4504std::pair<MSVehicle* const, double>
4505MSLane::getOppositeLeader(const MSVehicle* ego, double dist, bool oppositeDir, MinorLinkMode mLinkMode) const {
4506#ifdef DEBUG_OPPOSITE
4507 if (DEBUG_COND2(ego)) std::cout << SIMTIME << " getOppositeLeader lane=" << getID()
4508 << " ego=" << ego->getID()
4509 << " pos=" << ego->getPositionOnLane()
4510 << " posOnOpposite=" << getOppositePos(ego->getPositionOnLane())
4511 << " dist=" << dist
4512 << " oppositeDir=" << oppositeDir
4513 << "\n";
4514#endif
4515 if (!oppositeDir) {
4516 return getLeader(ego, getOppositePos(ego->getPositionOnLane()), ego->getBestLanesContinuation(this));
4517 } else {
4518 const double egoLength = ego->getVehicleType().getLength();
4519 const double egoPos = ego->getLaneChangeModel().isOpposite() ? ego->getPositionOnLane() : getOppositePos(ego->getPositionOnLane());
4520 std::pair<MSVehicle* const, double> result = getFollower(ego, egoPos + egoLength, dist, mLinkMode, true);
4521 if (result.first != nullptr) {
4522 result.second -= ego->getVehicleType().getMinGap();
4523 if (result.first->getLaneChangeModel().isOpposite()) {
4524 result.second -= result.first->getVehicleType().getLength();
4525 }
4526 }
4527 return result;
4528 }
4529}
4530
4531
4532std::pair<MSVehicle* const, double>
4534#ifdef DEBUG_OPPOSITE
4535 if (DEBUG_COND2(ego)) std::cout << SIMTIME << " getOppositeFollower lane=" << getID()
4536 << " ego=" << ego->getID()
4537 << " backPos=" << ego->getBackPositionOnLane()
4538 << " posOnOpposite=" << getOppositePos(ego->getBackPositionOnLane())
4539 << "\n";
4540#endif
4541 if (ego->getLaneChangeModel().isOpposite()) {
4542 std::pair<MSVehicle* const, double> result = getFollower(ego, getOppositePos(ego->getPositionOnLane()), -1, MinorLinkMode::FOLLOW_NEVER);
4543 return result;
4544 } else {
4545 double vehPos = getOppositePos(ego->getPositionOnLane() - ego->getVehicleType().getLength());
4546 std::pair<MSVehicle*, double> result = getLeader(ego, vehPos, std::vector<MSLane*>());
4547 double dist = getMaximumBrakeDist() + getOppositePos(ego->getPositionOnLane() - getLength());
4548 MSLane* next = const_cast<MSLane*>(this);
4549 while (result.first == nullptr && dist > 0) {
4550 // cannot call getLeadersOnConsecutive because succLinkSec doesn't
4551 // uses the vehicle's route and doesn't work on the opposite side
4552 vehPos -= next->getLength();
4553 next = next->getCanonicalSuccessorLane();
4554 if (next == nullptr) {
4555 break;
4556 }
4557 dist -= next->getLength();
4558 result = next->getLeader(ego, vehPos, std::vector<MSLane*>());
4559 }
4560 if (result.first != nullptr) {
4561 if (result.first->getLaneChangeModel().isOpposite()) {
4562 result.second -= result.first->getVehicleType().getLength();
4563 } else {
4564 if (result.second > POSITION_EPS) {
4565 // follower can be safely ignored since it is going the other way
4566 return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
4567 }
4568 }
4569 }
4570 return result;
4571 }
4572}
4573
4574void
4575MSLane::initCollisionAction(const OptionsCont& oc, const std::string& option, CollisionAction& myAction) {
4576 const std::string action = oc.getString(option);
4577 if (action == "none") {
4578 myAction = COLLISION_ACTION_NONE;
4579 } else if (action == "warn") {
4580 myAction = COLLISION_ACTION_WARN;
4581 } else if (action == "teleport") {
4582 myAction = COLLISION_ACTION_TELEPORT;
4583 } else if (action == "remove") {
4584 myAction = COLLISION_ACTION_REMOVE;
4585 } else {
4586 WRITE_ERROR(TLF("Invalid % '%'.", option, action));
4587 }
4588}
4589
4590void
4592 initCollisionAction(oc, "collision.action", myCollisionAction);
4593 initCollisionAction(oc, "intermodal-collision.action", myIntermodalCollisionAction);
4594 myCheckJunctionCollisions = oc.getBool("collision.check-junctions");
4595 myCheckJunctionCollisionMinGap = oc.getFloat("collision.check-junctions.mingap");
4596 myCollisionStopTime = string2time(oc.getString("collision.stoptime"));
4597 myIntermodalCollisionStopTime = string2time(oc.getString("intermodal-collision.stoptime"));
4598 myCollisionMinGapFactor = oc.getFloat("collision.mingap-factor");
4599 myExtrapolateSubstepDepart = oc.getBool("extrapolate-departpos");
4600}
4601
4602
4603void
4604MSLane::setPermissions(SVCPermissions permissions, long long transientID) {
4605 const SVCPermissions oldPermissions = myPermissions;
4606 if (transientID == CHANGE_PERMISSIONS_PERMANENT) {
4607 myPermissions = permissions;
4608 myOriginalPermissions = permissions;
4609 updateInternalLanePermissions(oldPermissions);
4610 } else {
4611 myPermissionChanges[transientID] = permissions;
4613 }
4614}
4615
4616
4617void
4618MSLane::resetPermissions(long long transientID) {
4619 const SVCPermissions oldPermissions = myPermissions;
4620 myPermissionChanges.erase(transientID);
4621 if (myPermissionChanges.empty()) {
4623 } else {
4624 // combine all permission changes
4626 for (const auto& item : myPermissionChanges) {
4627 myPermissions &= item.second;
4628 }
4629 }
4630 updateInternalLanePermissions(oldPermissions);
4631}
4632
4633
4634void
4636 if (isInternal()) {
4637 return;
4638 }
4639 for (MSLink* const link : getLinkCont()) {
4640 MSLane* const internal = link->getViaLane();
4641 // only update internal lanes that mirror the permissions of this lane;
4642 // lanes with connection-specific permissions are left untouched
4643 if (internal != nullptr && internal->getPermissions() == oldPermissions) {
4645 internal->getEdge().rebuildAllowedLanes(false, false);
4646 }
4647 }
4648}
4649
4650
4651bool
4653 return !myPermissionChanges.empty();
4654}
4655
4656
4657void
4659 myChangeLeft = permissions;
4660}
4661
4662
4663void
4665 myChangeRight = permissions;
4666}
4667
4668
4669bool
4671 MSNet* const net = MSNet::getInstance();
4672 return net->hasPersons() && net->getPersonControl().getMovementModel()->hasPedestrians(this);
4673}
4674
4675
4677MSLane::nextBlocking(double minPos, double minRight, double maxLeft, double stopTime, bool bidi) const {
4678 return MSNet::getInstance()->getPersonControl().getMovementModel()->nextBlocking(this, minPos, minRight, maxLeft, stopTime, bidi);
4679}
4680
4681
4682bool
4683MSLane::checkForPedestrians(const MSVehicle* aVehicle, double& speed, double& dist, double pos, bool patchSpeed) const {
4684 if (getEdge().getPersons().size() > 0 && hasPedestrians()) {
4685#ifdef DEBUG_INSERTION
4686 if (DEBUG_COND2(aVehicle)) {
4687 std::cout << SIMTIME << " check for pedestrians on lane=" << getID() << " pos=" << pos << "\n";
4688 }
4689#endif
4690 PersonDist leader = nextBlocking(pos - aVehicle->getVehicleType().getLength(),
4691 aVehicle->getRightSideOnLane(), aVehicle->getRightSideOnLane() + aVehicle->getVehicleType().getWidth(), ceil(speed / aVehicle->getCarFollowModel().getMaxDecel()));
4692 if (leader.first != 0) {
4693 const double gap = leader.second - aVehicle->getVehicleType().getLengthWithGap();
4694 const double stopSpeed = aVehicle->getCarFollowModel().stopSpeed(aVehicle, speed, gap, MSCFModel::CalcReason::FUTURE);
4695 if ((gap < 0 && (aVehicle->getInsertionChecks() & ((int)InsertionCheck::COLLISION | (int)InsertionCheck::PEDESTRIAN)) != 0)
4696 || checkFailure(aVehicle, speed, dist, stopSpeed, patchSpeed, "", InsertionCheck::PEDESTRIAN)) {
4697 // we may not drive with the given velocity - we crash into the pedestrian
4698#ifdef DEBUG_INSERTION
4699 if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
4700 << " isInsertionSuccess lane=" << getID()
4701 << " veh=" << aVehicle->getID()
4702 << " pos=" << pos
4703 << " posLat=" << aVehicle->getLateralPositionOnLane()
4704 << " patchSpeed=" << patchSpeed
4705 << " speed=" << speed
4706 << " stopSpeed=" << stopSpeed
4707 << " pedestrianLeader=" << leader.first->getID()
4708 << " failed (@796)!\n";
4709#endif
4710 return false;
4711 }
4712 }
4713 }
4714 double backLength = aVehicle->getLength() - pos;
4715 if (backLength > 0 && MSNet::getInstance()->hasPersons()) {
4716 // look upstream for pedestrian crossings
4717 const MSLane* prev = getLogicalPredecessorLane();
4718 const MSLane* cur = this;
4719 while (backLength > 0 && prev != nullptr) {
4720 const MSLink* link = prev->getLinkTo(cur);
4721 if (link->hasFoeCrossing()) {
4722 for (const MSLane* foe : link->getFoeLanes()) {
4723 if (foe->isCrossing() && (foe->hasPedestrians() ||
4724 (foe->getIncomingLanes()[0].viaLink->getApproachingPersons() != nullptr
4725 && foe->getIncomingLanes()[0].viaLink->getApproachingPersons()->size() > 0))) {
4726#ifdef DEBUG_INSERTION
4727 if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
4728 << " isInsertionSuccess lane=" << getID()
4729 << " veh=" << aVehicle->getID()
4730 << " pos=" << pos
4731 << " backCrossing=" << foe->getID()
4732 << " peds=" << joinNamedToString(foe->getEdge().getPersons(), " ")
4733 << " approaching=" << foe->getIncomingLanes()[0].viaLink->getApproachingPersons()->size()
4734 << " failed (@4550)!\n";
4735#endif
4736 return false;
4737 }
4738 }
4739 }
4740 backLength -= prev->getLength();
4741 cur = prev;
4742 prev = prev->getLogicalPredecessorLane();
4743 }
4744 }
4745 return true;
4746}
4747
4748
4749void
4751 myRNGs.clear();
4752 const int numRNGs = oc.getInt("thread-rngs");
4753 const bool random = oc.getBool("random");
4754 int seed = oc.getInt("seed");
4755 myRNGs.reserve(numRNGs); // this is needed for stable pointers on debugging
4756 for (int i = 0; i < numRNGs; i++) {
4757 myRNGs.push_back(SumoRNG("lanes_" + toString(i)));
4758 RandHelper::initRand(&myRNGs.back(), random, seed++);
4759 }
4760}
4761
4762void
4764 for (int i = 0; i < getNumRNGs(); i++) {
4766 out.writeAttr(SUMO_ATTR_INDEX, i);
4768 out.closeTag();
4769 }
4770}
4771
4772void
4773MSLane::loadRNGState(int index, const std::string& state) {
4774 if (index >= getNumRNGs()) {
4775 throw ProcessError(TLF("State was saved with more than % threads. Change the number of threads or do not load RNG state", toString(getNumRNGs())));
4776 }
4777 RandHelper::loadState(state, &myRNGs[index]);
4778}
4779
4780
4781MSLane*
4783 return myBidiLane;
4784}
4785
4786
4787bool
4790 myLinks.front()->getFoeLanes().size() > 0
4791 || myLinks.front()->getWalkingAreaFoe() != nullptr
4792 || myLinks.front()->getWalkingAreaFoeExit() != nullptr);
4793}
4794
4795
4796double
4797MSLane::getSpaceTillLastStanding(const MSVehicle* ego, bool& foundStopped) const {
4799 double lengths = 0;
4800 for (const MSVehicle* last : myVehicles) {
4801 if (last->getSpeed() < SUMO_const_haltingSpeed && !last->getLane()->getEdge().isRoundabout()
4802 && last != ego
4803 // @todo recheck
4804 && last->isFrontOnLane(this)) {
4805 foundStopped = true;
4806 const double lastBrakeGap = last->getCarFollowModel().brakeGap(last->getSpeed());
4807 const double ret = last->getBackPositionOnLane() + lastBrakeGap - lengths;
4808 return ret;
4809 }
4810 if (MSGlobals::gSublane && ego->getVehicleType().getWidth() + last->getVehicleType().getWidth() < getWidth()) {
4811 lengths += last->getVehicleType().getLengthWithGap() * (last->getVehicleType().getWidth() + last->getVehicleType().getMinGapLat()) / getWidth();
4812 } else {
4813 lengths += last->getVehicleType().getLengthWithGap();
4814 }
4815 }
4816 return getLength() - lengths;
4817}
4818
4819
4820bool
4821MSLane::allowsVehicleClass(SUMOVehicleClass vclass, int routingMode) const {
4822 return (((routingMode & libsumo::ROUTING_MODE_IGNORE_TRANSIENT_PERMISSIONS) ? myOriginalPermissions : myPermissions) & vclass) == vclass;
4823}
4824
4825
4826const MSJunction*
4828 return myEdge->getFromJunction();
4829}
4830
4831
4832const MSJunction*
4834 return myEdge->getToJunction();
4835}
4836
4837
4838bool
4840 if (veh->getDevice(typeid(MSDevice_Taxi)) != nullptr) {
4841 // taxi device may assign a new route that continues past the end of the initial route
4842 return true;
4843 }
4844 for (const MSMoveReminder* rem : myMoveReminders) {
4845 if (dynamic_cast<const MSTriggeredRerouter*>(rem) != nullptr) {
4846 return true;
4847 }
4848 }
4849 return false;
4850}
4851
4852
4853bool
4855 for (const MSLink* link : myLinks) {
4856 if (!link->havePriority() || link->getState() == LINKSTATE_ZIPPER) {
4857 return true;
4858 }
4859 }
4860 return false;
4861}
4862
4863/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define RAD2DEG(x)
Definition GeomHelper.h:36
#define DEBUG_COND2(obj)
#define INVALID_SPEED
Definition MSCFModel.h:33
std::vector< MSEdge * > MSEdgeVector
Definition MSEdge.h:74
#define LANE_RTREE_QUAL
Definition MSLane.h:1844
std::pair< const MSVehicle *, double > CLeaderDist
std::pair< const MSPerson *, double > PersonDist
Definition MSPModel.h:41
ConstMSEdgeVector::const_iterator MSRouteIterator
Definition MSRoute.h:57
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define WRITE_ERRORF(...)
Definition MsgHandler.h:296
#define WRITE_ERROR(msg)
Definition MsgHandler.h:295
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TL(string)
Definition MsgHandler.h:304
#define TLF(string,...)
Definition MsgHandler.h:306
SUMOTime DELTA_T
Definition SUMOTime.cpp:39
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition SUMOTime.cpp:47
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition SUMOTime.cpp:107
#define STEPS2TIME(x)
Definition SUMOTime.h:58
#define SPEED2DIST(x)
Definition SUMOTime.h:48
#define SIMSTEP
Definition SUMOTime.h:69
constexpr SUMOTime TIME2STEPS(double x)
Definition SUMOTime.h:60
#define SUMOTime_MIN
Definition SUMOTime.h:35
#define SIMTIME
Definition SUMOTime.h:70
const SVCPermissions SVCAll
all VClasses are allowed
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permissions is a (exclusive) railway edge.
bool isRailwayOrShared(SVCPermissions permissions)
Returns whether an edge with the given permissions is a railway edge or a shared road/rail edge.
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
@ AIRCRAFT
render as aircraft
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_SHIP
is an arbitrary ship
@ SVC_RAIL_CLASSES
classes which drive on tracks
@ SVC_BICYCLE
vehicle is a bicycle
const int STOP_DURATION_SET
@ GIVEN
The speed is given.
@ RANDOM
The lateral position is chosen randomly.
@ RIGHT
At the rightmost side of the lane.
@ GIVEN
The position is given.
@ DEFAULT
No information given; use default.
@ LEFT
At the leftmost side of the lane.
@ FREE
A free lateral position is chosen.
@ CENTER
At the center of the lane.
@ RANDOM_FREE
If a fixed number of random choices fails, a free lateral position is chosen.
@ RANDOM
A random position is chosen.
@ GIVEN
The position is given.
@ DEFAULT
No information given; use default.
@ STOP
depart position is endPos of first stop
@ FREE
A free position is chosen.
@ SPLIT_FRONT
depart position for a split vehicle is in front of the continuing vehicle
@ BASE
Back-at-zero position.
@ LAST
Insert behind the last vehicle as close as possible to still allow the specified departSpeed....
@ RANDOM_FREE
If a fixed number of random choices fails, a free position is chosen.
DepartSpeedDefinition
Possible ways to choose the departure speed.
@ RANDOM
The speed is chosen randomly.
@ MAX
The maximum safe speed is used.
@ GIVEN
The speed is given.
@ LIMIT
The maximum lane speed is used (speedLimit)
@ DEFAULT
No information given; use default.
@ DESIRED
The maximum lane speed is used (speedLimit * speedFactor)
@ LAST
The speed of the last vehicle. Fallback to DepartSpeedDefinition::DESIRED if there is no vehicle on t...
@ AVG
The average speed on the lane. Fallback to DepartSpeedDefinition::DESIRED if there is no vehicle on t...
const int STOP_START_SET
const int STOP_END_SET
@ SPLIT
The departure is triggered by a train split.
InsertionCheck
different checking levels for vehicle insertion
@ SUMO_TAG_LINK
Link information for state-saving.
@ SUMO_TAG_APPROACHING
Link-approaching vehicle information for state-saving.
@ SUMO_TAG_RNGLANE
@ SUMO_TAG_VIEWSETTINGS_VEHICLES
@ SUMO_TAG_LANE
begin/end of the description of a single lane
@ STRAIGHT
The link is a straight direction.
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic,...
@ LINKSTATE_ALLWAY_STOP
This is an uncontrolled, all-way stop link.
@ LINKSTATE_MAJOR
This is an uncontrolled, major link, may pass.
@ LINKSTATE_STOP
This is an uncontrolled, minor link, has to stop.
@ LINKSTATE_EQUAL
This is an uncontrolled, right-before-left link.
@ LINKSTATE_DEADEND
This is a dead end link.
@ LINKSTATE_ZIPPER
This is an uncontrolled, zipper-merge link.
@ LINKSTATE_MINOR
This is an uncontrolled, minor link, has to brake.
@ SUMO_ATTR_ARRIVALSPEED
@ SUMO_ATTR_JM_STOPLINE_CROSSING_GAP
@ SUMO_ATTR_ARRIVALTIME
@ SUMO_ATTR_WAITINGTIME
@ SUMO_ATTR_VALUE
@ SUMO_ATTR_POSITION_LAT
@ SUMO_ATTR_ARRIVALSPEEDBRAKING
@ SUMO_ATTR_INDEX
@ SUMO_ATTR_DEPARTSPEED
@ SUMO_ATTR_TO
@ SUMO_ATTR_DISTANCE
@ SUMO_ATTR_ID
@ SUMO_ATTR_REQUEST
@ SUMO_ATTR_STATE
The state of a link.
int gPrecision
the precision for floating point outputs
Definition StdDefs.cpp:27
int gPrecisionRandom
Definition StdDefs.cpp:30
double roundDecimal(double x, int precision)
round to the given number of decimal digits
Definition StdDefs.cpp:61
bool gDebugFlag4
Definition StdDefs.cpp:47
bool gDebugFlag1
global utility flags for debugging
Definition StdDefs.cpp:44
#define FALLTHROUGH
Definition StdDefs.h:39
T MIN2(T a, T b)
Definition StdDefs.h:80
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition StdDefs.h:62
T MAX2(T a, T b)
Definition StdDefs.h:86
T MAX3(T a, T b, T c)
Definition StdDefs.h:100
std::string joinNamedToString(const std::set< T *, C > &ns, const T_BETWEEN &between)
Definition ToString.h:374
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:57
A class that stores a 2D geometrical boundary.
Definition Boundary.h:39
double ymin() const
Returns minimum y-coordinate.
Definition Boundary.cpp:127
double xmin() const
Returns minimum x-coordinate.
Definition Boundary.cpp:115
Boundary & grow(double by)
extends the boundary by the given amount
Definition Boundary.cpp:340
double ymax() const
Returns maximum y-coordinate.
Definition Boundary.cpp:133
double xmax() const
Returns maximum x-coordinate.
Definition Boundary.cpp:121
static double angleDiff(const double angle1, const double angle2)
Returns the difference of the second angle to the first angle in radiants.
static double sum(double val)
Computes the resulting noise.
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition MELoop.cpp:397
A single mesoscopic segment (cell)
Definition MESegment.h:50
void setSpeed(double newSpeed, SUMOTime currentTime, double jamThresh=DO_NOT_PATCH_JAM_THRESHOLD, int qIdx=-1)
reset mySpeed and patch the speed of all vehicles in it. Also set/recompute myJamThreshold
MESegment * getNextSegment() const
Returns the following segment on the same edge (0 if it is the last).
Definition MESegment.h:253
Container & getContainer()
Definition MFXSynchQue.h:84
void unlock()
Definition MFXSynchQue.h:99
void unsetCondition()
Definition MFXSynchQue.h:79
void push_back(T what)
virtual double getExtraReservation(int bestLaneOffset, double neighExtraDist=0) const
MSLane * getShadowLane() const
Returns the lane the vehicle's shadow is on during continuous/sublane lane change.
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
The base class for microscopic and mesoscopic vehicles.
double getImpatience() const
Returns this vehicles impatience.
const MSEdge * succEdge(int nSuccs) const
Returns the nSuccs'th successor of edge the vehicle is currently at.
virtual double getArrivalPos() const
Returns this vehicle's desired arrivalPos for its current route (may change on reroute)
int getInsertionChecks() const
const SUMOVehicleParameter & getParameter() const
Returns the vehicle's parameter (including departure definition)
double getChosenSpeedFactor() const
Returns the precomputed factor by which the driver wants to be faster than the speed limit.
const SUMOVehicleParameter::Stop * getNextStopParameter() const
return parameters for the next stop (SUMOVehicle Interface)
bool isRail() const
bool isJumping() const
Returns whether the vehicle is perform a jump.
const MSRouteIterator & getCurrentRouteEdge() const
Returns an iterator pointing to the current edge in this vehicles route.
double getLength() const
Returns the vehicle's length.
bool isParking() const
Returns whether the vehicle is parking.
const MSEdge * getEdge() const
Returns the edge the vehicle is currently at.
bool hasDeparted() const
Returns whether this vehicle has already departed.
double basePos(const MSEdge *edge) const
departure position where the vehicle fits fully onto the edge (if possible)
bool hasStops() const
Returns whether the vehicle has to stop somewhere.
const MSStop & getNextStop() const
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
NumericalID getNumericalID() const
return the numerical ID which is only for internal usage
const MSRoute & getRoute() const
Returns the current route.
int getRoutePosition() const
return index of edge within route
SUMOTime getDepartDelay() const
Returns the depart delay.
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
bool isStopped() const
Returns whether the vehicle is at a stop.
MSDevice * getDevice(const std::type_info &type) const
Returns a device of the given type if it exists, nullptr otherwise.
The car-following model abstraction.
Definition MSCFModel.h:59
double getCollisionMinGapFactor() const
Get the factor of minGap that must be maintained to avoid a collision event.
Definition MSCFModel.h:337
double getEmergencyDecel() const
Get the vehicle type's maximal physically possible deceleration [m/s^2].
Definition MSCFModel.h:293
virtual double freeSpeed(const MSVehicle *const veh, double speed, double seen, double maxSpeed, const bool onInsertion=false, const CalcReason usage=CalcReason::CURRENT) const
Computes the vehicle's safe speed without a leader.
virtual double insertionFollowSpeed(const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle *const pred=0) const
Computes the vehicle's safe speed (no dawdling) This method is used during the insertion stage....
@ FUTURE
the return value is used for calculating future speeds
Definition MSCFModel.h:99
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 brakeGap(const double speed) const
Returns the distance the vehicle needs to halt including driver's reaction time tau (i....
Definition MSCFModel.h:424
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
Definition MSCFModel.h:285
double stopSpeed(const MSVehicle *const veh, const double speed, double gap, const CalcReason usage=CalcReason::CURRENT) const
Computes the vehicle's safe speed for approaching a non-moving obstacle (no dawdling)
Definition MSCFModel.h:189
virtual double insertionStopSpeed(const MSVehicle *const veh, double speed, double gap) const
Computes the vehicle's safe speed for approaching an obstacle at insertion without constraints due to...
std::string toString() const
print a debugging representation
int addFollower(const MSVehicle *veh, const MSVehicle *ego, double gap, double latOffset=0, int sublane=-1)
A device which collects info on the vehicle trip (mainly on departure and arrival)
bool sidingDeadlock(const SUMOVehicle *veh) const
whether insertion on this driveway would cause deadlock in an approached siding
static const MSDriveWay * getDepartureDriveway(const SUMOVehicle *veh, bool init=false)
bool foeDriveWayOccupied(bool store, const SUMOVehicle *ego, MSEdgeVector &occupied) const
whether any of myFoes is occupied (vehicles that are the target of a join must be ignored)
void gotActive(MSLane *l)
Informs the control that the given lane got active.
void checkCollisionForInactive(MSLane *l)
trigger collision checking for inactive lane
void needsVehicleIntegration(MSLane *const l)
A road/street connecting two junctions.
Definition MSEdge.h:78
void changeLanes(SUMOTime t) const
Performs lane changing on this edge.
Definition MSEdge.cpp:962
bool isCrossing() const
return whether this edge is a pedestrian crossing
Definition MSEdge.h:275
int getPriority() const
Returns the priority of the edge.
Definition MSEdge.h:338
const std::set< MSTransportable *, ComparatorNumericalIdLess > & getPersons() const
Returns this edge's persons set.
Definition MSEdge.h:205
bool isWalkingArea() const
return whether this edge is walking area
Definition MSEdge.h:289
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition MSEdge.h:169
const MSEdge * getNormalSuccessor() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
Definition MSEdge.cpp:1017
const std::vector< MSLane * > * allowedLanes(const MSEdge &destination, SUMOVehicleClass vclass=SVC_IGNORING, bool ignoreTransientPermissions=false) const
Get the allowed lanes to reach the destination-edge.
Definition MSEdge.cpp:516
const MSEdge * getBidiEdge() const
return opposite superposable/congruent edge, if it exist and 0 else
Definition MSEdge.h:284
bool isNormal() const
return whether this edge is an internal edge
Definition MSEdge.h:265
std::vector< MSTransportable * > getSortedPersons(SUMOTime timestep, bool includeRiding=false) const
Returns this edge's persons sorted by pos.
Definition MSEdge.cpp:1290
void recalcCache()
Recalculates the cached values.
Definition MSEdge.cpp:123
bool hasLaneChanger() const
Definition MSEdge.h:760
const MSJunction * getToJunction() const
Definition MSEdge.h:428
const MSJunction * getFromJunction() const
Definition MSEdge.h:424
int getNumLanes() const
Definition MSEdge.h:173
bool isInternal() const
return whether this edge is an internal edge
Definition MSEdge.h:270
bool isVaporizing() const
Returns whether vehicles on this edge shall be vaporized.
Definition MSEdge.h:444
MSLane * parallelLane(const MSLane *const lane, int offset, bool includeOpposite=true) const
Returns the lane with the given offset parallel to the given lane one or 0 if it does not exist.
Definition MSEdge.cpp:499
const std::string & getEdgeType() const
Returns the type of the edge.
Definition MSEdge.h:321
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition MSEdge.cpp:1007
void markDelayed() const
Definition MSEdge.h:751
const MSEdgeVector & getPredecessors() const
Definition MSEdge.h:419
void rebuildAllowedLanes(const bool onInit=false, bool updateVehicles=false)
Definition MSEdge.cpp:324
static SUMOTime gTimeToTeleportDisconnected
Definition MSGlobals.h:66
static bool gUseMesoSim
Definition MSGlobals.h:106
static SUMOTime gTimeToGridlockHighways
Definition MSGlobals.h:60
static bool gCheckRoutes
Definition MSGlobals.h:91
static double gGridlockHighwaysSpeed
Definition MSGlobals.h:63
static bool gRemoveGridlocked
Definition MSGlobals.h:75
static SUMOTime gTimeToTeleportBidi
Definition MSGlobals.h:69
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition MSGlobals.h:115
static double gLateralResolution
Definition MSGlobals.h:100
static SUMOTime gTimeToTeleportRSDeadlock
Definition MSGlobals.h:72
static bool gClearState
whether the simulation is in the process of clearing state (MSNet::clearState)
Definition MSGlobals.h:146
static bool gComputeLC
whether the simulationLoop is in the lane changing phase
Definition MSGlobals.h:143
static bool gEmergencyInsert
Definition MSGlobals.h:94
static int gNumSimThreads
how many threads to use for simulation
Definition MSGlobals.h:149
static SUMOTime gIgnoreJunctionBlocker
Definition MSGlobals.h:85
static bool gSublane
whether sublane simulation is enabled (sublane model or continuous lanechanging)
Definition MSGlobals.h:168
static SUMOTime gLaneChangeDuration
Definition MSGlobals.h:97
static bool gUnitTests
whether unit tests are being run
Definition MSGlobals.h:140
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition MSGlobals.h:81
static SUMOTime gTimeToGridlock
Definition MSGlobals.h:57
void retractDescheduleDeparture(const SUMOVehicle *veh)
reverts a previous call to descheduleDeparture (only needed for departPos="random_free")
void descheduleDeparture(const SUMOVehicle *veh)
stops trying to emit the given vehicle (and delete it)
The base class for an intersection.
Definition MSJunction.h:58
SumoXMLNodeType getType() const
return the type of this Junction
Definition MSJunction.h:133
AnyVehicleIterator is a structure, which manages the iteration through all vehicles on the lane,...
Definition MSLane.h:129
bool nextIsMyVehicles() const
Definition MSLane.cpp:206
AnyVehicleIterator & operator++()
Definition MSLane.cpp:172
const MSVehicle * operator*()
Definition MSLane.cpp:189
void add(const MSLane *const l) const
Adds the given object to the container.
Definition MSLane.cpp:125
std::set< const Named * > & myObjects
The container.
Definition MSLane.h:98
const double myRange
Definition MSLane.h:100
const PositionVector & myShape
Definition MSLane.h:99
Sorts edges by their angle relative to the given edge (straight comes first)
Definition MSLane.h:1731
by_connections_to_sorter(const MSEdge *const e)
constructor
Definition MSLane.cpp:3580
int operator()(const MSEdge *const e1, const MSEdge *const e2) const
comparing operator
Definition MSLane.cpp:3587
Sorts lanes (IncomingLaneInfos) by their priority or, if this doesn't apply, wrt. the angle differenc...
Definition MSLane.h:1750
incoming_lane_priority_sorter(const MSLane *targetLane)
constructor
Definition MSLane.cpp:3621
int operator()(const IncomingLaneInfo &lane1, const IncomingLaneInfo &lane2) const
comparing operator
Definition MSLane.cpp:3626
Sorts lanes (their origin link) by the priority of their noninternal target edges or,...
Definition MSLane.h:1768
outgoing_lane_priority_sorter(const MSLane *sourceLane)
constructor
Definition MSLane.cpp:3699
int operator()(const MSLink *link1, const MSLink *link2) const
comparing operator
Definition MSLane.cpp:3703
int operator()(MSVehicle *v1, MSVehicle *v2) const
Comparing operator.
Definition MSLane.cpp:3569
Sorts vehicles by their position (descending)
Definition MSLane.h:1685
int operator()(MSVehicle *v1, MSVehicle *v2) const
Comparing operator.
Definition MSLane.cpp:3557
Representation of a lane in the micro simulation.
Definition MSLane.h:84
void addApproachingLane(MSLane *lane, bool warnMultiCon)
Definition MSLane.cpp:2921
void loadState(const std::vector< SUMOVehicle * > &vehs)
Loads the state of this segment with the given parameters.
Definition MSLane.cpp:3820
bool detectCollisionBetween(SUMOTime timestep, const std::string &stage, MSVehicle *collider, MSVehicle *victim, std::set< const MSVehicle *, ComparatorNumericalIdLess > &toRemove, std::set< const MSVehicle *, ComparatorNumericalIdLess > &toTeleport) const
detect whether there is a collision between the two vehicles
Definition MSLane.cpp:1988
static SUMOTime myIntermodalCollisionStopTime
Definition MSLane.h:1676
MFXSynchQue< MSVehicle *, std::vector< MSVehicle * > > myVehBuffer
Buffer for vehicles that moved from their previous lane onto this one. Integrated after all vehicles ...
Definition MSLane.h:1530
SVCPermissions myPermissions
The vClass permissions for this lane.
Definition MSLane.h:1568
MSLane * myLogicalPredecessorLane
Definition MSLane.h:1584
static void initCollisionAction(const OptionsCont &oc, const std::string &option, CollisionAction &myAction)
Definition MSLane.cpp:4575
std::set< const MSBaseVehicle * > myParkingVehicles
Definition MSLane.h:1543
bool checkForPedestrians(const MSVehicle *aVehicle, double &speed, double &dist, double pos, bool patchSpeed) const
check whether pedestrians on this lane interfere with vehicle insertion
Definition MSLane.cpp:4683
static double myDefaultDepartSpeed
Definition MSLane.h:1680
std::pair< const MSPerson *, double > nextBlocking(double minPos, double minRight, double maxLeft, double stopTime=0, bool bidi=false) const
This is just a wrapper around MSPModel::nextBlocking. You should always check using hasPedestrians be...
Definition MSLane.cpp:4677
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:2905
double myRightSideOnEdge
the combined width of all lanes with lower index on myEdge
Definition MSLane.h:1634
const StopOffset & getLaneStopOffsets() const
Returns vehicle class specific stopOffsets.
Definition MSLane.cpp:3847
virtual void removeParking(MSBaseVehicle *veh)
remove parking vehicle. This must be syncrhonized when running with GUI
Definition MSLane.cpp:3744
virtual ~MSLane()
Destructor.
Definition MSLane.cpp:307
bool insertVehicle(MSVehicle &v)
Tries to insert the given vehicle.
Definition MSLane.cpp:692
bool mySpeedModified
Whether the current speed limit is set by a variable speed sign (VSS), TraCI or a MSCalibrator.
Definition MSLane.h:1565
const MSLeaderInfo getFirstVehicleInformation(const MSVehicle *ego, double latOffset, bool onlyFrontOnLane, double maxPos=std::numeric_limits< double >::max(), bool allowCached=true) const
analogue to getLastVehicleInformation but in the upstream direction
Definition MSLane.cpp:1550
virtual void integrateNewVehicles()
Insert buffered vehicle into the real lane.
Definition MSLane.cpp:2615
double myLength
Lane length [m].
Definition MSLane.h:1546
bool isApproachedFrom(MSEdge *const edge)
Definition MSLane.h:990
double getNettoOccupancy() const
Returns the netto (excluding minGaps) occupancy of this lane during the last step (including minGaps)
Definition MSLane.cpp:3466
virtual MSVehicle * removeVehicle(MSVehicle *remVehicle, MSMoveReminder::Notification notification, bool notify=true)
Definition MSLane.cpp:2887
int getCrossingIndex() const
return the index of the link to the next crossing if this is walkingArea, else -1
Definition MSLane.cpp:3421
PositionVector myShape
The shape of the lane.
Definition MSLane.h:1491
PositionVector * myOutlineShape
the outline of the lane (optional)
Definition MSLane.h:1494
std::map< long long, SVCPermissions > myPermissionChanges
Definition MSLane.h:1648
const std::map< SUMOVehicleClass, double > * myRestrictions
The vClass speed restrictions for this lane.
Definition MSLane.h:1578
virtual void incorporateVehicle(MSVehicle *veh, double pos, double speed, double posLat, const MSLane::VehCont::iterator &at, MSMoveReminder::Notification notification=MSMoveReminder::NOTIFICATION_DEPARTED)
Inserts the vehicle into this lane, and informs it about entering the network.
Definition MSLane.cpp:457
void initRestrictions()
initialized vClass-specific speed limits
Definition MSLane.cpp:316
std::vector< MSMoveReminder * > myMoveReminders
This lane's move reminder.
Definition MSLane.h:1668
bool hasApproaching() const
Definition MSLane.cpp:3749
void addParking(MSBaseVehicle *veh)
add parking vehicle. This should only used during state loading
Definition MSLane.cpp:3738
VehCont myTmpVehicles
Container for lane-changing vehicles. After completion of lane-change- process, the containers will b...
Definition MSLane.h:1526
static DepartSpeedDefinition myDefaultDepartSpeedDefinition
Definition MSLane.h:1679
MSLane(const std::string &id, double maxSpeed, double friction, double length, MSEdge *const edge, int numericalID, const PositionVector &shape, double width, SVCPermissions permissions, SVCPermissions changeLeft, SVCPermissions changeRight, int index, bool isRampAccel, const std::string &type, const PositionVector &outlineShape)
Constructor.
Definition MSLane.cpp:255
double getDepartSpeed(const MSVehicle &veh, bool &patchSpeed)
Definition MSLane.cpp:607
void updateInternalLanePermissions(SVCPermissions oldPermissions)
Propagate a permission change of this lane to internal lanes that mirror it.
Definition MSLane.cpp:4635
MSLeaderInfo myFollowerInfo
followers on all sublanes as seen by vehicles on consecutive lanes (cached)
Definition MSLane.h:1617
const MSLane * getNormalSuccessorLane() const
get normal lane following this internal lane, for normal lanes, the lane itself is returned
Definition MSLane.cpp:3306
int getVehicleNumber() const
Returns the number of vehicles on this lane (for which this lane is responsible)
Definition MSLane.h:457
static SUMOTime myCollisionStopTime
Definition MSLane.h:1675
static CollisionAction myCollisionAction
the action to take on collisions
Definition MSLane.h:1671
MSLane * myCanonicalSuccessorLane
Main successor lane,.
Definition MSLane.h:1590
SVCPermissions myChangeLeft
The vClass permissions for changing from this lane.
Definition MSLane.h:1571
void getLeadersOnConsecutive(double dist, double seen, double speed, const MSVehicle *ego, const std::vector< MSLane * > &bestLaneConts, MSLeaderDistanceInfo &result, bool oppositeDirection=false) const
Returns the immediate leaders and the distance to them (as getLeaderOnConsecutive but for the sublane...
Definition MSLane.cpp:4096
std::vector< IncomingLaneInfo > myIncomingLanes
All direct predecessor lanes.
Definition MSLane.h:1581
AnyVehicleIterator anyVehiclesEnd() const
end iterator for iterating over all vehicles touching this lane in downstream direction
Definition MSLane.h:496
static void insertIDs(std::vector< std::string > &into)
Adds the ids of all stored lanes into the given vector.
Definition MSLane.cpp:2570
bool hadPermissionChanges() const
Definition MSLane.cpp:4652
void sortPartialVehicles()
sorts myPartialVehicles
Definition MSLane.cpp:2642
double myFrictionCoefficient
Lane-wide friction coefficient [0..1].
Definition MSLane.h:1562
MSVehicle * getFirstAnyVehicle() const
returns the first vehicle that is fully or partially on this lane
Definition MSLane.cpp:2736
const MSLink * getEntryLink() const
Returns the entry link if this is an internal lane, else nullptr.
Definition MSLane.cpp:2824
int getVehicleNumberWithPartials() const
Returns the number of vehicles on this lane (including partial occupators)
Definition MSLane.h:465
static bool myCheckJunctionCollisions
Definition MSLane.h:1673
static void clear()
Clears the dictionary.
Definition MSLane.cpp:2561
virtual void resetManeuverReservation(MSVehicle *v)
Unregisters a vehicle, which previously registered for maneuvering into this lane.
Definition MSLane.cpp:439
SVCPermissions myOriginalPermissions
The original vClass permissions for this lane (before temporary modifications)
Definition MSLane.h:1575
MSEdge *const myEdge
The lane's edge, for routing only.
Definition MSLane.h:1557
double myNettoVehicleLengthSum
The current length of all vehicles on this lane, excluding their minGaps.
Definition MSLane.h:1596
std::pair< MSVehicle *const, double > getFollower(const MSVehicle *ego, double egoPos, double dist, MinorLinkMode mLinkMode, bool maxSearchDist=false) const
Find follower vehicle for the given ego vehicle (which may be on the opposite direction lane)
Definition MSLane.cpp:4482
static std::vector< MSLink * >::const_iterator succLinkSec(const SUMOVehicle &veh, int nRouteSuccs, const MSLane &succLinkSource, const std::vector< MSLane * > &conts)
Definition MSLane.cpp:2750
void detectPedestrianJunctionCollision(const MSVehicle *collider, const PositionVector &colliderBoundary, const MSLane *foeLane, SUMOTime timestep, const std::string &stage, std::set< const MSVehicle *, ComparatorNumericalIdLess > &toRemove, std::set< const MSVehicle *, ComparatorNumericalIdLess > &toTeleport)
detect whether a vehicle collids with pedestrians on the junction
Definition MSLane.cpp:1947
double getMissingRearGap(const MSVehicle *leader, double backOffset, double leaderSpeed) const
return by how much further the leader must be inserted to avoid rear end collisions
Definition MSLane.cpp:2946
double myMaxSpeed
Lane-wide speed limit [m/s].
Definition MSLane.h:1560
void saveState(OutputDevice &out)
Saves the state of this lane into the given stream.
Definition MSLane.cpp:3759
void markRecalculateBruttoSum()
Set a flag to recalculate the brutto (including minGaps) occupancy of this lane (used if mingap is ch...
Definition MSLane.cpp:2482
const MSLink * getLinkTo(const MSLane *const) const
returns the link to the given lane or nullptr, if it is not connected
Definition MSLane.cpp:2801
int myRightmostSublane
the index of the rightmost sublane of this lane on myEdge
Definition MSLane.h:1636
void setChangeRight(SVCPermissions permissions)
Sets the permissions for changing to the right neighbour lane.
Definition MSLane.cpp:4664
const MSLeaderInfo getLastVehicleInformation(const MSVehicle *ego, double latOffset, double minPos=0, bool allowCached=true, const MSVehicle *ignore=nullptr) const
Returns the last vehicles on the lane.
Definition MSLane.cpp:1488
const bool myIsRampAccel
whether this lane is an acceleration lane
Definition MSLane.h:1628
virtual void planMovements(const SUMOTime t)
Compute safe velocities for all vehicles based on positions and speeds from the last time step....
Definition MSLane.cpp:1605
MSLeaderDistanceInfo getFollowersOnConsecutive(const MSVehicle *ego, double backOffset, bool allSublanes, double searchDist=-1, MinorLinkMode mLinkMode=FOLLOW_ALWAYS, bool maxSearchDist=false) const
return the sublane followers with the largest missing rear gap among all predecessor lanes (within di...
Definition MSLane.cpp:3859
static void saveRNGStates(OutputDevice &out)
save random number generator states to the given output device
Definition MSLane.cpp:4763
SUMOTime myFollowerInfoTime
time step for which myFollowerInfo was last updated
Definition MSLane.h:1622
MSLeaderInfo myLeaderInfo
leaders on all sublanes as seen by approaching vehicles (cached)
Definition MSLane.h:1615
bool isInsertionSuccess(MSVehicle *vehicle, double speed, double pos, double posLat, bool recheckNextLanes, MSMoveReminder::Notification notification)
Tries to insert the given vehicle with the given state (speed and pos)
Definition MSLane.cpp:852
void forceVehicleInsertion(MSVehicle *veh, double pos, MSMoveReminder::Notification notification, double posLat=0)
Inserts the given vehicle at the given position.
Definition MSLane.cpp:1435
double getVehicleStopOffset(const MSVehicle *veh) const
Returns vehicle class specific stopOffset for the vehicle.
Definition MSLane.cpp:3834
static void initCollisionOptions(const OptionsCont &oc)
Definition MSLane.cpp:4591
int myNumericalID
Unique numerical ID (set on reading by netload)
Definition MSLane.h:1488
VehCont myVehicles
The lane's vehicles. This container holds all vehicles that have their front (longitudinally) and the...
Definition MSLane.h:1510
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition MSLane.h:602
MSLeaderInfo getPartialBeyond() const
get all vehicles that are inlapping from consecutive edges
Definition MSLane.cpp:4319
std::vector< MSVehicle * > VehCont
Container for vehicles.
Definition MSLane.h:119
bool checkFailure(const MSVehicle *aVehicle, double &speed, double &dist, const double nspeed, const bool patchSpeed, const std::string errorMsg, InsertionCheck check) const
Definition MSLane.cpp:819
static DictType myDict
Static dictionary to associate string-ids with objects.
Definition MSLane.h:1662
static void fill(RTREE &into)
Fills the given RTree with lane instances.
Definition MSLane.cpp:2578
double safeInsertionSpeed(const MSVehicle *veh, double seen, const MSLeaderInfo &leaders, double speed)
return the maximum safe speed for insertion behind leaders (a negative value indicates that safe inse...
Definition MSLane.cpp:1446
MSLane * myBidiLane
Definition MSLane.h:1645
std::vector< const MSJunction * > getUpcomingJunctions(double pos, double range, const std::vector< MSLane * > &contLanes) const
Returns all upcoming junctions within given range along the given (non-internal) continuation lanes m...
Definition MSLane.cpp:4406
void addIncomingLane(MSLane *lane, MSLink *viaLink)
Definition MSLane.cpp:2911
bool isWalkingArea() const
Definition MSLane.cpp:2693
const MSEdge * getNextNormal() const
Returns the lane's follower if it is an internal lane, the edge of the lane otherwise.
Definition MSLane.cpp:2514
void addLink(MSLink *link)
Delayed initialization.
Definition MSLane.cpp:335
std::set< MSVehicle * > getVehiclesInRange(const double a, const double b) const
Returns all vehicles on the lane overlapping with the interval [a,b].
Definition MSLane.cpp:4386
void enteredByLaneChange(MSVehicle *v)
Definition MSLane.cpp:3414
double getDepartPosLat(const MSVehicle &veh)
Definition MSLane.cpp:666
std::pair< MSVehicle *const, double > getOppositeLeader(const MSVehicle *ego, double dist, bool oppositeDir, MinorLinkMode mLinkMode=MinorLinkMode::FOLLOW_NEVER) const
Definition MSLane.cpp:4505
SVCPermissions getPermissions() const
Returns the vehicle class permissions for this lane.
Definition MSLane.h:640
LinkState getIncomingLinkState() const
get the state of the link from the logical predecessor to this lane
Definition MSLane.cpp:3372
void updateLengthSum()
updated current vehicle length sum (delayed to avoid lane-order-dependency)
Definition MSLane.cpp:2488
const std::vector< IncomingLaneInfo > & getIncomingLanes() const
Definition MSLane.h:984
static const long CHANGE_PERMISSIONS_PERMANENT
Definition MSLane.h:1408
virtual void addMoveReminder(MSMoveReminder *rem, bool addToVehicles=true)
Add a move-reminder to move-reminder container.
Definition MSLane.cpp:362
MSLane * getCanonicalPredecessorLane() const
Definition MSLane.cpp:3327
void resetPermissions(long long transientID)
Definition MSLane.cpp:4618
bool isPriorityCrossing() const
Definition MSLane.cpp:2687
MSVehicle * getLastFullVehicle() const
returns the last vehicle for which this lane is responsible or 0
Definition MSLane.cpp:2699
static void loadRNGState(int index, const std::string &state)
load random number generator state for the given rng index
Definition MSLane.cpp:4773
const std::string myLaneType
the type of this lane
Definition MSLane.h:1631
int myRNGIndex
Definition MSLane.h:1651
VehCont myManeuverReservations
The vehicles which registered maneuvering into the lane within their current action step....
Definition MSLane.h:1538
const MSJunction * getToJunction() const
Definition MSLane.cpp:4833
void addLeaders(const MSVehicle *vehicle, double vehPos, MSLeaderDistanceInfo &result, bool oppositeDirection=false)
get leaders for ego on the given lane
Definition MSLane.cpp:4229
static double myCheckJunctionCollisionMinGap
Definition MSLane.h:1674
double getLength() const
Returns the lane's length.
Definition MSLane.h:632
double myBruttoVehicleLengthSum
The current length of all vehicles on this lane, including their minGaps.
Definition MSLane.h:1593
bool mayContinue(const MSVehicle *veh) const
whether the route of the give vehicle might be extended on insertion
Definition MSLane.cpp:4839
const PositionVector & getShape() const
Returns this lane's shape.
Definition MSLane.h:534
static bool isFrontalCollision(const MSVehicle *collider, const MSVehicle *victim)
detect frontal collisions
Definition MSLane.cpp:2309
void setChangeLeft(SVCPermissions permissions)
Sets the permissions for changing to the left neighbour lane.
Definition MSLane.cpp:4658
std::vector< const MSLink * > getUpcomingLinks(double pos, double range, const std::vector< MSLane * > &contLanes) const
Returns all upcoming links within given range along the given (non-internal) continuation lanes measu...
Definition MSLane.cpp:4417
const MSLane * getFirstInternalInConnection(double &offset) const
Returns 0 if the lane is not internal. Otherwise the first part of the connection (sequence of intern...
Definition MSLane.cpp:2520
const MSJunction * getFromJunction() const
Definition MSLane.cpp:4827
static int getNumRNGs()
return the number of RNGs
Definition MSLane.h:251
void handleCollisionBetween(SUMOTime timestep, const std::string &stage, const MSVehicle *collider, const MSVehicle *victim, double gap, double latGap, std::set< const MSVehicle *, ComparatorNumericalIdLess > &toRemove, std::set< const MSVehicle *, ComparatorNumericalIdLess > &toTeleport) const
take action upon collision
Definition MSLane.cpp:2095
double getMaximumBrakeDist() const
compute maximum braking distance on this lane
Definition MSLane.cpp:2962
static CollisionAction myIntermodalCollisionAction
Definition MSLane.h:1672
const MSLane * getInternalFollowingLane(const MSLane *const) const
returns the internal lane leading to the given lane or nullptr, if there is none
Definition MSLane.cpp:2813
static std::vector< SumoRNG > myRNGs
Definition MSLane.h:1664
virtual void swapAfterLaneChange(SUMOTime t)
moves myTmpVehicles int myVehicles after a lane change procedure
Definition MSLane.cpp:2870
std::pair< MSVehicle *const, double > getCriticalLeader(double dist, double seen, double speed, const MSVehicle &veh) const
Returns the most dangerous leader and the distance to him.
Definition MSLane.cpp:3187
StopOffset myLaneStopOffset
Definition MSLane.h:1554
static void initRNGs(const OptionsCont &oc)
initialize rngs
Definition MSLane.cpp:4750
std::pair< MSVehicle *const, double > getLeaderOnConsecutive(double dist, double seen, double speed, const MSVehicle &veh, const std::vector< MSLane * > &bestLaneConts, bool considerCrossingFoes=true) const
Returns the immediate leader and the distance to him.
Definition MSLane.cpp:3046
std::set< MSVehicle * > getSurroundingVehicles(double startPos, double downstreamDist, double upstreamDist, std::shared_ptr< LaneCoverageInfo > checkedLanes) const
Returns all vehicles closer than downstreamDist along the road network starting on the given position...
Definition MSLane.cpp:4334
bool myRecalculateBruttoSum
Flag to recalculate the occupancy (including minGaps) after a change in minGap.
Definition MSLane.h:1605
virtual void removeMoveReminder(MSMoveReminder *rem)
Remove a move-reminder from move-reminder container.
Definition MSLane.cpp:374
void clearState()
Remove all vehicles before quick-loading state.
Definition MSLane.cpp:3803
MSLane * myCanonicalPredecessorLane
Similar to LogicalPredecessorLane,.
Definition MSLane.h:1587
bool myNeedsCollisionCheck
whether a collision check is currently needed
Definition MSLane.h:1639
bool isLinkEnd(std::vector< MSLink * >::const_iterator &i) const
Definition MSLane.h:881
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition MSLane.h:959
virtual double setPartialOccupation(MSVehicle *v)
Sets the information about a vehicle lapping into this lane.
Definition MSLane.cpp:386
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the lane's maximum speed, given a vehicle's speed limit adaptation.
Definition MSLane.h:575
void setBidiLane(MSLane *bidyLane)
Adds the (overlapping) reverse direction lane to this lane.
Definition MSLane.cpp:349
double getRightSideOnEdge() const
Definition MSLane.h:1229
void checkBufferType()
Definition MSLane.cpp:323
std::pair< MSVehicle *const, double > getOppositeFollower(const MSVehicle *ego) const
Definition MSLane.cpp:4533
bool hasPedestrians() const
whether the lane has pedestrians on it
Definition MSLane.cpp:4670
const std::vector< std::pair< const MSLane *, const MSEdge * > > getOutgoingViaLanes() const
get the list of outgoing lanes
Definition MSLane.cpp:3383
MSVehicle * getPartialBehind(const MSVehicle *ego) const
Definition MSLane.cpp:4296
void setLaneStopOffset(const StopOffset &stopOffset)
Set vehicle class specific stopOffsets.
Definition MSLane.cpp:3853
double myBruttoVehicleLengthSumToRemove
The length of all vehicles that have left this lane in the current step (this lane,...
Definition MSLane.h:1599
void leftByLaneChange(MSVehicle *v)
Definition MSLane.cpp:3407
MSLane * getCanonicalSuccessorLane() const
Definition MSLane.cpp:3351
std::vector< StopWatch< std::chrono::nanoseconds > > myStopWatch
Definition MSLane.h:1831
void setPermissions(SVCPermissions permissions, long long transientID)
Sets the permissions to the given value. If a transientID is given, the permissions are recored as te...
Definition MSLane.cpp:4604
const double myWidth
Lane width [m].
Definition MSLane.h:1549
bool lastInsertion(MSVehicle &veh, double mspeed, double posLat, bool patchSpeed)
inserts vehicle as close as possible to the last vehicle on this lane (or at the end of the lane if t...
Definition MSLane.cpp:482
void changeLanes(const SUMOTime time)
Definition MSLane.cpp:2508
double getOppositePos(double pos) const
return the corresponding position on the opposite lane
Definition MSLane.cpp:4477
SVCPermissions myChangeRight
Definition MSLane.h:1572
const double myLengthGeometryFactor
precomputed myShape.length / myLength
Definition MSLane.h:1625
virtual void executeMovements(const SUMOTime t)
Executes planned vehicle movements with regards to right-of-way.
Definition MSLane.cpp:2328
const std::set< const MSBaseVehicle * > & getParkingVehicles() const
retrieve the parking vehicles (see GUIParkingArea)
Definition MSLane.h:1288
MSLane * getLogicalPredecessorLane() const
get the most likely predecessor lane (sorted using by_connections_to_sorter). The result is cached in...
Definition MSLane.cpp:3271
double getBruttoOccupancy() const
Returns the brutto (including minGaps) occupancy of this lane during the last step.
Definition MSLane.cpp:3451
AnyVehicleIterator anyVehiclesUpstreamEnd() const
end iterator for iterating over all vehicles touching this lane in upstream direction
Definition MSLane.h:508
int myIndex
The lane index.
Definition MSLane.h:1497
bool isNormal() const
Definition MSLane.cpp:2675
bool isCrossing() const
Definition MSLane.cpp:2681
double getMeanSpeedBike() const
get the mean speed of all bicycles on this lane
Definition MSLane.cpp:3515
void updateLeaderInfo(const MSVehicle *veh, VehCont::reverse_iterator &vehPart, VehCont::reverse_iterator &vehRes, MSLeaderInfo &ahead) const
This updates the MSLeaderInfo argument with respect to the given MSVehicle. All leader-vehicles on th...
Definition MSLane.cpp:1653
double getWaitingSeconds() const
Returns the overall waiting time on this lane.
Definition MSLane.cpp:3481
bool hasUnsafeLink() const
whether any link from this lane is unsafe
Definition MSLane.cpp:4854
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition MSLane.cpp:2538
virtual void detectCollisions(SUMOTime timestep, const std::string &stage)
Check if vehicles are too close.
Definition MSLane.cpp:1706
std::vector< MSLink * > myLinks
Definition MSLane.h:1609
MSVehicle * getLastAnyVehicle() const
returns the last vehicle that is fully or partially on this lane
Definition MSLane.cpp:2717
bool isInternal() const
Definition MSLane.cpp:2669
VehCont myPartialVehicles
The lane's partial vehicles. This container holds all vehicles that are partially on this lane but wh...
Definition MSLane.h:1522
void sortManeuverReservations()
sorts myManeuverReservations
Definition MSLane.cpp:2650
MinorLinkMode
determine whether/how getFollowers looks upstream beyond minor links
Definition MSLane.h:1007
@ FOLLOW_ONCOMING
Definition MSLane.h:1010
@ FOLLOW_ALWAYS
Definition MSLane.h:1009
@ FOLLOW_NEVER
Definition MSLane.h:1008
void setMaxSpeed(const double val, const bool modified=true, const double jamThreshold=-1)
Sets a new maximum speed for the lane (used by TraCI, MSLaneSpeedTrigger (VSS) and MSCalibrator)
Definition MSLane.cpp:2841
AnyVehicleIterator anyVehiclesUpstreamBegin() const
begin iterator for iterating over all vehicles touching this lane in upstream direction
Definition MSLane.h:502
std::vector< const MSLane * > getNormalIncomingLanes() const
get the list of all direct (disregarding internal predecessors) non-internal predecessor lanes of thi...
Definition MSLane.cpp:3393
virtual void resetPartialOccupation(MSVehicle *v)
Removes the information about a vehicle lapping into this lane.
Definition MSLane.cpp:405
void setOpposite(MSLane *oppositeLane)
Adds a neighbor to this lane.
Definition MSLane.cpp:341
AnyVehicleIterator anyVehiclesBegin() const
begin iterator for iterating over all vehicles touching this lane in downstream direction
Definition MSLane.h:490
double getHarmonoise_NoiseEmissions() const
Returns the sum of last step noise emissions.
Definition MSLane.cpp:3540
std::pair< MSVehicle *const, double > getLeader(const MSVehicle *veh, const double vehPos, const std::vector< MSLane * > &bestLaneConts, double dist=-1, bool checkTmpVehicles=false) const
Returns the immediate leader of veh and the distance to veh starting on this lane.
Definition MSLane.cpp:2974
void handleIntermodalCollisionBetween(SUMOTime timestep, const std::string &stage, const MSVehicle *collider, const MSTransportable *victim, double gap, const std::string &collisionType, std::set< const MSVehicle *, ComparatorNumericalIdLess > &toRemove, std::set< const MSVehicle *, ComparatorNumericalIdLess > &toTeleport) const
Definition MSLane.cpp:2232
static bool myExtrapolateSubstepDepart
Definition MSLane.h:1678
MSLane * getOpposite() const
return the neighboring opposite direction lane for lane changing or nullptr
Definition MSLane.cpp:4465
void setLength(double val)
Sets a new length for the lane (used by TraCI only)
Definition MSLane.cpp:2863
std::map< MSEdge *, std::vector< MSLane * > > myApproachingLanes
All direct internal and direct (disregarding internal predecessors) non-internal predecessor lanes of...
Definition MSLane.h:1612
virtual const VehCont & getVehiclesSecure() const
Returns the vehicles container; locks it for microsimulation.
Definition MSLane.h:484
virtual void releaseVehicles() const
Allows to use the container for microsimulation again.
Definition MSLane.h:514
bool mustCheckJunctionCollisions() const
whether this lane must check for junction collisions
Definition MSLane.cpp:4788
virtual void setManeuverReservation(MSVehicle *v)
Registers the lane change intentions (towards this lane) for the given vehicle.
Definition MSLane.cpp:428
virtual void setJunctionApproaches() const
Register junction approaches for all vehicles after velocities have been planned.
Definition MSLane.cpp:1645
MSLane * getBidiLane() const
retrieve bidirectional lane or nullptr
Definition MSLane.cpp:4782
static double myCollisionMinGapFactor
Definition MSLane.h:1677
SUMOTime myLeaderInfoTime
time step for which myLeaderInfo was last updated
Definition MSLane.h:1620
MSLane * myOpposite
Definition MSLane.h:1642
CollisionAction
Definition MSLane.h:201
@ COLLISION_ACTION_NONE
Definition MSLane.h:202
@ COLLISION_ACTION_WARN
Definition MSLane.h:203
@ COLLISION_ACTION_TELEPORT
Definition MSLane.h:204
@ COLLISION_ACTION_REMOVE
Definition MSLane.h:205
virtual const PositionVector & getShape(bool) const
Definition MSLane.h:294
MSLane * getParallelOpposite() const
return the opposite direction lane of this lanes edge or nullptr
Definition MSLane.cpp:4471
std::map< std::string, MSLane * > DictType
definition of the static dictionary type
Definition MSLane.h:1654
double getFractionalVehicleLength(bool brutto) const
return length of fractional vehicles on this lane
Definition MSLane.cpp:3432
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:790
double getSpaceTillLastStanding(const MSVehicle *ego, bool &foundStopped) const
return the empty space up to the last standing vehicle or the empty space on the whole lane if no veh...
Definition MSLane.cpp:4797
const MSLane * getNormalPredecessorLane() const
get normal lane leading to this internal lane, for normal lanes, the lane itself is returned
Definition MSLane.cpp:3296
virtual bool appropriate(const MSVehicle *veh) const
Definition MSLane.cpp:2594
double getWidth() const
Returns the lane's width.
Definition MSLane.h:661
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
Definition MSLane.h:750
bool freeInsertion(MSVehicle &veh, double speed, double posLat, MSMoveReminder::Notification notification=MSMoveReminder::NOTIFICATION_DEPARTED)
Tries to insert the given vehicle on any place.
Definition MSLane.cpp:517
MSVehicle * getFirstFullVehicle() const
returns the first vehicle for which this lane is responsible or 0
Definition MSLane.cpp:2708
double getMeanSpeed() const
Returns the mean speed on this lane.
Definition MSLane.cpp:3494
double myNettoVehicleLengthSumToRemove
The length of all vehicles that have left this lane in the current step (this lane,...
Definition MSLane.h:1602
void setFrictionCoefficient(double val)
Sets a new friction coefficient for the lane [to be later (used by TraCI and MSCalibrator)].
Definition MSLane.cpp:2856
static CollisionAction getCollisionAction()
Definition MSLane.h:1391
saves leader/follower vehicles and their distances relative to an ego vehicle
virtual std::string toString() const
print a debugging representation
CLeaderDist getClosest() const
return vehicle with the smalles gap
virtual int addLeader(const MSVehicle *veh, double gap, double latOffset=0, int sublane=-1)
bool hasVehicle(const MSVehicle *veh) const
whether the given vehicle is part of this leaderInfo
void setSublaneOffset(int offset)
set number of sublanes by which to shift positions
int numFreeSublanes() const
int numSublanes() const
virtual int addLeader(const MSVehicle *veh, bool beyond, double latOffset=0.)
virtual std::string toString() const
print a debugging representation
bool hasVehicles() const
int getSublaneOffset() const
Something on a lane to be noticed about vehicle movement.
Notification
Definition of a vehicle state.
@ NOTIFICATION_ARRIVED
The vehicle arrived at its destination (is deleted)
@ NOTIFICATION_TELEPORT_ARRIVED
The vehicle was teleported out of the net.
@ NOTIFICATION_DEPARTED
The vehicle has departed (was inserted into the network)
@ NOTIFICATION_VAPORIZED_VAPORIZER
The vehicle got vaporized with a vaporizer.
@ NOTIFICATION_VAPORIZED_BREAKDOWN
The vehicle got removed via stationfinder device.
@ NOTIFICATION_VAPORIZED_COLLISION
The vehicle got removed by a collision.
@ NOTIFICATION_LOAD_STATE
The vehicle has been loaded from a state file.
@ NOTIFICATION_TELEPORT
The vehicle is being teleported.
The simulated network and simulation perfomer.
Definition MSNet.h:89
@ COLLISION
The vehicle is involved in a collision.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:201
static const std::string STAGE_MOVEMENTS
Definition MSNet.h:870
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:334
const std::map< SUMOVehicleClass, double > * getRestrictions(const std::string &id) const
Returns the restrictions for an edge type If no restrictions are present, 0 is returned.
Definition MSNet.cpp:382
void informVehicleStateListener(const SUMOVehicle *const vehicle, VehicleState to, const std::string &info="")
Informs all added listeners about a vehicle's state change.
Definition MSNet.cpp:1402
bool hasPersons() const
Returns whether persons are simulated.
Definition MSNet.h:419
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition MSNet.h:455
static const std::string STAGE_LANECHANGE
Definition MSNet.h:871
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:402
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition MSNet.cpp:1317
bool registerCollision(const SUMOTrafficObject *collider, const SUMOTrafficObject *victim, const std::string &collisionType, const MSLane *lane, double pos)
register collision and return whether it was the first one involving these vehicles
Definition MSNet.cpp:1441
MSEdgeControl & getEdgeControl()
Returns the edge control.
Definition MSNet.h:445
virtual PersonDist nextBlocking(const MSLane *lane, double minPos, double minRight, double maxLeft, double stopTime=0, bool bidi=false)
returns the next pedestrian beyond minPos that is laterally between minRight and maxLeft or nullptr
Definition MSPModel.h:124
virtual bool hasPedestrians(const MSLane *lane)
whether the given lane has pedestrians on it
Definition MSPModel.h:110
static const double SAFETY_GAP
Definition MSPModel.h:59
static bool isSignalized(SUMOVehicleClass svc)
static MSRailSignalControl & getInstance()
bool haveDeadlock(const SUMOVehicle *veh) const
whether there is a circle in the waiting-for relationships that contains the given vehicle
static bool hasInsertionConstraint(MSLink *link, const MSVehicle *veh, std::string &info, bool &isInsertionOrder)
int size() const
Returns the number of edges to pass.
Definition MSRoute.cpp:85
const MSEdge * getLastEdge() const
returns the destination edge
Definition MSRoute.cpp:91
MSRouteIterator begin() const
Returns the begin of the list of edges to pass.
Definition MSRoute.cpp:73
const MSLane * lane
The lane to stop at (microsim only)
Definition MSStop.h:50
MSRouteIterator edge
The edge in the route to stop at.
Definition MSStop.h:48
double getEndPos(const SUMOVehicle &veh) const
return halting position for upcoming stop;
Definition MSStop.cpp:38
const SUMOVehicleParameter::Stop pars
The stop parameter.
Definition MSStop.h:65
MSPModel * getMovementModel()
Returns the default movement model for this kind of transportables.
virtual double getEdgePos() const
Return the position on the edge.
const MSVehicleType & getVehicleType() const override
Returns the object's "vehicle" type.
Reroutes traffic objects passing an edge.
bool isRemoteAffected(SUMOTime t) const
The class responsible for building and deletion of vehicles.
void registerTeleportYield()
register one non-collision-related teleport
double getMinDeceleration() const
return the minimum deceleration capability for all road vehicles that ever entered the network
void countCollision(bool teleport)
registers one collision-related teleport
double getMaxMinGap() const
return the maximum minGap for all vehicles that ever entered the network
void registerTeleportJam()
register one non-collision-related teleport
double getMaxSpeedFactor() const
return the maximum speed factor for all vehicles that ever entered the network
double getMinDecelerationRail() const
return the minimum deceleration capability for all ral vehicles that ever entered the network
void scheduleVehicleRemoval(SUMOVehicle *veh, bool checkDuplicate=false)
Removes a vehicle after it has ended.
void registerTeleportWrongLane()
register one non-collision-related teleport
Representation of a vehicle in the micro simulation.
Definition MSVehicle.h:77
double getRightSideOnEdge(const MSLane *lane=0) const
Get the vehicle's lateral position on the edge of the given lane (or its current edge if lane == 0)
void checkLinkLeader(const MSLink *link, const MSLane *lane, double seen, DriveProcessItem *const lastLink, double &v, double &vLinkPass, double &vLinkWait, bool &setRequest, bool isShadowLink=false) const
checks for link leaders on the given link
void updateBestLanes(bool forceRebuild=false, const MSLane *startLane=0)
computes the best lanes to use in order to continue the route
bool isOnRoad() const
Returns the information whether the vehicle is on a road (is simulated)
Definition MSVehicle.h:605
SUMOTime getLastActionTime() const
Returns the time of the vehicle's last action point.
Definition MSVehicle.h:541
PositionVector getBoundingPoly(double offset=0) const
get bounding polygon
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...
bool brokeDown() const
Returns how long the vehicle has been stopped already due to lack of energy.
void registerInsertionApproach(MSLink *link, double dist)
register approach on insertion
void enterLaneAtInsertion(MSLane *enteredLane, double pos, double speed, double posLat, MSMoveReminder::Notification notification)
Update when the vehicle enters a new lane in the emit step.
SUMOTime getWaitingTime(const bool accumulated=false) const
Returns the SUMOTime waited (speed was lesser than 0.1m/s)
Definition MSVehicle.h:670
bool isFrontOnLane(const MSLane *lane) const
Returns the information whether the front of the vehicle is on the given lane.
MSAbstractLaneChangeModel & getLaneChangeModel()
double getLeftSideOnLane() const
Get the lateral position of the vehicles left side on the lane:
double getActionStepLengthSecs() const
Returns the vehicle's action step length in secs, i.e. the interval between two action points.
Definition MSVehicle.h:533
const std::vector< MSLane * > getUpstreamOppositeLanes() const
Returns the sequence of opposite lanes corresponding to past lanes.
PositionVector getBoundingBox(double offset=0) const
get bounding rectangle
Position getPosition(const double offset=0) const
Return current position (x/y, cartesian)
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the best sequence of lanes to continue the route starting at myLane.
bool ignoreCollision() const
whether this vehicle is except from collision checks
void onRemovalFromNet(const MSMoveReminder::Notification reason)
Called when the vehicle is removed from the network.
bool resumeFromStopping()
int getBestLaneOffset() const
void adaptToJunctionLeader(const std::pair< const MSVehicle *, double > leaderInfo, const double seen, DriveProcessItem *const lastLink, const MSLane *const lane, double &v, double &vLinkPass, double distToCrossing=-1) const
double getBackPositionOnLane(const MSLane *lane) const
Get the vehicle's position relative to the given lane.
Definition MSVehicle.h:398
void resetActionOffset(const SUMOTime timeUntilNextAction=0)
Resets the action offset for the vehicle.
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.
double getLatOffset(const MSLane *lane) const
Get the offset that that must be added to interpret myState.myPosLat for the given lane.
bool hasArrived() const
Returns whether this vehicle has already arrived (reached the arrivalPosition on its final edge)
SUMOTime collisionStopTime() const
Returns the remaining time a vehicle needs to stop due to a collision. A negative value indicates tha...
double getBestLaneDist() const
returns the distance that can be driven without lane change
bool executeMove()
Executes planned vehicle movements with regards to right-of-way.
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition MSVehicle.h:581
bool isLeader(const MSLink *link, const MSVehicle *veh, const double gap) const
whether the given vehicle must be followed at the given junction
MSLane * getMutableLane() const
Returns the lane the vehicle is on Non const version indicates that something volatile is going on.
Definition MSVehicle.h:589
Influencer & getInfluencer()
bool isBidiOn(const MSLane *lane) const
whether this vehicle is driving against lane
double getRightSideOnLane() const
Get the lateral position of the vehicles right side on the lane:
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
Definition MSVehicle.h:413
double getSpeed() const
Returns the vehicle's current speed.
Definition MSVehicle.h:490
const std::vector< MSLane * > & getFurtherLanes() const
Definition MSVehicle.h:839
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition MSVehicle.h:973
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
double getAngle() const
Returns the vehicle's direction in radians.
Definition MSVehicle.h:735
bool hasInfluencer() const
whether the vehicle is individually influenced (via TraCI or special parameters)
Definition MSVehicle.h:1706
double getBrakeGap(bool delayed=false) const
get distance for coming to a stop (used for rerouting checks)
void executeFractionalMove(double dist)
move vehicle forward by the given distance during insertion
double getCenterOnEdge(const MSLane *lane=0) const
Get the vehicle's lateral position on the edge of the given lane (or its current edge if lane == 0)
int getLaneIndex() const
static MSVehicleTransfer * getInstance()
Returns the instance of this object.
void add(const SUMOTime t, MSVehicle *veh)
Adds a vehicle to this transfer object.
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
double getMinGap() const
Get the free space in front of vehicles of this class.
double getLength() const
Get vehicle's length [m].
SUMOVehicleShape getGuiShape() const
Get this vehicle type's shape.
const SUMOVTypeParameter & getParameter() const
Base class for objects which have an id.
Definition Named.h:53
std::string myID
The name of the object.
Definition Named.h:124
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:66
const std::string & getID() const
Returns the id.
Definition Named.h:73
A RT-tree for efficient storing of SUMO's Named objects.
Definition NamedRTree.h:61
A storage for options typed value containers)
Definition OptionsCont.h:89
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
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 & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const ATTR_TYPE &attr, const T &val, const bool isNull=false, const bool escape=false)
writes a named attribute
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
void unsetParameter(const std::string &key)
Removes a parameter.
virtual void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition Position.h:273
A list of positions.
bool overlapsWith(const AbstractPoly &poly, double offset=0) const
Returns the information whether the given polygon overlaps with this.
double distance2D(const Position &p, bool perpendicular=false) const
closest 2D-distance to point p (or -1 if perpendicular is true and the point is beyond this vector)
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
double angleAt2D(int pos) const
get angle in certain position of position vector (in radians between -M_PI and M_PI)
static void loadState(const std::string &state, SumoRNG *rng=nullptr)
load rng state from string
Definition RandHelper.h:244
static void initRand(SumoRNG *which=nullptr, const bool random=false, const int seed=23423)
Initialises the random number generator with hardware randomness or seed.
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
static std::string saveState(SumoRNG *rng=nullptr)
save rng state to string
Definition RandHelper.h:231
virtual SUMOVehicleClass getVClass() const =0
Returns the object's access class.
SUMOTime getTimeToTeleport(SUMOTime defaultValue) const
return time-to-teleport (either custom or default)
SUMOTime getTimeToTeleportBidi(SUMOTime defaultValue) const
return time-to-teleport.bidi (either custom or default)
double getJMParam(const SumoXMLAttr attr, const double defaultValue) const
Returns the named value from the map, or the default if it is not contained there.
Representation of a vehicle.
Definition SUMOVehicle.h:63
virtual const MSEdge * succEdge(int nSuccs) const =0
Returns the nSuccs'th successor of edge the vehicle is currently at.
Definition of vehicle stop (position and duration)
std::string lane
The lane to stop at.
double speed
the speed at which this stop counts as reached (waypoint mode)
std::string split
the id of the vehicle (train portion) that splits of upon reaching this stop
double startPos
The stopping position start.
int parametersSet
Information for the output which parameter were set.
double endPos
The stopping position end.
bool collision
Whether this stop was triggered by a collision.
SUMOTime duration
The stopping duration.
Structure representing possible vehicle parameter.
double departPosLat
(optional) The lateral position the vehicle shall depart from
ArrivalSpeedDefinition arrivalSpeedProcedure
Information how the vehicle's end speed shall be chosen.
double departSpeed
(optional) The initial speed of the vehicle
DepartPosLatDefinition departPosLatProcedure
Information how the vehicle shall choose the lateral departure position.
double departPos
(optional) The position the vehicle shall depart from
DepartSpeedDefinition departSpeedProcedure
Information how the vehicle's initial speed shall be chosen.
double arrivalSpeed
(optional) The final speed of the vehicle (not used yet)
DepartDefinition departProcedure
Information how the vehicle shall choose the depart time.
DepartPosDefinition departPosProcedure
Information how the vehicle shall choose the departure position.
A scoped lock which only triggers on condition.
stop offset
bool isDefined() const
check if stopOffset was defined
SVCPermissions getPermissions() const
get permissions
double getOffset() const
get offset
#define DEBUG_COND
TRACI_CONST int CMD_GET_VEHICLE_VARIABLE
TRACI_CONST int CMD_GET_EDGE_VARIABLE
TRACI_CONST int CMD_GET_PERSON_VARIABLE
TRACI_CONST int CMD_GET_LANE_VARIABLE
TRACI_CONST int ROUTING_MODE_IGNORE_TRANSIENT_PERMISSIONS
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression, cppcoreguidelines-noexcept-swap, performance-noexcept-swap) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition json.hpp:25297
#define M_PI
Definition odrSpiral.cpp:45