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-2025 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
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
59#include <mesosim/MELoop.h>
60#include "MSNet.h"
61#include "MSVehicleType.h"
62#include "MSEdge.h"
63#include "MSEdgeControl.h"
64#include "MSJunction.h"
65#include "MSLogicJunction.h"
66#include "MSLink.h"
67#include "MSLane.h"
68#include "MSVehicleTransfer.h"
69#include "MSGlobals.h"
70#include "MSVehicleControl.h"
71#include "MSInsertionControl.h"
72#include "MSVehicleControl.h"
73#include "MSLeaderInfo.h"
74#include "MSVehicle.h"
75#include "MSStop.h"
76
77//#define DEBUG_INSERTION
78//#define DEBUG_PLAN_MOVE
79//#define DEBUG_EXEC_MOVE
80//#define DEBUG_CONTEXT
81//#define DEBUG_PARTIALS
82//#define DEBUG_OPPOSITE
83//#define DEBUG_VEHICLE_CONTAINER
84//#define DEBUG_COLLISIONS
85//#define DEBUG_JUNCTION_COLLISIONS
86//#define DEBUG_PEDESTRIAN_COLLISIONS
87//#define DEBUG_LANE_SORTER
88//#define DEBUG_NO_CONNECTION
89//#define DEBUG_SURROUNDING
90//#define DEBUG_EXTRAPOLATE_DEPARTPOS
91//#define DEBUG_ITERATOR
92
93//#define DEBUG_COND (false)
94//#define DEBUG_COND (true)
95//#define DEBUG_COND (getID() == "undefined")
96#define DEBUG_COND (isSelected())
97//#define DEBUG_COND2(obj) ((obj != 0 && (obj)->getID() == "disabled"))
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 << " myI1=" << myI1
210 << " myI1End=" << myI1End
211 << " myI2=" << myI2
212 << " myI2End=" << myI2End
213 << " myI3=" << myI3
214 << " myI3End=" << myI3End
215 << "\n";
216#endif
217 if (myI1 == myI1End && myI3 == myI3End) {
218 if (myI2 != myI2End) {
219 return false;
220 } else {
221 return true; // @note. must be caught
222 }
223 } else {
224 if (myI2 == myI2End) {
225 return true;
226 } else {
227 MSVehicle* cand = myI1 == myI1End ? myLane->myTmpVehicles[myI3] : myLane->myVehicles[myI1];
228#ifdef DEBUG_ITERATOR
229 if (DEBUG_COND2(myLane)) std::cout << " "
230 << " veh1=" << cand->getID()
231 << " isTmp=" << (myI1 == myI1End)
232 << " veh2=" << myLane->myPartialVehicles[myI2]->getID()
233 << " pos1=" << cand->getPositionOnLane(myLane)
234 << " pos2=" << myLane->myPartialVehicles[myI2]->getPositionOnLane(myLane)
235 << "\n";
236#endif
237 if (cand->getPositionOnLane() < myLane->myPartialVehicles[myI2]->getPositionOnLane(myLane)) {
238 return myDownstream;
239 } else {
240 return !myDownstream;
241 }
242 }
243 }
244}
245
246
247// ===========================================================================
248// member method definitions
249// ===========================================================================
250#ifdef _MSC_VER
251#pragma warning(push)
252#pragma warning(disable: 4355) // mask warning about "this" in initializers
253#endif
254MSLane::MSLane(const std::string& id, double maxSpeed, double friction, double length, MSEdge* const edge,
255 int numericalID, const PositionVector& shape, double width,
256 SVCPermissions permissions,
257 SVCPermissions changeLeft, SVCPermissions changeRight,
258 int index, bool isRampAccel,
259 const std::string& type,
260 const PositionVector& outlineShape) :
261 Named(id),
262 myNumericalID(numericalID), myShape(shape), myIndex(index),
263 myVehicles(), myLength(length), myWidth(width),
264 myEdge(edge), myMaxSpeed(maxSpeed),
265 myFrictionCoefficient(friction),
266 mySpeedByVSS(false),
267 mySpeedByTraCI(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_CONTEXT
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_CONTEXT
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);
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 // stil, emit a warning
834 WRITE_WARNINGF(TL("Vehicle '%' is inserted in emergency situation."), aVehicle->getID());
835 return false;
836 }
837 }
838
839 if (errorMsg != "") {
840 WRITE_ERRORF(TL("Vehicle '%' will not be able to depart using the given velocity (%)!"), aVehicle->getID(), errorMsg);
842 }
843 return true;
844 }
845 }
846 return false;
847}
848
849
850bool
852 double speed, double pos, double posLat, bool patchSpeed,
853 MSMoveReminder::Notification notification) {
854 int insertionChecks = aVehicle->getInsertionChecks();
855 if (pos < 0 || pos > myLength) {
856 // we may not start there
857 WRITE_WARNINGF(TL("Invalid departPos % given for vehicle '%'. Inserting at lane end instead."),
858 pos, aVehicle->getID());
859 pos = myLength;
860 }
861
862#ifdef DEBUG_INSERTION
863 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
864 std::cout << "\nIS_INSERTION_SUCCESS\n"
865 << SIMTIME << " lane=" << getID()
866 << " veh '" << aVehicle->getID()
867 << " bestLanes=" << toString(aVehicle->getBestLanesContinuation(this))
868 << " pos=" << pos
869 << " speed=" << speed
870 << " patchSpeed=" << patchSpeed
871 << "'\n";
872 }
873#endif
874
875 aVehicle->setTentativeLaneAndPosition(this, pos, posLat);
876 aVehicle->updateBestLanes(false, this);
877 const MSCFModel& cfModel = aVehicle->getCarFollowModel();
878 const std::vector<MSLane*>& bestLaneConts = aVehicle->getBestLanesContinuation(this);
879 std::vector<MSLane*>::const_iterator ri = bestLaneConts.begin();
880 double seen = getLength() - pos; // == distance from insertion position until the end of the currentLane
881 double dist = cfModel.brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
882 const bool isRail = aVehicle->isRail();
883 if (isRail && insertionChecks != (int)InsertionCheck::NONE
886 const MSDriveWay* dw = MSDriveWay::getDepartureDriveway(aVehicle);
887 MSEdgeVector occupied;
888 if (dw->foeDriveWayOccupied(false, aVehicle, occupied)) {
889 setParameter("insertionBlocked:" + aVehicle->getID(), dw->getID());
890#ifdef DEBUG_INSERTION
891 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
892 std::cout << " foe of driveway " + dw->getID() + " has occupied edges " + toString(occupied) << "\n";
893 }
894#endif
895 return false;
896 }
897 }
898 // do not insert if the bidirectional edge is occupied
899 if (getBidiLane() != nullptr && isRail && getBidiLane()->getVehicleNumberWithPartials() > 0) {
900 if ((insertionChecks & (int)InsertionCheck::BIDI) != 0) {
901#ifdef DEBUG_INSERTION
902 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
903 std::cout << " bidi-lane occupied\n";
904 }
905#endif
906 return false;
907 }
908 }
909 MSLink* firstRailSignal = nullptr;
910 double firstRailSignalDist = -1;
911
912 // before looping through the continuation lanes, check if a stop is scheduled on this lane
913 // (the code is duplicated in the loop)
914 if (aVehicle->hasStops()) {
915 const MSStop& nextStop = aVehicle->getNextStop();
916 if (nextStop.lane == this) {
917 std::stringstream msg;
918 double distToStop, safeSpeed;
919 if (nextStop.pars.speed > 0) {
920 msg << "scheduled waypoint on lane '" << myID << "' too close";
921 distToStop = MAX2(0.0, nextStop.pars.startPos - pos);
922 safeSpeed = cfModel.freeSpeed(aVehicle, speed, distToStop, nextStop.pars.speed, true, MSCFModel::CalcReason::FUTURE);
923 } else {
924 msg << "scheduled stop on lane '" << myID << "' too close";
925 distToStop = nextStop.pars.endPos - pos;
926 safeSpeed = cfModel.stopSpeed(aVehicle, speed, distToStop, MSCFModel::CalcReason::FUTURE);
927 }
928 if (checkFailure(aVehicle, speed, dist, MAX2(0.0, safeSpeed), patchSpeed, msg.str(), InsertionCheck::STOP)) {
929 // we may not drive with the given velocity - we cannot stop at the stop
930 return false;
931 }
932 }
933 }
934
935 const MSRoute& r = aVehicle->getRoute();
936 MSRouteIterator ce = r.begin();
937 int nRouteSuccs = 1;
938 MSLane* currentLane = this;
939 MSLane* nextLane = this;
941 while ((seen < dist || (isRail && firstRailSignal == nullptr)) && ri != bestLaneConts.end()) {
942 // get the next link used...
943 std::vector<MSLink*>::const_iterator link = succLinkSec(*aVehicle, nRouteSuccs, *currentLane, bestLaneConts);
944 if (currentLane->isLinkEnd(link)) {
945 if (&currentLane->getEdge() == r.getLastEdge()) {
946 // reached the end of the route
948 const double remaining = seen + aVehicle->getArrivalPos() - currentLane->getLength();
949 const double nspeed = cfModel.freeSpeed(aVehicle, speed, remaining, aVehicle->getParameter().arrivalSpeed, true, MSCFModel::CalcReason::FUTURE);
950 if (checkFailure(aVehicle, speed, dist, nspeed,
951 patchSpeed, "arrival speed too low", InsertionCheck::ARRIVAL_SPEED)) {
952 // we may not drive with the given velocity - we cannot match the specified arrival speed
953 return false;
954 }
955 }
956 } else {
957 // lane does not continue
958 if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, seen),
959 patchSpeed, "junction '" + currentLane->getEdge().getToJunction()->getID() + "' too close", InsertionCheck::JUNCTION)) {
960 // we may not drive with the given velocity - we cannot stop at the junction
961 return false;
962 }
963 }
964 break;
965 }
966 if (isRail && firstRailSignal == nullptr) {
967 std::string constraintInfo;
968 bool isInsertionOrder;
969 if (MSRailSignal::hasInsertionConstraint(*link, aVehicle, constraintInfo, isInsertionOrder)) {
970 setParameter((isInsertionOrder ? "insertionOrder" : "insertionConstraint:")
971 + aVehicle->getID(), constraintInfo);
972#ifdef DEBUG_INSERTION
973 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
974 std::cout << " insertion constraint at link " << (*link)->getDescription() << " not cleared \n";
975 }
976#endif
977 return false;
978 }
979 }
980
981 // might also by a regular traffic_light instead of a rail_signal
982 if (firstRailSignal == nullptr && (*link)->getTLLogic() != nullptr) {
983 firstRailSignal = *link;
984 firstRailSignalDist = seen;
985 }
986 if (!(*link)->opened(arrivalTime, speed, speed, aVehicle->getVehicleType().getLength(), aVehicle->getImpatience(),
987 cfModel.getMaxDecel(), 0, posLat, nullptr, false, aVehicle)
988 || !(*link)->havePriority()) {
989 // have to stop at junction
990 std::string errorMsg = "";
991 const LinkState state = (*link)->getState();
992 if (state == LINKSTATE_MINOR
993 || state == LINKSTATE_EQUAL
994 || state == LINKSTATE_STOP
995 || state == LINKSTATE_ALLWAY_STOP) {
996 // no sense in trying later
997 errorMsg = "unpriorised junction too close";
998 } else if ((*link)->getTLLogic() != nullptr && !(*link)->getTLLogic()->getsMajorGreen((*link)->getTLIndex())) {
999 // traffic light never turns 'G'?
1000 errorMsg = "tlLogic '" + (*link)->getTLLogic()->getID() + "' link " + toString((*link)->getTLIndex()) + " never switches to 'G'";
1001 }
1002 const double laneStopOffset = MAX2(getVehicleStopOffset(aVehicle),
1003 aVehicle->getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_STOPLINE_CROSSING_GAP, MSPModel::SAFETY_GAP) - (*link)->getDistToFoePedCrossing());
1004 const double remaining = seen - laneStopOffset;
1005 auto dsp = aVehicle->getParameter().departSpeedProcedure;
1006 const bool patchSpeedSpecial = patchSpeed || dsp == DepartSpeedDefinition::DESIRED || dsp == DepartSpeedDefinition::LIMIT;
1007 // patchSpeed depends on the presence of vehicles for these procedures. We never want to abort them here
1009 errorMsg = "";
1010 }
1011 if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, remaining),
1012 patchSpeedSpecial, errorMsg, InsertionCheck::JUNCTION)) {
1013 // we may not drive with the given velocity - we cannot stop at the junction in time
1014#ifdef DEBUG_INSERTION
1015 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1016 std::cout << SIMTIME << " isInsertionSuccess lane=" << getID()
1017 << " veh=" << aVehicle->getID()
1018 << " patchSpeed=" << patchSpeed
1019 << " speed=" << speed
1020 << " remaining=" << remaining
1021 << " leader=" << currentLane->getLastVehicleInformation(aVehicle, 0, 0).toString()
1022 << " last=" << Named::getIDSecure(getLastAnyVehicle())
1023 << " meanSpeed=" << getMeanSpeed()
1024 << " failed (@926)!\n";
1025 }
1026#endif
1027 return false;
1028 }
1029#ifdef DEBUG_INSERTION
1030 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1031 std::cout << "trying insertion before minor link: "
1032 << "insertion speed = " << speed << " dist=" << dist
1033 << "\n";
1034 }
1035#endif
1036 break;
1037 } else if (nextLane->isInternal()) {
1038 double tmp = 0;
1039 bool dummyReq = true;
1040#ifdef DEBUG_INSERTION
1041 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1042 std::cout << "checking linkLeader for lane '" << nextLane->getID() << "'\n";
1043 gDebugFlag1 = true;
1044 }
1045#endif
1046 aVehicle->checkLinkLeader(*link, nextLane, seen, nullptr, speed, tmp, tmp, dummyReq);
1047#ifdef DEBUG_INSERTION
1048 gDebugFlag1 = false;
1049#endif
1050 }
1051 // get the next used lane (including internal)
1052 nextLane = (*link)->getViaLaneOrLane();
1053 // check how next lane affects the journey
1054 if (nextLane != nullptr) {
1055
1056 // do not insert if the bidirectional edge is occupied before a railSignal has been encountered
1057 if (firstRailSignal == nullptr && nextLane->getBidiLane() != nullptr && nextLane->getBidiLane()->getVehicleNumberWithPartials() > 0) {
1058 if ((insertionChecks & (int)InsertionCheck::ONCOMING_TRAIN) != 0) {
1059#ifdef DEBUG_INSERTION
1060 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1061 std::cout << " nextLane=" << nextLane->getID() << " occupiedBidi\n";
1062 }
1063#endif
1064 return false;
1065 }
1066 }
1067
1068 // check if there are stops on the next lane that should be regarded
1069 // (this block is duplicated before the loop to deal with the insertion lane)
1070 if (aVehicle->hasStops()) {
1071 const MSStop& nextStop = aVehicle->getNextStop();
1072 if (nextStop.lane == nextLane) {
1073 std::stringstream msg;
1074 msg << "scheduled stop on lane '" << nextStop.lane->getID() << "' too close";
1075 const double distToStop = seen + nextStop.pars.endPos;
1076 if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, distToStop),
1077 patchSpeed, msg.str(), InsertionCheck::STOP)) {
1078 // we may not drive with the given velocity - we cannot stop at the stop
1079 return false;
1080 }
1081 }
1082 }
1083
1084 // check leader on next lane
1085 MSLeaderInfo leaders = nextLane->getLastVehicleInformation(aVehicle, 0, 0);
1086 if (leaders.hasVehicles()) {
1087 const double nspeed = nextLane->safeInsertionSpeed(aVehicle, seen, leaders, speed);
1088#ifdef DEBUG_INSERTION
1089 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1090 std::cout << SIMTIME << " leader on lane '" << nextLane->getID() << "': " << leaders.toString() << " nspeed=" << nspeed << "\n";
1091 }
1092#endif
1093 if (nspeed == INVALID_SPEED || checkFailure(aVehicle, speed, dist, nspeed, patchSpeed, "", InsertionCheck::LEADER_GAP)) {
1094 // we may not drive with the given velocity - we crash into the leader
1095#ifdef DEBUG_INSERTION
1096 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1097 std::cout << " isInsertionSuccess lane=" << getID()
1098 << " veh=" << aVehicle->getID()
1099 << " pos=" << pos
1100 << " posLat=" << posLat
1101 << " patchSpeed=" << patchSpeed
1102 << " speed=" << speed
1103 << " nspeed=" << nspeed
1104 << " nextLane=" << nextLane->getID()
1105 << " lead=" << leaders.toString()
1106 << " failed (@641)!\n";
1107 }
1108#endif
1109 return false;
1110 }
1111 }
1112 if (!nextLane->checkForPedestrians(aVehicle, speed, dist, -seen, patchSpeed)) {
1113 return false;
1114 }
1115 // check next lane's maximum velocity
1116 const double nspeed = cfModel.freeSpeed(aVehicle, speed, seen, nextLane->getVehicleMaxSpeed(aVehicle), true, MSCFModel::CalcReason::FUTURE);
1117 if (nspeed < speed) {
1118 if (patchSpeed || aVehicle->getParameter().departSpeedProcedure != DepartSpeedDefinition::GIVEN) {
1119 speed = nspeed;
1120 dist = cfModel.brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
1121 } else {
1122 if ((insertionChecks & (int)InsertionCheck::SPEED_LIMIT) != 0) {
1124 WRITE_WARNINGF(TL("Vehicle '%' is inserted too fast and will violate the speed limit on a lane '%'."),
1125 aVehicle->getID(), nextLane->getID());
1126 } else {
1127 // we may not drive with the given velocity - we would be too fast on the next lane
1128 WRITE_ERRORF(TL("Vehicle '%' will not be able to depart using the given velocity (slow lane ahead)!"), aVehicle->getID());
1130 return false;
1131 }
1132 }
1133 }
1134 }
1135 // check traffic on next junction
1136 // we cannot use (*link)->opened because a vehicle without priority
1137 // may already be comitted to blocking the link and unable to stop
1138 const SUMOTime leaveTime = (*link)->getLeaveTime(arrivalTime, speed, speed, aVehicle->getVehicleType().getLength());
1139 if ((*link)->hasApproachingFoe(arrivalTime, leaveTime, speed, cfModel.getMaxDecel())) {
1140 if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, seen), patchSpeed, "", InsertionCheck::JUNCTION)) {
1141 // we may not drive with the given velocity - we crash at the junction
1142 return false;
1143 }
1144 }
1145 arrivalTime += TIME2STEPS(nextLane->getLength() / MAX2(speed, NUMERICAL_EPS));
1146 seen += nextLane->getLength();
1147 currentLane = nextLane;
1148 if ((*link)->getViaLane() == nullptr) {
1149 nRouteSuccs++;
1150 ++ce;
1151 ++ri;
1152 }
1153 }
1154 }
1155
1156 // get the pointer to the vehicle next in front of the given position
1157 MSLeaderInfo leaders = getLastVehicleInformation(aVehicle, 0, pos);
1158 //if (aVehicle->getID() == "disabled") std::cout << " leaders=" << leaders.toString() << "\n";
1159 const double nspeed = safeInsertionSpeed(aVehicle, -pos, leaders, speed);
1160 if (nspeed == INVALID_SPEED || checkFailure(aVehicle, speed, dist, nspeed, patchSpeed, "", InsertionCheck::LEADER_GAP)) {
1161 // we may not drive with the given velocity - we crash into the leader
1162#ifdef DEBUG_INSERTION
1163 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1164 std::cout << SIMTIME << " isInsertionSuccess lane=" << getID()
1165 << " veh=" << aVehicle->getID()
1166 << " pos=" << pos
1167 << " posLat=" << posLat
1168 << " patchSpeed=" << patchSpeed
1169 << " speed=" << speed
1170 << " nspeed=" << nspeed
1171 << " nextLane=" << nextLane->getID()
1172 << " leaders=" << leaders.toString()
1173 << " failed (@700)!\n";
1174 }
1175#endif
1176 return false;
1177 }
1178#ifdef DEBUG_INSERTION
1179 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1180 std::cout << SIMTIME << " speed = " << speed << " nspeed = " << nspeed << std::endl;
1181 }
1182#endif
1183
1184 const MSLeaderDistanceInfo& followers = getFollowersOnConsecutive(aVehicle, aVehicle->getBackPositionOnLane(), false);
1185 for (int i = 0; i < followers.numSublanes(); ++i) {
1186 const MSVehicle* follower = followers[i].first;
1187 if (follower != nullptr) {
1188 const double backGapNeeded = follower->getCarFollowModel().getSecureGap(follower, aVehicle, follower->getSpeed(), speed, cfModel.getMaxDecel());
1189 if (followers[i].second < backGapNeeded
1190 && ((insertionChecks & (int)InsertionCheck::FOLLOWER_GAP) != 0
1191 || (followers[i].second < 0 && (insertionChecks & (int)InsertionCheck::COLLISION) != 0))) {
1192 // too close to the follower on this lane
1193#ifdef DEBUG_INSERTION
1194 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1195 std::cout << SIMTIME << " isInsertionSuccess lane=" << getID()
1196 << " veh=" << aVehicle->getID()
1197 << " pos=" << pos
1198 << " posLat=" << posLat
1199 << " speed=" << speed
1200 << " nspeed=" << nspeed
1201 << " follower=" << follower->getID()
1202 << " backGapNeeded=" << backGapNeeded
1203 << " gap=" << followers[i].second
1204 << " failure (@719)!\n";
1205 }
1206#endif
1207 return false;
1208 }
1209 }
1210 }
1211
1212 if (!checkForPedestrians(aVehicle, speed, dist, pos, patchSpeed)) {
1213 return false;
1214 }
1215
1216 MSLane* shadowLane = aVehicle->getLaneChangeModel().getShadowLane(this);
1217#ifdef DEBUG_INSERTION
1218 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1219 std::cout << " shadowLane=" << Named::getIDSecure(shadowLane) << "\n";
1220 }
1221#endif
1222 if (shadowLane != nullptr) {
1223 const MSLeaderDistanceInfo& shadowFollowers = shadowLane->getFollowersOnConsecutive(aVehicle, aVehicle->getBackPositionOnLane(), false);
1224 for (int i = 0; i < shadowFollowers.numSublanes(); ++i) {
1225 const MSVehicle* follower = shadowFollowers[i].first;
1226 if (follower != nullptr) {
1227 const double backGapNeeded = follower->getCarFollowModel().getSecureGap(follower, aVehicle, follower->getSpeed(), speed, cfModel.getMaxDecel());
1228 if (shadowFollowers[i].second < backGapNeeded
1229 && ((insertionChecks & (int)InsertionCheck::FOLLOWER_GAP) != 0
1230 || (shadowFollowers[i].second < 0 && (insertionChecks & (int)InsertionCheck::COLLISION) != 0))) {
1231 // too close to the follower on this lane
1232#ifdef DEBUG_INSERTION
1233 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1234 std::cout << SIMTIME
1235 << " isInsertionSuccess shadowlane=" << shadowLane->getID()
1236 << " veh=" << aVehicle->getID()
1237 << " pos=" << pos
1238 << " posLat=" << posLat
1239 << " speed=" << speed
1240 << " nspeed=" << nspeed
1241 << " follower=" << follower->getID()
1242 << " backGapNeeded=" << backGapNeeded
1243 << " gap=" << shadowFollowers[i].second
1244 << " failure (@812)!\n";
1245 }
1246#endif
1247 return false;
1248 }
1249 }
1250 }
1251 const MSLeaderInfo& ahead = shadowLane->getLastVehicleInformation(nullptr, 0, aVehicle->getPositionOnLane(), false);
1252 for (int i = 0; i < ahead.numSublanes(); ++i) {
1253 const MSVehicle* veh = ahead[i];
1254 if (veh != nullptr) {
1255 const double gap = veh->getBackPositionOnLane(shadowLane) - aVehicle->getPositionOnLane() - aVehicle->getVehicleType().getMinGap();
1256 const double gapNeeded = aVehicle->getCarFollowModel().getSecureGap(aVehicle, veh, speed, veh->getSpeed(), veh->getCarFollowModel().getMaxDecel());
1257 if (gap < gapNeeded
1258 && ((insertionChecks & (int)InsertionCheck::LEADER_GAP) != 0
1259 || (gap < 0 && (insertionChecks & (int)InsertionCheck::COLLISION) != 0))) {
1260 // too close to the shadow leader
1261#ifdef DEBUG_INSERTION
1262 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1263 std::cout << SIMTIME
1264 << " isInsertionSuccess shadowlane=" << shadowLane->getID()
1265 << " veh=" << aVehicle->getID()
1266 << " pos=" << pos
1267 << " posLat=" << posLat
1268 << " speed=" << speed
1269 << " nspeed=" << nspeed
1270 << " leader=" << veh->getID()
1271 << " gapNeeded=" << gapNeeded
1272 << " gap=" << gap
1273 << " failure (@842)!\n";
1274 }
1275#endif
1276 return false;
1277 }
1278 }
1279 }
1280 }
1281 if (followers.numFreeSublanes() > 0) {
1282 // check approaching vehicles to prevent rear-end collisions
1283 const double backOffset = pos - aVehicle->getVehicleType().getLength();
1284 const double missingRearGap = getMissingRearGap(aVehicle, backOffset, speed);
1285 if (missingRearGap > 0
1286 && (insertionChecks & (int)InsertionCheck::LEADER_GAP) != 0) {
1287 // too close to a follower
1288#ifdef DEBUG_INSERTION
1289 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1290 std::cout << SIMTIME
1291 << " isInsertionSuccess lane=" << getID()
1292 << " veh=" << aVehicle->getID()
1293 << " pos=" << pos
1294 << " posLat=" << posLat
1295 << " speed=" << speed
1296 << " nspeed=" << nspeed
1297 << " missingRearGap=" << missingRearGap
1298 << " failure (@728)!\n";
1299 }
1300#endif
1301 return false;
1302 }
1303 }
1304 if (insertionChecks == (int)InsertionCheck::NONE) {
1305 speed = MAX2(0.0, speed);
1306 }
1307 // may got negative while adaptation
1308 if (speed < 0) {
1309#ifdef DEBUG_INSERTION
1310 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1311 std::cout << SIMTIME
1312 << " isInsertionSuccess lane=" << getID()
1313 << " veh=" << aVehicle->getID()
1314 << " pos=" << pos
1315 << " posLat=" << posLat
1316 << " speed=" << speed
1317 << " nspeed=" << nspeed
1318 << " failed (@733)!\n";
1319 }
1320#endif
1321 return false;
1322 }
1323 const int bestLaneOffset = aVehicle->getBestLaneOffset();
1324 const double extraReservation = aVehicle->getLaneChangeModel().getExtraReservation(bestLaneOffset);
1325 if (extraReservation > 0) {
1326 std::stringstream msg;
1327 msg << "too many lane changes required on lane '" << myID << "'";
1328 // we need to take into acount one extra actionStep of delay due to #3665
1329 double distToStop = aVehicle->getBestLaneDist() - pos - extraReservation - speed * aVehicle->getActionStepLengthSecs();
1330 if (distToStop >= 0) {
1331 double stopSpeed = cfModel.stopSpeed(aVehicle, speed, distToStop, MSCFModel::CalcReason::FUTURE);
1332#ifdef DEBUG_INSERTION
1333 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1334 std::cout << "\nIS_INSERTION_SUCCESS\n"
1335 << SIMTIME << " veh=" << aVehicle->getID() << " bestLaneOffset=" << bestLaneOffset << " bestLaneDist=" << aVehicle->getBestLaneDist() << " extraReservation=" << extraReservation
1336 << " distToStop=" << distToStop << " v=" << speed << " v2=" << stopSpeed << "\n";
1337 }
1338#endif
1339 if (checkFailure(aVehicle, speed, distToStop, MAX2(0.0, stopSpeed),
1340 patchSpeed, msg.str(), InsertionCheck::LANECHANGE)) {
1341 // we may not drive with the given velocity - we cannot reserve enough space for lane changing
1342 return false;
1343 }
1344 }
1345 }
1346 // enter
1347 incorporateVehicle(aVehicle, pos, speed, posLat, find_if(myVehicles.begin(), myVehicles.end(), [&](MSVehicle * const v) {
1348 return v->getPositionOnLane() >= pos;
1349 }), notification);
1350#ifdef DEBUG_INSERTION
1351 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1352 std::cout << SIMTIME
1353 << " isInsertionSuccess lane=" << getID()
1354 << " veh=" << aVehicle->getID()
1355 << " pos=" << pos
1356 << " posLat=" << posLat
1357 << " speed=" << speed
1358 << " nspeed=" << nspeed
1359 << "\n myVehicles=" << toString(myVehicles)
1360 << " myPartial=" << toString(myPartialVehicles)
1361 << " myManeuverReservations=" << toString(myManeuverReservations)
1362 << "\n leaders=" << leaders.toString()
1363 << "\n success!\n";
1364 }
1365#endif
1366 if (isRail) {
1367 unsetParameter("insertionConstraint:" + aVehicle->getID());
1368 unsetParameter("insertionOrder:" + aVehicle->getID());
1369 unsetParameter("insertionBlocked:" + aVehicle->getID());
1370 // rail_signal (not traffic_light) requires approach information for
1371 // switching correctly at the start of the next simulation step
1372 if (firstRailSignal != nullptr && firstRailSignal->getJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
1373 aVehicle->registerInsertionApproach(firstRailSignal, firstRailSignalDist);
1374 }
1375 }
1376 return true;
1377}
1378
1379
1380void
1381MSLane::forceVehicleInsertion(MSVehicle* veh, double pos, MSMoveReminder::Notification notification, double posLat) {
1382 veh->updateBestLanes(true, this);
1383 bool dummy;
1384 const double speed = veh->hasDeparted() ? veh->getSpeed() : getDepartSpeed(*veh, dummy);
1385 incorporateVehicle(veh, pos, speed, posLat, find_if(myVehicles.begin(), myVehicles.end(), [&](MSVehicle * const v) {
1386 return v->getPositionOnLane() >= pos;
1387 }), notification);
1388}
1389
1390
1391double
1392MSLane::safeInsertionSpeed(const MSVehicle* veh, double seen, const MSLeaderInfo& leaders, double speed) {
1393 double nspeed = speed;
1394#ifdef DEBUG_INSERTION
1395 if (DEBUG_COND2(veh)) {
1396 std::cout << SIMTIME << " safeInsertionSpeed veh=" << veh->getID() << " speed=" << speed << "\n";
1397 }
1398#endif
1399 for (int i = 0; i < leaders.numSublanes(); ++i) {
1400 const MSVehicle* leader = leaders[i];
1401 if (leader != nullptr) {
1402 double gap = leader->getBackPositionOnLane(this) + seen - veh->getVehicleType().getMinGap();
1403 if (leader->getLane() == getBidiLane()) {
1404 // use distance to front position and account for movement
1405 gap -= (leader->getLength() + leader->getBrakeGap(true));
1406 }
1407 if (gap < 0) {
1408#ifdef DEBUG_INSERTION
1409 if (DEBUG_COND2(veh)) {
1410 std::cout << " leader=" << leader->getID() << " bPos=" << leader->getBackPositionOnLane(this) << " gap=" << gap << "\n";
1411 }
1412#endif
1413 if ((veh->getInsertionChecks() & (int)InsertionCheck::COLLISION) != 0) {
1414 return INVALID_SPEED;
1415 } else {
1416 return 0;
1417 }
1418 }
1419 nspeed = MIN2(nspeed,
1420 veh->getCarFollowModel().insertionFollowSpeed(veh, speed, gap, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel(), leader));
1421#ifdef DEBUG_INSERTION
1422 if (DEBUG_COND2(veh)) {
1423 std::cout << " leader=" << leader->getID() << " bPos=" << leader->getBackPositionOnLane(this) << " gap=" << gap << " nspeed=" << nspeed << "\n";
1424 }
1425#endif
1426 }
1427 }
1428 return nspeed;
1429}
1430
1431
1432// ------ Handling vehicles lapping into lanes ------
1433const MSLeaderInfo
1434MSLane::getLastVehicleInformation(const MSVehicle* ego, double latOffset, double minPos, bool allowCached) const {
1435 if (myLeaderInfoTime < MSNet::getInstance()->getCurrentTimeStep() || ego != nullptr || minPos > 0 || !allowCached) {
1436 MSLeaderInfo leaderTmp(myWidth, ego, latOffset);
1438 int freeSublanes = 1; // number of sublanes for which no leader was found
1439 //if (ego->getID() == "disabled" && SIMTIME == 58) {
1440 // std::cout << "DEBUG\n";
1441 //}
1442 const MSVehicle* veh = *last;
1443 while (freeSublanes > 0 && veh != nullptr) {
1444#ifdef DEBUG_PLAN_MOVE
1445 if (DEBUG_COND2(ego) || DEBUG_COND) {
1446 gDebugFlag1 = true;
1447 std::cout << " getLastVehicleInformation lane=" << getID() << " minPos=" << minPos << " veh=" << veh->getID() << " pos=" << veh->getPositionOnLane(this) << "\n";
1448 }
1449#endif
1450 if (veh != ego && MAX2(0.0, veh->getPositionOnLane(this)) >= minPos) {
1451 const double vehLatOffset = veh->getLatOffset(this);
1452 freeSublanes = leaderTmp.addLeader(veh, true, vehLatOffset);
1453#ifdef DEBUG_PLAN_MOVE
1454 if (DEBUG_COND2(ego) || DEBUG_COND) {
1455 std::cout << " latOffset=" << vehLatOffset << " newLeaders=" << leaderTmp.toString() << "\n";
1456 }
1457#endif
1458 }
1459 veh = *(++last);
1460 }
1461 if (ego == nullptr && minPos == 0) {
1462#ifdef HAVE_FOX
1463 ScopedLocker<> lock(myLeaderInfoMutex, MSGlobals::gNumSimThreads > 1);
1464#endif
1465 // update cached value
1466 myLeaderInfo = leaderTmp;
1468 }
1469#ifdef DEBUG_PLAN_MOVE
1470 //if (DEBUG_COND2(ego)) std::cout << SIMTIME
1471 // << " getLastVehicleInformation lane=" << getID()
1472 // << " ego=" << Named::getIDSecure(ego)
1473 // << "\n"
1474 // << " vehicles=" << toString(myVehicles)
1475 // << " partials=" << toString(myPartialVehicles)
1476 // << "\n"
1477 // << " result=" << leaderTmp.toString()
1478 // << " cached=" << myLeaderInfo.toString()
1479 // << " myLeaderInfoTime=" << myLeaderInfoTime
1480 // << "\n";
1481 gDebugFlag1 = false;
1482#endif
1483 return leaderTmp;
1484 }
1485 return myLeaderInfo;
1486}
1487
1488
1489const MSLeaderInfo
1490MSLane::getFirstVehicleInformation(const MSVehicle* ego, double latOffset, bool onlyFrontOnLane, double maxPos, bool allowCached) const {
1491#ifdef HAVE_FOX
1492 ScopedLocker<> lock(myFollowerInfoMutex, MSGlobals::gNumSimThreads > 1);
1493#endif
1494 if (myFollowerInfoTime < MSNet::getInstance()->getCurrentTimeStep() || ego != nullptr || maxPos < myLength || !allowCached || onlyFrontOnLane) {
1495 // XXX separate cache for onlyFrontOnLane = true
1496 MSLeaderInfo followerTmp(myWidth, ego, latOffset);
1498 int freeSublanes = 1; // number of sublanes for which no leader was found
1499 const MSVehicle* veh = *first;
1500 while (freeSublanes > 0 && veh != nullptr) {
1501#ifdef DEBUG_PLAN_MOVE
1502 if (DEBUG_COND2(ego)) {
1503 std::cout << " veh=" << veh->getID() << " pos=" << veh->getPositionOnLane(this) << " maxPos=" << maxPos << "\n";
1504 }
1505#endif
1506 if (veh != ego && veh->getPositionOnLane(this) <= maxPos
1507 && (!onlyFrontOnLane || veh->isFrontOnLane(this))) {
1508 //const double vehLatOffset = veh->getLane()->getRightSideOnEdge() - getRightSideOnEdge();
1509 const double vehLatOffset = veh->getLatOffset(this);
1510#ifdef DEBUG_PLAN_MOVE
1511 if (DEBUG_COND2(ego)) {
1512 std::cout << " veh=" << veh->getID() << " latOffset=" << vehLatOffset << "\n";
1513 }
1514#endif
1515 freeSublanes = followerTmp.addLeader(veh, true, vehLatOffset);
1516 }
1517 veh = *(++first);
1518 }
1519 if (ego == nullptr && maxPos == std::numeric_limits<double>::max()) {
1520 // update cached value
1521 myFollowerInfo = followerTmp;
1523 }
1524#ifdef DEBUG_PLAN_MOVE
1525 //if (DEBUG_COND2(ego)) std::cout << SIMTIME
1526 // << " getFirstVehicleInformation lane=" << getID()
1527 // << " ego=" << Named::getIDSecure(ego)
1528 // << "\n"
1529 // << " vehicles=" << toString(myVehicles)
1530 // << " partials=" << toString(myPartialVehicles)
1531 // << "\n"
1532 // << " result=" << followerTmp.toString()
1533 // //<< " cached=" << myFollowerInfo.toString()
1534 // << " myLeaderInfoTime=" << myLeaderInfoTime
1535 // << "\n";
1536#endif
1537 return followerTmp;
1538 }
1539 return myFollowerInfo;
1540}
1541
1542
1543// ------ ------
1544void
1546 assert(myVehicles.size() != 0);
1547 double cumulatedVehLength = 0.;
1548 MSLeaderInfo leaders(myWidth);
1549
1550 // iterate over myVehicles, myPartialVehicles, and myManeuverReservations merge-sort style
1551 VehCont::reverse_iterator veh = myVehicles.rbegin();
1552 VehCont::reverse_iterator vehPart = myPartialVehicles.rbegin();
1553 VehCont::reverse_iterator vehRes = myManeuverReservations.rbegin();
1554#ifdef DEBUG_PLAN_MOVE
1555 if (DEBUG_COND) std::cout
1556 << "\n"
1557 << SIMTIME
1558 << " planMovements() lane=" << getID()
1559 << "\n vehicles=" << toString(myVehicles)
1560 << "\n partials=" << toString(myPartialVehicles)
1561 << "\n reservations=" << toString(myManeuverReservations)
1562 << "\n";
1563#endif
1565 for (; veh != myVehicles.rend(); ++veh) {
1566#ifdef DEBUG_PLAN_MOVE
1567 if (DEBUG_COND2((*veh))) {
1568 std::cout << " plan move for: " << (*veh)->getID();
1569 }
1570#endif
1571 updateLeaderInfo(*veh, vehPart, vehRes, leaders); // 36ns with 8 threads, 9ns with 1
1572#ifdef DEBUG_PLAN_MOVE
1573 if (DEBUG_COND2((*veh))) {
1574 std::cout << " leaders=" << leaders.toString() << "\n";
1575 }
1576#endif
1577 (*veh)->planMove(t, leaders, cumulatedVehLength); // 4800ns with 8 threads, 3100 with 1
1578 cumulatedVehLength += (*veh)->getVehicleType().getLengthWithGap();
1579 leaders.addLeader(*veh, false, 0);
1580 }
1581}
1582
1583
1584void
1586 for (MSVehicle* const veh : myVehicles) {
1587 veh->setApproachingForAllLinks();
1588 }
1589}
1590
1591
1592void
1593MSLane::updateLeaderInfo(const MSVehicle* veh, VehCont::reverse_iterator& vehPart, VehCont::reverse_iterator& vehRes, MSLeaderInfo& ahead) const {
1594 bool morePartialVehsAhead = vehPart != myPartialVehicles.rend();
1595 bool moreReservationsAhead = vehRes != myManeuverReservations.rend();
1596 bool nextToConsiderIsPartial;
1597
1598 // Determine relevant leaders for veh
1599 while (moreReservationsAhead || morePartialVehsAhead) {
1600 if ((!moreReservationsAhead || (*vehRes)->getPositionOnLane(this) <= veh->getPositionOnLane())
1601 && (!morePartialVehsAhead || (*vehPart)->getPositionOnLane(this) <= veh->getPositionOnLane())) {
1602 // All relevant downstream vehicles have been collected.
1603 break;
1604 }
1605
1606 // Check whether next farthest relevant vehicle downstream is a partial vehicle or a maneuver reservation
1607 if (moreReservationsAhead && !morePartialVehsAhead) {
1608 nextToConsiderIsPartial = false;
1609 } else if (morePartialVehsAhead && !moreReservationsAhead) {
1610 nextToConsiderIsPartial = true;
1611 } else {
1612 assert(morePartialVehsAhead && moreReservationsAhead);
1613 // Add farthest downstream vehicle first
1614 nextToConsiderIsPartial = (*vehPart)->getPositionOnLane(this) > (*vehRes)->getPositionOnLane(this);
1615 }
1616 // Add appropriate leader information
1617 if (nextToConsiderIsPartial) {
1618 const double latOffset = (*vehPart)->getLatOffset(this);
1619#ifdef DEBUG_PLAN_MOVE
1620 if (DEBUG_COND) {
1621 std::cout << " partial ahead: " << (*vehPart)->getID() << " latOffset=" << latOffset << "\n";
1622 }
1623#endif
1624 if (!(MSGlobals::gLaneChangeDuration > 0 && (*vehPart)->getLaneChangeModel().isOpposite()
1625 && !(*vehPart)->getLaneChangeModel().isChangingLanes())) {
1626 ahead.addLeader(*vehPart, false, latOffset);
1627 }
1628 ++vehPart;
1629 morePartialVehsAhead = vehPart != myPartialVehicles.rend();
1630 } else {
1631 const double latOffset = (*vehRes)->getLatOffset(this);
1632#ifdef DEBUG_PLAN_MOVE
1633 if (DEBUG_COND) {
1634 std::cout << " reservation ahead: " << (*vehRes)->getID() << " latOffset=" << latOffset << "\n";
1635 }
1636#endif
1637 ahead.addLeader(*vehRes, false, latOffset);
1638 ++vehRes;
1639 moreReservationsAhead = vehRes != myManeuverReservations.rend();
1640 }
1641 }
1642}
1643
1644
1645void
1646MSLane::detectCollisions(SUMOTime timestep, const std::string& stage) {
1647 myNeedsCollisionCheck = false;
1648#ifdef DEBUG_COLLISIONS
1649 if (DEBUG_COND) {
1650 std::vector<const MSVehicle*> all;
1651 for (AnyVehicleIterator last = anyVehiclesBegin(); last != anyVehiclesEnd(); ++last) {
1652 all.push_back(*last);
1653 }
1654 std::cout << SIMTIME << " detectCollisions stage=" << stage << " lane=" << getID() << ":\n"
1655 << " vehs=" << toString(myVehicles) << "\n"
1656 << " part=" << toString(myPartialVehicles) << "\n"
1657 << " all=" << toString(all) << "\n"
1658 << "\n";
1659 }
1660#endif
1661
1663 return;
1664 }
1665
1666 std::set<const MSVehicle*, ComparatorNumericalIdLess> toRemove;
1667 std::set<const MSVehicle*, ComparatorNumericalIdLess> toTeleport;
1669 myNeedsCollisionCheck = true; // always check
1670#ifdef DEBUG_JUNCTION_COLLISIONS
1671 if (DEBUG_COND) {
1672 std::cout << SIMTIME << " detect junction Collisions stage=" << stage << " lane=" << getID() << ":\n"
1673 << " vehs=" << toString(myVehicles) << "\n"
1674 << " part=" << toString(myPartialVehicles) << "\n"
1675 << "\n";
1676 }
1677#endif
1678 assert(myLinks.size() == 1);
1679 const std::vector<const MSLane*>& foeLanes = myLinks.front()->getFoeLanes();
1680 // save the iterator, it might get modified, see #8842
1682 for (AnyVehicleIterator veh = anyVehiclesBegin(); veh != end; ++veh) {
1683 const MSVehicle* const collider = *veh;
1684 //std::cout << " collider " << collider->getID() << "\n";
1685 PositionVector colliderBoundary = collider->getBoundingBox(myCheckJunctionCollisionMinGap);
1686 for (const MSLane* const foeLane : foeLanes) {
1687#ifdef DEBUG_JUNCTION_COLLISIONS
1688 if (DEBUG_COND) {
1689 std::cout << " foeLane " << foeLane->getID()
1690 << " foeVehs=" << toString(foeLane->myVehicles)
1691 << " foePart=" << toString(foeLane->myPartialVehicles) << "\n";
1692 }
1693#endif
1694 MSLane::AnyVehicleIterator foeEnd = foeLane->anyVehiclesEnd();
1695 for (MSLane::AnyVehicleIterator it_veh = foeLane->anyVehiclesBegin(); it_veh != foeEnd; ++it_veh) {
1696 const MSVehicle* const victim = *it_veh;
1697 if (victim == collider) {
1698 // may happen if the vehicles lane and shadow lane are siblings
1699 continue;
1700 }
1701#ifdef DEBUG_JUNCTION_COLLISIONS
1702 if (DEBUG_COND && DEBUG_COND2(collider)) {
1703 std::cout << SIMTIME << " foe=" << victim->getID()
1704 << " bound=" << colliderBoundary << " foeBound=" << victim->getBoundingBox()
1705 << " overlaps=" << colliderBoundary.overlapsWith(victim->getBoundingBox())
1706 << " poly=" << collider->getBoundingPoly()
1707 << " foePoly=" << victim->getBoundingPoly()
1708 << " overlaps2=" << collider->getBoundingPoly().overlapsWith(victim->getBoundingPoly())
1709 << "\n";
1710 }
1711#endif
1712 if (MSGlobals::gIgnoreJunctionBlocker < std::numeric_limits<SUMOTime>::max()) {
1715 // ignored vehicles should not tigger collision
1716 continue;
1717 }
1718 }
1719
1720 if (colliderBoundary.overlapsWith(victim->getBoundingBox())) {
1721 // make a detailed check
1722 PositionVector boundingPoly = collider->getBoundingPoly();
1724 // junction leader is the victim (collider must still be on junction)
1725 assert(isInternal());
1726 if (victim->getLane()->isInternal() && victim->isLeader(myLinks.front(), collider, -1)) {
1727 foeLane->handleCollisionBetween(timestep, stage, victim, collider, -1, 0, toRemove, toTeleport);
1728 } else {
1729 handleCollisionBetween(timestep, stage, collider, victim, -1, 0, toRemove, toTeleport);
1730 }
1731 }
1732 }
1733 }
1734 detectPedestrianJunctionCollision(collider, colliderBoundary, foeLane, timestep, stage, toRemove, toTeleport);
1735 }
1736 if (myLinks.front()->getWalkingAreaFoe() != nullptr) {
1737 detectPedestrianJunctionCollision(collider, colliderBoundary, myLinks.front()->getWalkingAreaFoe(), timestep, stage, toRemove, toTeleport);
1738 }
1739 if (myLinks.front()->getWalkingAreaFoeExit() != nullptr) {
1740 detectPedestrianJunctionCollision(collider, colliderBoundary, myLinks.front()->getWalkingAreaFoeExit(), timestep, stage, toRemove, toTeleport);
1741 }
1742 }
1743 }
1744
1745
1747#ifdef DEBUG_PEDESTRIAN_COLLISIONS
1748 if (DEBUG_COND) {
1749 std::cout << SIMTIME << " detect pedestrian collisions stage=" << stage << " lane=" << getID() << "\n";
1750 }
1751#endif
1753 for (AnyVehicleIterator it_v = anyVehiclesBegin(); it_v != v_end; ++it_v) {
1754 const MSVehicle* v = *it_v;
1755 double back = v->getBackPositionOnLane(this);
1756 const double length = v->getVehicleType().getLength();
1757 const double right = v->getRightSideOnEdge(this) - getRightSideOnEdge();
1758 if (v->getLane() == getBidiLane()) {
1759 // use the front position for checking
1760 back -= length;
1761 }
1762 PersonDist leader = nextBlocking(back, right, right + v->getVehicleType().getWidth());
1763#ifdef DEBUG_PEDESTRIAN_COLLISIONS
1764 if (DEBUG_COND && DEBUG_COND2(v)) {
1765 std::cout << SIMTIME << " back=" << back << " right=" << right << " person=" << Named::getIDSecure(leader.first)
1766 << " dist=" << leader.second << " jammed=" << (leader.first == nullptr ? false : leader.first->isJammed()) << "\n";
1767 }
1768#endif
1769 if (leader.first != 0 && leader.second < length && !leader.first->isJammed()) {
1771 // aircraft wings and body are above walking level
1772 continue;
1773 }
1774 const double gap = leader.second - length;
1775 handleIntermodalCollisionBetween(timestep, stage, v, leader.first, gap, "sharedLane", toRemove, toTeleport);
1776 }
1777 }
1778 }
1779
1780 if (myVehicles.size() == 0) {
1781 return;
1782 }
1783 if (!MSGlobals::gSublane) {
1784 // no sublanes
1785 VehCont::reverse_iterator lastVeh = myVehicles.rend() - 1;
1786 for (VehCont::reverse_iterator pred = myVehicles.rbegin(); pred != lastVeh; ++pred) {
1787 VehCont::reverse_iterator veh = pred + 1;
1788 detectCollisionBetween(timestep, stage, *veh, *pred, toRemove, toTeleport);
1789 }
1790 if (myPartialVehicles.size() > 0) {
1791 detectCollisionBetween(timestep, stage, *lastVeh, myPartialVehicles.front(), toRemove, toTeleport);
1792 }
1793 if (getBidiLane() != nullptr) {
1794 // bidirectional railway
1795 MSLane* bidiLane = getBidiLane();
1796 if (bidiLane->getVehicleNumberWithPartials() > 0) {
1797 for (auto veh = myVehicles.begin(); veh != myVehicles.end(); ++veh) {
1798 double high = (*veh)->getPositionOnLane(this);
1799 double low = (*veh)->getBackPositionOnLane(this);
1800 if (stage == MSNet::STAGE_MOVEMENTS) {
1801 // use previous back position to catch trains that
1802 // "jump" through each other
1803 low -= SPEED2DIST((*veh)->getSpeed());
1804 }
1805 for (AnyVehicleIterator veh2 = bidiLane->anyVehiclesBegin(); veh2 != bidiLane->anyVehiclesEnd(); ++veh2) {
1806 // self-collisions might legitemately occur when a long train loops back on itself
1807 if (*veh == *veh2 && !(*veh)->isRail()) {
1808 continue;
1809 }
1810 if ((*veh)->getLane() == (*veh2)->getLane() ||
1811 (*veh)->getLane() == (*veh2)->getBackLane() ||
1812 (*veh)->getBackLane() == (*veh2)->getLane()) {
1813 // vehicles are not in a bidi relation
1814 continue;
1815 }
1816 double low2 = myLength - (*veh2)->getPositionOnLane(bidiLane);
1817 double high2 = myLength - (*veh2)->getBackPositionOnLane(bidiLane);
1818 if (stage == MSNet::STAGE_MOVEMENTS) {
1819 // use previous back position to catch trains that
1820 // "jump" through each other
1821 high2 += SPEED2DIST((*veh2)->getSpeed());
1822 }
1823 if (!(high < low2 || high2 < low)) {
1824#ifdef DEBUG_COLLISIONS
1825 if (DEBUG_COND) {
1826 std::cout << SIMTIME << " bidi-collision veh=" << (*veh)->getID() << " bidiVeh=" << (*veh2)->getID()
1827 << " vehFurther=" << toString((*veh)->getFurtherLanes())
1828 << " high=" << high << " low=" << low << " high2=" << high2 << " low2=" << low2 << "\n";
1829 }
1830#endif
1831 // the faster vehicle is at fault
1832 MSVehicle* collider = const_cast<MSVehicle*>(*veh);
1833 MSVehicle* victim = const_cast<MSVehicle*>(*veh2);
1834 if (collider->getSpeed() < victim->getSpeed()) {
1835 std::swap(victim, collider);
1836 }
1837 handleCollisionBetween(timestep, stage, collider, victim, -1, 0, toRemove, toTeleport);
1838 }
1839 }
1840 }
1841 }
1842 }
1843 } else {
1844 // in the sublane-case it is insufficient to check the vehicles ordered
1845 // by their front position as there might be more than 2 vehicles next to each
1846 // other on the same lane
1847 // instead, a moving-window approach is used where all vehicles that
1848 // overlap in the longitudinal direction receive pairwise checks
1849 // XXX for efficiency, all lanes of an edge should be checked together
1850 // (lanechanger-style)
1851
1852 // XXX quick hack: check each in myVehicles against all others
1853 for (AnyVehicleIterator veh = anyVehiclesBegin(); veh != anyVehiclesEnd(); ++veh) {
1854 MSVehicle* follow = (MSVehicle*)*veh;
1855 for (AnyVehicleIterator veh2 = anyVehiclesBegin(); veh2 != anyVehiclesEnd(); ++veh2) {
1856 MSVehicle* lead = (MSVehicle*)*veh2;
1857 if (lead == follow) {
1858 continue;
1859 }
1860 if (lead->getPositionOnLane(this) < follow->getPositionOnLane(this)) {
1861 continue;
1862 }
1863 if (detectCollisionBetween(timestep, stage, follow, lead, toRemove, toTeleport)) {
1864 // XXX what about collisions with multiple leaders at once?
1865 break;
1866 }
1867 }
1868 }
1869 }
1870
1871
1872 for (std::set<const MSVehicle*, ComparatorNumericalIdLess>::iterator it = toRemove.begin(); it != toRemove.end(); ++it) {
1873 MSVehicle* veh = const_cast<MSVehicle*>(*it);
1874 MSLane* vehLane = veh->getMutableLane();
1876 if (toTeleport.count(veh) > 0) {
1877 MSVehicleTransfer::getInstance()->add(timestep, veh);
1878 } else {
1881 }
1882 }
1883}
1884
1885
1886void
1887MSLane::detectPedestrianJunctionCollision(const MSVehicle* collider, const PositionVector& colliderBoundary, const MSLane* foeLane,
1888 SUMOTime timestep, const std::string& stage,
1889 std::set<const MSVehicle*, ComparatorNumericalIdLess>& toRemove,
1890 std::set<const MSVehicle*, ComparatorNumericalIdLess>& toTeleport) {
1891 if (myIntermodalCollisionAction != COLLISION_ACTION_NONE && foeLane->getEdge().getPersons().size() > 0 && foeLane->hasPedestrians()) {
1892#ifdef DEBUG_PEDESTRIAN_COLLISIONS
1893 if (DEBUG_COND) {
1894 std::cout << SIMTIME << " detect pedestrian junction collisions stage=" << stage << " lane=" << getID() << " foeLane=" << foeLane->getID() << "\n";
1895 }
1896#endif
1897 const std::vector<MSTransportable*>& persons = foeLane->getEdge().getSortedPersons(timestep);
1898 for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
1899#ifdef DEBUG_PEDESTRIAN_COLLISIONS
1900 if (DEBUG_COND) {
1901 std::cout << " collider=" << collider->getID()
1902 << " ped=" << (*it_p)->getID()
1903 << " jammed=" << (*it_p)->isJammed()
1904 << " colliderBoundary=" << colliderBoundary
1905 << " pedBoundary=" << (*it_p)->getBoundingBox()
1906 << "\n";
1907 }
1908#endif
1909 if ((*it_p)->isJammed()) {
1910 continue;
1911 }
1912 if (colliderBoundary.overlapsWith((*it_p)->getBoundingBox())
1913 && collider->getBoundingPoly().overlapsWith((*it_p)->getBoundingBox())) {
1914 std::string collisionType = "junctionPedestrian";
1915 if (foeLane->getEdge().isCrossing()) {
1916 collisionType = "crossing";
1917 } else if (foeLane->getEdge().isWalkingArea()) {
1918 collisionType = "walkingarea";
1919 }
1920 handleIntermodalCollisionBetween(timestep, stage, collider, *it_p, 0, collisionType, toRemove, toTeleport);
1921 }
1922 }
1923 }
1924}
1925
1926
1927bool
1928MSLane::detectCollisionBetween(SUMOTime timestep, const std::string& stage, MSVehicle* collider, MSVehicle* victim,
1929 std::set<const MSVehicle*, ComparatorNumericalIdLess>& toRemove,
1930 std::set<const MSVehicle*, ComparatorNumericalIdLess>& toTeleport) const {
1931 if (myCollisionAction == COLLISION_ACTION_TELEPORT && ((victim->hasInfluencer() && victim->getInfluencer().isRemoteAffected(timestep)) ||
1932 (collider->hasInfluencer() && collider->getInfluencer().isRemoteAffected(timestep)))) {
1933 return false;
1934 }
1935
1936 // No self-collisions! (This is assumed to be ensured at caller side)
1937 if (collider == victim) {
1938 return false;
1939 }
1940
1941 const bool colliderOpposite = collider->getLaneChangeModel().isOpposite() || collider->isBidiOn(this);
1942 const bool victimOpposite = victim->getLaneChangeModel().isOpposite() || victim->isBidiOn(this);
1943 const bool bothOpposite = victimOpposite && colliderOpposite;
1944 if (bothOpposite) {
1945 std::swap(victim, collider);
1946 }
1947 const double colliderPos = colliderOpposite && !bothOpposite ? collider->getBackPositionOnLane(this) : collider->getPositionOnLane(this);
1948 const double minGapFactor = myCollisionMinGapFactor >= 0 ? myCollisionMinGapFactor : collider->getCarFollowModel().getCollisionMinGapFactor();
1949 double victimBack = victimOpposite && !bothOpposite ? victim->getPositionOnLane(this) : victim->getBackPositionOnLane(this);
1950 if (victim->getLateralOverlap() > 0 || collider->getLateralOverlap() > 0) {
1951 if (&collider->getLane()->getEdge() == myEdge && collider->getLane()->getLength() > getLength()) {
1952 // interpret victim position on the longer lane
1953 victimBack *= collider->getLane()->getLength() / getLength();
1954 }
1955 }
1956 double gap = victimBack - colliderPos - minGapFactor * collider->getVehicleType().getMinGap();
1957 if (bothOpposite) {
1958 gap = colliderPos - victimBack - minGapFactor * collider->getVehicleType().getMinGap();
1959 } else if (colliderOpposite) {
1960 // vehicles are back to back so (frontal) minGap doesn't apply
1961 gap += minGapFactor * collider->getVehicleType().getMinGap();
1962 }
1963#ifdef DEBUG_COLLISIONS
1964 if (DEBUG_COND && (DEBUG_COND2(collider) || DEBUG_COND2(victim))) {
1965 std::cout << SIMTIME
1966 << " thisLane=" << getID()
1967 << " collider=" << collider->getID()
1968 << " victim=" << victim->getID()
1969 << " colOpposite=" << colliderOpposite
1970 << " vicOpposite=" << victimOpposite
1971 << " colLane=" << collider->getLane()->getID()
1972 << " vicLane=" << victim->getLane()->getID()
1973 << " colPos=" << colliderPos
1974 << " vicBack=" << victimBack
1975 << " colLat=" << collider->getCenterOnEdge(this)
1976 << " vicLat=" << victim->getCenterOnEdge(this)
1977 << " minGap=" << collider->getVehicleType().getMinGap()
1978 << " minGapFactor=" << minGapFactor
1979 << " gap=" << gap
1980 << "\n";
1981 }
1982#endif
1983 if (victimOpposite && gap < -(collider->getLength() + victim->getLength())) {
1984 // already past each other
1985 return false;
1986 }
1987 if (gap < -NUMERICAL_EPS) {
1988 double latGap = 0;
1989 if (MSGlobals::gSublane) {
1990 latGap = (fabs(victim->getCenterOnEdge(this) - collider->getCenterOnEdge(this))
1991 - 0.5 * fabs(victim->getVehicleType().getWidth() + collider->getVehicleType().getWidth()));
1992 if (latGap + NUMERICAL_EPS > 0) {
1993 return false;
1994 }
1995 // account for ambiguous gap computation related to partial
1996 // occupation of lanes with different lengths
1997 if (isInternal() && getEdge().getNumLanes() > 1 && victim->getLane() != collider->getLane()) {
1998 double gapDelta = 0;
1999 const MSVehicle* otherLaneVeh = collider->getLane() == this ? victim : collider;
2000 if (otherLaneVeh->getLaneChangeModel().getShadowLane() == this) {
2001 gapDelta = getLength() - otherLaneVeh->getLane()->getLength();
2002 } else {
2003 for (const MSLane* cand : otherLaneVeh->getFurtherLanes()) {
2004 if (&cand->getEdge() == &getEdge()) {
2005 gapDelta = getLength() - cand->getLength();
2006 break;
2007 }
2008 }
2009 }
2010 if (gap + gapDelta >= 0) {
2011 return false;
2012 }
2013 }
2014 }
2016 && collider->getLaneChangeModel().isChangingLanes()
2017 && victim->getLaneChangeModel().isChangingLanes()
2018 && victim->getLane() != this) {
2019 // synchroneous lane change maneuver
2020 return false;
2021 }
2022#ifdef DEBUG_COLLISIONS
2023 if (DEBUG_COND && (DEBUG_COND2(collider) || DEBUG_COND2(victim))) {
2024 std::cout << SIMTIME << " detectedCollision gap=" << gap << " latGap=" << latGap << "\n";
2025 }
2026#endif
2027 handleCollisionBetween(timestep, stage, collider, victim, gap, latGap, toRemove, toTeleport);
2028 return true;
2029 }
2030 return false;
2031}
2032
2033
2034void
2035MSLane::handleCollisionBetween(SUMOTime timestep, const std::string& stage, const MSVehicle* collider, const MSVehicle* victim,
2036 double gap, double latGap, std::set<const MSVehicle*, ComparatorNumericalIdLess>& toRemove,
2037 std::set<const MSVehicle*, ComparatorNumericalIdLess>& toTeleport) const {
2038 if (collider->ignoreCollision() || victim->ignoreCollision()) {
2039 return;
2040 }
2041 std::string collisionType;
2042 std::string collisionText;
2043 if (isFrontalCollision(collider, victim)) {
2044 collisionType = "frontal";
2045 collisionText = TL("frontal collision");
2046 } else if (stage == MSNet::STAGE_LANECHANGE) {
2047 collisionType = "side";
2048 collisionText = TL("side collision");
2049 } else if (isInternal()) {
2050 collisionType = "junction";
2051 collisionText = TL("junction collision");
2052 } else {
2053 collisionType = "collision";
2054 collisionText = TL("collision");
2055 }
2056
2057 // in frontal collisions the opposite vehicle is the collider
2058 if (victim->getLaneChangeModel().isOpposite() && !collider->getLaneChangeModel().isOpposite()) {
2059 std::swap(collider, victim);
2060 }
2061 std::string prefix = TLF("Vehicle '%'; % with vehicle '%", collider->getID(), collisionText, victim->getID());
2062 if (myCollisionStopTime > 0) {
2063 if (collider->collisionStopTime() >= 0 && victim->collisionStopTime() >= 0) {
2064 return;
2065 }
2066 std::string dummyError;
2070 const double collisionAngle = RAD2DEG(fabs(GeomHelper::angleDiff(victim->getAngle(), collider->getAngle())));
2071 // determine new speeds from collision angle (@todo account for vehicle mass)
2072 double victimSpeed = victim->getSpeed();
2073 double colliderSpeed = collider->getSpeed();
2074 // double victimOrigSpeed = victim->getSpeed();
2075 // double colliderOrigSpeed = collider->getSpeed();
2076 if (collisionAngle < 45) {
2077 // rear-end collisions
2078 colliderSpeed = MIN2(colliderSpeed, victimSpeed);
2079 } else if (collisionAngle < 135) {
2080 // side collision
2081 colliderSpeed /= 2;
2082 victimSpeed /= 2;
2083 } else {
2084 // frontal collision
2085 colliderSpeed = 0;
2086 victimSpeed = 0;
2087 }
2088 const double victimStopPos = MIN2(victim->getLane()->getLength(),
2089 victim->getPositionOnLane() + victim->getCarFollowModel().brakeGap(victimSpeed, victim->getCarFollowModel().getEmergencyDecel(), 0));
2090 if (victim->collisionStopTime() < 0) {
2091 stop.collision = true;
2092 stop.lane = victim->getLane()->getID();
2093 // @todo: push victim forward?
2094 stop.startPos = victimStopPos;
2095 stop.endPos = stop.startPos;
2097 ((MSBaseVehicle*)victim)->addStop(stop, dummyError, 0);
2098 }
2099 if (collider->collisionStopTime() < 0) {
2100 stop.collision = true;
2101 stop.lane = collider->getLane()->getID();
2102 stop.startPos = MIN2(collider->getPositionOnLane() + collider->getCarFollowModel().brakeGap(colliderSpeed, collider->getCarFollowModel().getEmergencyDecel(), 0),
2103 MAX3(0.0, victimStopPos - 0.75 * victim->getVehicleType().getLength(),
2104 collider->getPositionOnLane() - SPEED2DIST(collider->getSpeed())));
2105 stop.endPos = stop.startPos;
2107 ((MSBaseVehicle*)collider)->addStop(stop, dummyError, 0);
2108 }
2109 //std::cout << " collisionAngle=" << collisionAngle
2110 // << "\n vPos=" << victim->getPositionOnLane() << " vStop=" << victimStopPos << " vSpeed=" << victimOrigSpeed << " vSpeed2=" << victimSpeed << " vSpeed3=" << victim->getSpeed()
2111 // << "\n cPos=" << collider->getPositionOnLane() << " cStop=" << stop.startPos << " cSpeed=" << colliderOrigSpeed << " cSpeed2=" << colliderSpeed << " cSpeed3=" << collider->getSpeed()
2112 // << "\n";
2113 } else {
2114 switch (myCollisionAction) {
2116 break;
2118 prefix = TLF("Teleporting vehicle '%'; % with vehicle '%", collider->getID(), collisionText, victim->getID());
2119 toRemove.insert(collider);
2120 toTeleport.insert(collider);
2121 break;
2123 prefix = TLF("Removing % participants: vehicle '%', vehicle '%", collisionText, collider->getID(), victim->getID());
2124 bool removeCollider = true;
2125 bool removeVictim = true;
2126 removeVictim = !(victim->hasInfluencer() && victim->getInfluencer()->isRemoteAffected(timestep));
2127 removeCollider = !(collider->hasInfluencer() && collider->getInfluencer()->isRemoteAffected(timestep));
2128 if (removeVictim) {
2129 toRemove.insert(victim);
2130 }
2131 if (removeCollider) {
2132 toRemove.insert(collider);
2133 }
2134 if (!removeVictim) {
2135 if (!removeCollider) {
2136 prefix = TLF("Keeping remote-controlled % participants: vehicle '%', vehicle '%", collisionText, collider->getID(), victim->getID());
2137 } else {
2138 prefix = TLF("Removing % participant: vehicle '%', keeping remote-controlled vehicle '%", collisionText, collider->getID(), victim->getID());
2139 }
2140 } else if (!removeCollider) {
2141 prefix = TLF("Keeping remote-controlled % participant: vehicle '%', removing vehicle '%", collisionText, collider->getID(), victim->getID());
2142 }
2143 break;
2144 }
2145 default:
2146 break;
2147 }
2148 }
2149 const bool newCollision = MSNet::getInstance()->registerCollision(collider, victim, collisionType, this, collider->getPositionOnLane(this));
2150 if (newCollision) {
2151 WRITE_WARNINGF(prefix + "', lane='%', gap=%%, time=%, stage=%.",
2152 getID(), toString(gap), (MSGlobals::gSublane ? TL(", latGap=") + toString(latGap) : ""),
2153 time2string(timestep), stage);
2157 }
2158#ifdef DEBUG_COLLISIONS
2159 if (DEBUG_COND2(collider)) {
2160 toRemove.erase(collider);
2161 toTeleport.erase(collider);
2162 }
2163 if (DEBUG_COND2(victim)) {
2164 toRemove.erase(victim);
2165 toTeleport.erase(victim);
2166 }
2167#endif
2168}
2169
2170
2171void
2172MSLane::handleIntermodalCollisionBetween(SUMOTime timestep, const std::string& stage, const MSVehicle* collider, const MSTransportable* victim,
2173 double gap, const std::string& collisionType,
2174 std::set<const MSVehicle*, ComparatorNumericalIdLess>& toRemove,
2175 std::set<const MSVehicle*, ComparatorNumericalIdLess>& toTeleport) const {
2176 if (collider->ignoreCollision()) {
2177 return;
2178 }
2179 std::string prefix = TLF("Vehicle '%'", collider->getID());
2181 if (collider->collisionStopTime() >= 0) {
2182 return;
2183 }
2184 std::string dummyError;
2188 // determine new speeds from collision angle (@todo account for vehicle mass)
2189 double colliderSpeed = collider->getSpeed();
2190 const double victimStopPos = victim->getEdgePos();
2191 // double victimOrigSpeed = victim->getSpeed();
2192 // double colliderOrigSpeed = collider->getSpeed();
2193 if (collider->collisionStopTime() < 0) {
2194 stop.collision = true;
2195 stop.lane = collider->getLane()->getID();
2196 stop.startPos = MIN2(collider->getPositionOnLane() + collider->getCarFollowModel().brakeGap(colliderSpeed, collider->getCarFollowModel().getEmergencyDecel(), 0),
2197 MAX3(0.0, victimStopPos - 0.75 * victim->getVehicleType().getLength(),
2198 collider->getPositionOnLane() - SPEED2DIST(collider->getSpeed())));
2199 stop.endPos = stop.startPos;
2201 ((MSBaseVehicle*)collider)->addStop(stop, dummyError, 0);
2202 }
2203 } else {
2206 break;
2208 prefix = TLF("Teleporting vehicle '%' after", collider->getID());
2209 toRemove.insert(collider);
2210 toTeleport.insert(collider);
2211 break;
2213 prefix = TLF("Removing vehicle '%' after", collider->getID());
2214 bool removeCollider = true;
2215 removeCollider = !(collider->hasInfluencer() && collider->getInfluencer()->isRemoteAffected(timestep));
2216 if (!removeCollider) {
2217 prefix = TLF("Keeping remote-controlled vehicle '%' after", collider->getID());
2218 } else {
2219 toRemove.insert(collider);
2220 }
2221 break;
2222 }
2223 default:
2224 break;
2225 }
2226 }
2227 const bool newCollision = MSNet::getInstance()->registerCollision(collider, victim, collisionType, this, victim->getEdgePos());
2228 if (newCollision) {
2229 if (gap != 0) {
2230 WRITE_WARNING(prefix + TLF(" collision with person '%', lane='%', gap=%, time=%, stage=%.",
2231 victim->getID(), getID(), gap, time2string(timestep), stage));
2232 } else {
2233 WRITE_WARNING(prefix + TLF(" collision with person '%', lane='%', time=%, stage=%.",
2234 victim->getID(), getID(), time2string(timestep), stage));
2235 }
2238 }
2239#ifdef DEBUG_COLLISIONS
2240 if (DEBUG_COND2(collider)) {
2241 toRemove.erase(collider);
2242 toTeleport.erase(collider);
2243 }
2244#endif
2245}
2246
2247
2248bool
2249MSLane::isFrontalCollision(const MSVehicle* collider, const MSVehicle* victim) {
2250 if (collider->getLaneChangeModel().isOpposite() != victim->getLaneChangeModel().isOpposite()) {
2251 return true;
2252 } else {
2253 const MSEdge* victimBidi = victim->getLane()->getEdge().getBidiEdge();
2254 if (&collider->getLane()->getEdge() == victimBidi) {
2255 return true;
2256 } else {
2257 for (MSLane* further : collider->getFurtherLanes()) {
2258 if (&further->getEdge() == victimBidi) {
2259 return true;
2260 }
2261 }
2262 }
2263 }
2264 return false;
2265}
2266
2267void
2269 // multithreading: there are concurrent writes to myNeedsCollisionCheck but all of them should set it to true
2270 myNeedsCollisionCheck = true;
2271 MSLane* bidi = getBidiLane();
2272 if (bidi != nullptr && bidi->getVehicleNumber() == 0) {
2274 }
2275 MSVehicle* firstNotStopped = nullptr;
2276 // iterate over vehicles in reverse so that move reminders will be called in the correct order
2277 for (VehCont::reverse_iterator i = myVehicles.rbegin(); i != myVehicles.rend();) {
2278 MSVehicle* veh = *i;
2279 // length is needed later when the vehicle may not exist anymore
2280 const double length = veh->getVehicleType().getLengthWithGap();
2281 const double nettoLength = veh->getVehicleType().getLength();
2282 const bool moved = veh->executeMove();
2283 MSLane* const target = veh->getMutableLane();
2284 if (veh->hasArrived()) {
2285 // vehicle has reached its arrival position
2286#ifdef DEBUG_EXEC_MOVE
2287 if DEBUG_COND2(veh) {
2288 std::cout << SIMTIME << " veh " << veh->getID() << " has arrived." << std::endl;
2289 }
2290#endif
2293 } else if (target != nullptr && moved) {
2294 if (target->getEdge().isVaporizing()) {
2295 // vehicle has reached a vaporizing edge
2298 } else {
2299 // vehicle has entered a new lane (leaveLane and workOnMoveReminders were already called in MSVehicle::executeMove)
2300 target->myVehBuffer.push_back(veh);
2302 if (MSGlobals::gSublane && veh->getLaneChangeModel().getShadowLane() != nullptr) {
2303 // trigger sorting of partial vehicles as their order may have changed (lane might not be active and only contain partial vehicles)
2305 }
2306 }
2307 } else if (veh->isParking()) {
2308 // vehicle started to park
2310 myParkingVehicles.insert(veh);
2311 } else if (veh->brokeDown()) {
2312 veh->resumeFromStopping();
2313 WRITE_WARNINGF(TL("Removing vehicle '%' after breaking down, lane='%', time=%."),
2314 veh->getID(), veh->getLane()->getID(), time2string(t));
2317 } else if (veh->isJumping()) {
2318 // vehicle jumps to next route edge
2320 } else if (veh->getPositionOnLane() > getLength()) {
2321 // for any reasons the vehicle is beyond its lane...
2322 // this should never happen because it is handled in MSVehicle::executeMove
2323 assert(false);
2324 WRITE_WARNINGF(TL("Teleporting vehicle '%'; beyond end of lane, target lane='%', time=%."),
2325 veh->getID(), getID(), time2string(t));
2328
2329 } else if (veh->collisionStopTime() == 0) {
2330 veh->resumeFromStopping();
2332 WRITE_WARNINGF(TL("Removing vehicle '%' after earlier collision, lane='%', time=%."),
2333 veh->getID(), veh->getLane()->getID(), time2string(t));
2337 WRITE_WARNINGF(TL("Teleporting vehicle '%' after earlier collision, lane='%', time=%."),
2338 veh->getID(), veh->getLane()->getID(), time2string(t));
2340 } else {
2341 if (firstNotStopped == nullptr && !(*i)->isStopped() && (*i)->getLane() == this) {
2342 firstNotStopped = *i;
2343 }
2344 ++i;
2345 continue;
2346 }
2347 } else {
2348 if (firstNotStopped == nullptr && !(*i)->isStopped() && (*i)->getLane() == this) {
2349 firstNotStopped = *i;
2350 }
2351 ++i;
2352 continue;
2353 }
2355 myNettoVehicleLengthSumToRemove += nettoLength;
2356 ++i;
2357 i = VehCont::reverse_iterator(myVehicles.erase(i.base()));
2358 }
2359 if (firstNotStopped != nullptr) {
2363 const bool wrongLane = !appropriate(firstNotStopped);
2364 const bool disconnected = (MSGlobals::gTimeToTeleportDisconnected >= 0
2365 && firstNotStopped->succEdge(1) != nullptr
2366 && firstNotStopped->getEdge()->allowedLanes(*firstNotStopped->succEdge(1), firstNotStopped->getVClass()) == nullptr);
2367
2368 const bool r1 = ttt > 0 && firstNotStopped->getWaitingTime() > ttt && !disconnected
2369 // never teleport a taxi on the last edge of it's route (where it would exit the simulation)
2370 && (firstNotStopped->getDevice(typeid(MSDevice_Taxi)) == nullptr || firstNotStopped->getRoutePosition() < (firstNotStopped->getRoute().size() - 1));
2371 const bool r2 = !r1 && MSGlobals::gTimeToGridlockHighways > 0
2374 && !disconnected;
2375 const bool r3 = disconnected && firstNotStopped->getWaitingTime() > MSGlobals::gTimeToTeleportDisconnected;
2376 const bool r4 = !r1 && !r2 && !r3 && tttb > 0
2377 && firstNotStopped->getWaitingTime() > tttb && getBidiLane() && !disconnected;
2378 const bool r5 = MSGlobals::gTimeToTeleportRSDeadlock > 0 && MSRailSignalControl::hasInstance() && !r1 && !r2 && !r3 && !r4
2380 if (r1 || r2 || r3 || r4 || r5) {
2381 const std::vector<MSLink*>::const_iterator link = succLinkSec(*firstNotStopped, 1, *this, firstNotStopped->getBestLanesContinuation());
2382 const bool minorLink = !wrongLane && (link != myLinks.end()) && !((*link)->havePriority());
2383 std::string reason = (wrongLane ? " (wrong lane" : (minorLink ? " (yield" : " (jam"));
2386 if (firstNotStopped == myVehicles.back()) {
2387 myVehicles.pop_back();
2388 } else {
2389 myVehicles.erase(std::find(myVehicles.begin(), myVehicles.end(), firstNotStopped));
2390 reason = " (blocked";
2391 }
2392 WRITE_WARNINGF("Teleporting vehicle '%'; waited too long" + reason
2393 + (r2 ? ", highway" : "")
2394 + (r3 ? ", disconnected" : "")
2395 + (r4 ? ", bidi" : "")
2396 + (r5 ? ", railSignal" : "")
2397 + "), lane='%', time=%.", firstNotStopped->getID(), getID(), time2string(t));
2398 if (wrongLane) {
2400 } else if (minorLink) {
2402 } else {
2404 }
2408 } else {
2409 MSVehicleTransfer::getInstance()->add(t, firstNotStopped);
2410 }
2411 }
2412 }
2413 }
2414 if (MSGlobals::gSublane) {
2415 // trigger sorting of vehicles as their order may have changed
2417 }
2418}
2419
2420
2421void
2425
2426
2427void
2433 if (myVehicles.empty()) {
2434 // avoid numerical instability
2437 } else if (myRecalculateBruttoSum) {
2439 for (VehCont::const_iterator i = myVehicles.begin(); i != myVehicles.end(); ++i) {
2440 myBruttoVehicleLengthSum += (*i)->getVehicleType().getLengthWithGap();
2441 }
2442 myRecalculateBruttoSum = false;
2443 }
2444}
2445
2446
2447void
2451
2452
2453const MSEdge*
2455 return myEdge->getNormalSuccessor();
2456}
2457
2458
2459const MSLane*
2461 if (!this->isInternal()) {
2462 return nullptr;
2463 }
2464 offset = 0.;
2465 const MSLane* firstInternal = this;
2467 while (pred != nullptr && pred->isInternal()) {
2468 firstInternal = pred;
2469 offset += pred->getLength();
2470 pred = firstInternal->getCanonicalPredecessorLane();
2471 }
2472 return firstInternal;
2473}
2474
2475
2476// ------ Static (sic!) container methods ------
2477bool
2478MSLane::dictionary(const std::string& id, MSLane* ptr) {
2479 const DictType::iterator it = myDict.lower_bound(id);
2480 if (it == myDict.end() || it->first != id) {
2481 // id not in myDict
2482 myDict.emplace_hint(it, id, ptr);
2483 return true;
2484 }
2485 return false;
2486}
2487
2488
2489MSLane*
2490MSLane::dictionary(const std::string& id) {
2491 const DictType::iterator it = myDict.find(id);
2492 if (it == myDict.end()) {
2493 // id not in myDict
2494 return nullptr;
2495 }
2496 return it->second;
2497}
2498
2499
2500void
2502 for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
2503 delete (*i).second;
2504 }
2505 myDict.clear();
2506}
2507
2508
2509void
2510MSLane::insertIDs(std::vector<std::string>& into) {
2511 for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
2512 into.push_back((*i).first);
2513 }
2514}
2515
2516
2517template<class RTREE> void
2518MSLane::fill(RTREE& into) {
2519 for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
2520 MSLane* l = (*i).second;
2521 Boundary b = l->getShape().getBoxBoundary();
2522 b.grow(3.);
2523 const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
2524 const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
2525 into.Insert(cmin, cmax, l);
2526 }
2527}
2528
2529template void MSLane::fill<NamedRTree>(NamedRTree& into);
2530template void MSLane::fill<LANE_RTREE_QUAL>(LANE_RTREE_QUAL& into);
2531
2532// ------ ------
2533bool
2535 if (veh->getLaneChangeModel().isOpposite()) {
2536 return false;
2537 }
2538 if (myEdge->isInternal()) {
2539 return true;
2540 }
2541 if (veh->succEdge(1) == nullptr) {
2542 assert((int)veh->getBestLanes().size() > veh->getLaneIndex());
2543 if (veh->getBestLanes()[veh->getLaneIndex()].bestLaneOffset == 0) {
2544 return true;
2545 } else {
2546 return false;
2547 }
2548 }
2549 std::vector<MSLink*>::const_iterator link = succLinkSec(*veh, 1, *this, veh->getBestLanesContinuation());
2550 return (link != myLinks.end());
2551}
2552
2553
2554void
2556 myNeedsCollisionCheck = true;
2557 std::vector<MSVehicle*>& buffered = myVehBuffer.getContainer();
2558 sort(buffered.begin(), buffered.end(), vehicle_position_sorter(this));
2559 for (MSVehicle* const veh : buffered) {
2560 assert(veh->getLane() == this);
2561 myVehicles.insert(myVehicles.begin(), veh);
2562 myBruttoVehicleLengthSum += veh->getVehicleType().getLengthWithGap();
2563 myNettoVehicleLengthSum += veh->getVehicleType().getLength();
2564 //if (true) std::cout << SIMTIME << " integrateNewVehicle lane=" << getID() << " veh=" << veh->getID() << " (on lane " << veh->getLane()->getID() << ") into lane=" << getID() << " myBrutto=" << myBruttoVehicleLengthSum << "\n";
2566 }
2567 buffered.clear();
2569 //std::cout << SIMTIME << " integrateNewVehicle lane=" << getID() << " myVehicles1=" << toString(myVehicles);
2570 if (MSGlobals::gLateralResolution > 0 || myOpposite != nullptr) {
2571 sort(myVehicles.begin(), myVehicles.end(), vehicle_natural_position_sorter(this));
2572 }
2574#ifdef DEBUG_VEHICLE_CONTAINER
2575 if (DEBUG_COND) std::cout << SIMTIME << " integrateNewVehicle lane=" << getID()
2576 << " vehicles=" << toString(myVehicles) << " partials=" << toString(myPartialVehicles) << "\n";
2577#endif
2578}
2579
2580
2581void
2583 if (myPartialVehicles.size() > 1) {
2585 }
2586}
2587
2588
2589void
2591 if (myManeuverReservations.size() > 1) {
2592#ifdef DEBUG_CONTEXT
2593 if (DEBUG_COND) {
2594 std::cout << "sortManeuverReservations on lane " << getID()
2595 << "\nBefore sort: " << toString(myManeuverReservations) << std::endl;
2596 }
2597#endif
2599#ifdef DEBUG_CONTEXT
2600 if (DEBUG_COND) {
2601 std::cout << "After sort: " << toString(myManeuverReservations) << std::endl;
2602 }
2603#endif
2604 }
2605}
2606
2607
2608bool
2610 return myEdge->isInternal();
2611}
2612
2613
2614bool
2616 return myEdge->isNormal();
2617}
2618
2619
2620bool
2622 return myEdge->isCrossing();
2623}
2624
2625bool
2627 return myEdge->isWalkingArea();
2628}
2629
2630
2631MSVehicle*
2633 if (myVehicles.size() == 0) {
2634 return nullptr;
2635 }
2636 return myVehicles.front();
2637}
2638
2639
2640MSVehicle*
2642 if (myVehicles.size() == 0) {
2643 return nullptr;
2644 }
2645 return myVehicles.back();
2646}
2647
2648
2649MSVehicle*
2651 // all vehicles in myVehicles should have positions smaller or equal to
2652 // those in myPartialVehicles (unless we're on a bidi-lane)
2653 if (myVehicles.size() > 0) {
2654 if (myBidiLane != nullptr && myPartialVehicles.size() > 0) {
2655 if (myVehicles.front()->getPositionOnLane() > myPartialVehicles.front()->getPositionOnLane(this)) {
2656 return myPartialVehicles.front();
2657 }
2658 }
2659 return myVehicles.front();
2660 }
2661 if (myPartialVehicles.size() > 0) {
2662 return myPartialVehicles.front();
2663 }
2664 return nullptr;
2665}
2666
2667
2668MSVehicle*
2670 MSVehicle* result = nullptr;
2671 if (myVehicles.size() > 0) {
2672 result = myVehicles.back();
2673 }
2674 if (myPartialVehicles.size() > 0
2675 && (result == nullptr || result->getPositionOnLane(this) < myPartialVehicles.back()->getPositionOnLane(this))) {
2676 result = myPartialVehicles.back();
2677 }
2678 return result;
2679}
2680
2681
2682std::vector<MSLink*>::const_iterator
2683MSLane::succLinkSec(const SUMOVehicle& veh, int nRouteSuccs,
2684 const MSLane& succLinkSource, const std::vector<MSLane*>& conts) {
2685 const MSEdge* nRouteEdge = veh.succEdge(nRouteSuccs);
2686 // check whether the vehicle tried to look beyond its route
2687 if (nRouteEdge == nullptr) {
2688 // return end (no succeeding link) if so
2689 return succLinkSource.myLinks.end();
2690 }
2691 // if we are on an internal lane there should only be one link and it must be allowed
2692 if (succLinkSource.isInternal()) {
2693 assert(succLinkSource.myLinks.size() == 1);
2694 // could have been disallowed dynamically with a rerouter or via TraCI
2695 // assert(succLinkSource.myLinks[0]->getLane()->allowsVehicleClass(veh.getVehicleType().getVehicleClass()));
2696 return succLinkSource.myLinks.begin();
2697 }
2698 // a link may be used if
2699 // 1) there is a destination lane ((*link)->getLane()!=0)
2700 // 2) the destination lane belongs to the next edge in route ((*link)->getLane()->myEdge == nRouteEdge)
2701 // 3) the destination lane allows the vehicle's class ((*link)->getLane()->allowsVehicleClass(veh.getVehicleClass()))
2702
2703 // there should be a link which leads to the next desired lane our route in "conts" (built in "getBestLanes")
2704 // "conts" stores the best continuations of our current lane
2705 // we should never return an arbitrary link since this may cause collisions
2706
2707 if (nRouteSuccs < (int)conts.size()) {
2708 // we go through the links in our list and return the matching one
2709 for (std::vector<MSLink*>::const_iterator link = succLinkSource.myLinks.begin(); link != succLinkSource.myLinks.end(); ++link) {
2710 if ((*link)->getLane() != nullptr && (*link)->getLane()->myEdge == nRouteEdge
2711 && (*link)->getLane()->allowsVehicleClass(veh.getVClass())
2712 && ((*link)->getViaLane() == nullptr || (*link)->getViaLane()->allowsVehicleClass(veh.getVClass()))) {
2713 // we should use the link if it connects us to the best lane
2714 if ((*link)->getLane() == conts[nRouteSuccs]) {
2715 return link;
2716 }
2717 }
2718 }
2719 } else {
2720 // the source lane is a dead end (no continuations exist)
2721 return succLinkSource.myLinks.end();
2722 }
2723 // the only case where this should happen is for a disconnected route (deliberately ignored)
2724#ifdef DEBUG_NO_CONNECTION
2725 // the "'" around the ids are missing intentionally in the message below because it slows messaging down, resulting in test timeouts
2726 WRITE_WARNING("Could not find connection between lane " + succLinkSource.getID() + " and lane " + conts[nRouteSuccs]->getID() +
2727 " for vehicle " + veh.getID() + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
2728#endif
2729 return succLinkSource.myLinks.end();
2730}
2731
2732
2733const MSLink*
2734MSLane::getLinkTo(const MSLane* const target) const {
2735 const bool internal = target->isInternal();
2736 for (const MSLink* const l : myLinks) {
2737 if ((internal && l->getViaLane() == target) || (!internal && l->getLane() == target)) {
2738 return l;
2739 }
2740 }
2741 return nullptr;
2742}
2743
2744
2745const MSLane*
2746MSLane::getInternalFollowingLane(const MSLane* const target) const {
2747 for (const MSLink* const l : myLinks) {
2748 if (l->getLane() == target) {
2749 return l->getViaLane();
2750 }
2751 }
2752 return nullptr;
2753}
2754
2755
2756const MSLink*
2758 if (!isInternal()) {
2759 return nullptr;
2760 }
2761 const MSLane* internal = this;
2762 const MSLane* lane = this->getCanonicalPredecessorLane();
2763 assert(lane != nullptr);
2764 while (lane->isInternal()) {
2765 internal = lane;
2766 lane = lane->getCanonicalPredecessorLane();
2767 assert(lane != nullptr);
2768 }
2769 return lane->getLinkTo(internal);
2770}
2771
2772
2773void
2774MSLane::setMaxSpeed(double val, bool byVSS, bool byTraCI, double jamThreshold) {
2775 myMaxSpeed = val;
2776 mySpeedByVSS = byVSS;
2777 mySpeedByTraCI = byTraCI;
2781 while (first != nullptr) {
2782 first->setSpeed(val, SIMSTEP, jamThreshold, myIndex);
2783 first = first->getNextSegment();
2784 }
2785 }
2786}
2787
2788
2789void
2794
2795
2796void
2798 myLength = val;
2800}
2801
2802
2803void
2805 //if (getID() == "disabled_lane") std::cout << SIMTIME << " swapAfterLaneChange lane=" << getID() << " myVehicles=" << toString(myVehicles) << " myTmpVehicles=" << toString(myTmpVehicles) << "\n";
2807 myTmpVehicles.clear();
2808 // this needs to be done after finishing lane-changing for all lanes on the
2809 // current edge (MSLaneChanger::updateLanes())
2811 if (MSGlobals::gSublane && getOpposite() != nullptr) {
2813 }
2814 if (myBidiLane != nullptr) {
2816 }
2817}
2818
2819
2820MSVehicle*
2821MSLane::removeVehicle(MSVehicle* remVehicle, MSMoveReminder::Notification notification, bool notify) {
2822 assert(remVehicle->getLane() == this);
2823 for (MSLane::VehCont::iterator it = myVehicles.begin(); it < myVehicles.end(); it++) {
2824 if (remVehicle == *it) {
2825 if (notify) {
2826 remVehicle->leaveLane(notification);
2827 }
2828 myVehicles.erase(it);
2831 break;
2832 }
2833 }
2834 return remVehicle;
2835}
2836
2837
2838MSLane*
2839MSLane::getParallelLane(int offset, bool includeOpposite) const {
2840 return myEdge->parallelLane(this, offset, includeOpposite);
2841}
2842
2843
2844void
2846 IncomingLaneInfo ili;
2847 ili.lane = lane;
2848 ili.viaLink = viaLink;
2849 ili.length = lane->getLength();
2850 myIncomingLanes.push_back(ili);
2851}
2852
2853
2854void
2855MSLane::addApproachingLane(MSLane* lane, bool warnMultiCon) {
2856 MSEdge* approachingEdge = &lane->getEdge();
2857 if (myApproachingLanes.find(approachingEdge) == myApproachingLanes.end()) {
2858 myApproachingLanes[approachingEdge] = std::vector<MSLane*>();
2859 } else if (!approachingEdge->isInternal() && warnMultiCon) {
2860 // whenever a normal edge connects twice, there is a corresponding
2861 // internal edge wich connects twice, one warning is sufficient
2862 WRITE_WARNINGF(TL("Lane '%' is approached multiple times from edge '%'. This may cause collisions."),
2863 getID(), approachingEdge->getID());
2864 }
2865 myApproachingLanes[approachingEdge].push_back(lane);
2866}
2867
2868
2869bool
2870MSLane::isApproachedFrom(MSEdge* const edge, MSLane* const lane) {
2871 std::map<MSEdge*, std::vector<MSLane*> >::const_iterator i = myApproachingLanes.find(edge);
2872 if (i == myApproachingLanes.end()) {
2873 return false;
2874 }
2875 const std::vector<MSLane*>& lanes = (*i).second;
2876 return std::find(lanes.begin(), lanes.end(), lane) != lanes.end();
2877}
2878
2879
2880double MSLane::getMissingRearGap(const MSVehicle* leader, double backOffset, double leaderSpeed) const {
2881 // this follows the same logic as getFollowerOnConsecutive. we do a tree
2882 // search and check for the vehicle with the largest missing rear gap within
2883 // relevant range
2884 double result = 0;
2885 const double leaderDecel = leader->getCarFollowModel().getMaxDecel();
2886 CLeaderDist followerInfo = getFollowersOnConsecutive(leader, backOffset, false)[0];
2887 const MSVehicle* v = followerInfo.first;
2888 if (v != nullptr) {
2889 result = v->getCarFollowModel().getSecureGap(v, leader, v->getSpeed(), leaderSpeed, leaderDecel) - followerInfo.second;
2890 }
2891 return result;
2892}
2893
2894
2895double
2898 const double maxSpeed = getSpeedLimit() * vc.getMaxSpeedFactor();
2899 // NOTE: For the euler update this is an upper bound on the actual braking distance (see ticket #860)
2900 // impose a hard bound due to visibility / common sense to avoid unnecessary computation if there are strange vehicles in the fleet
2901 const double minDecel = isRailway(myPermissions) ? vc.getMinDecelerationRail() : vc.getMinDeceleration();
2902 return MIN2(maxSpeed * maxSpeed * 0.5 / minDecel,
2903 myPermissions == SVC_SHIP ? 10000.0 : 1000.0);
2904}
2905
2906
2907std::pair<MSVehicle* const, double>
2908MSLane::getLeader(const MSVehicle* veh, const double vehPos, const std::vector<MSLane*>& bestLaneConts, double dist, bool checkTmpVehicles) const {
2909 // get the leading vehicle for (shadow) veh
2910 // XXX this only works as long as all lanes of an edge have equal length
2911#ifdef DEBUG_CONTEXT
2912 if (DEBUG_COND2(veh)) {
2913 std::cout << " getLeader lane=" << getID() << " ego=" << veh->getID() << " vehs=" << toString(myVehicles) << " tmpVehs=" << toString(myTmpVehicles) << "\n";
2914 }
2915#endif
2916 if (checkTmpVehicles) {
2917 for (VehCont::const_iterator last = myTmpVehicles.begin(); last != myTmpVehicles.end(); ++last) {
2918 // XXX refactor leaderInfo to use a const vehicle all the way through the call hierarchy
2919 MSVehicle* pred = (MSVehicle*)*last;
2920 if (pred == veh) {
2921 continue;
2922 }
2923#ifdef DEBUG_CONTEXT
2924 if (DEBUG_COND2(veh)) {
2925 std::cout << std::setprecision(gPrecision) << " getLeader lane=" << getID() << " ego=" << veh->getID() << " egoPos=" << vehPos << " pred=" << pred->getID() << " predPos=" << pred->getPositionOnLane() << "\n";
2926 }
2927#endif
2928 if (pred->getPositionOnLane() >= vehPos) {
2929 return std::pair<MSVehicle* const, double>(pred, pred->getBackPositionOnLane(this) - veh->getVehicleType().getMinGap() - vehPos);
2930 }
2931 }
2932 } else {
2933 for (AnyVehicleIterator last = anyVehiclesBegin(); last != anyVehiclesEnd(); ++last) {
2934 // XXX refactor leaderInfo to use a const vehicle all the way through the call hierarchy
2935 MSVehicle* pred = (MSVehicle*)*last;
2936 if (pred == veh) {
2937 continue;
2938 }
2939#ifdef DEBUG_CONTEXT
2940 if (DEBUG_COND2(veh)) {
2941 std::cout << " getLeader lane=" << getID() << " ego=" << veh->getID() << " egoPos=" << vehPos
2942 << " pred=" << pred->getID() << " predPos=" << pred->getPositionOnLane(this) << " predBack=" << pred->getBackPositionOnLane(this) << "\n";
2943 }
2944#endif
2945 if (pred->getPositionOnLane(this) >= vehPos) {
2947 && pred->getLaneChangeModel().isOpposite()
2949 && pred->getLaneChangeModel().getShadowLane() == this) {
2950 // skip non-overlapping shadow
2951 continue;
2952 }
2953 return std::pair<MSVehicle* const, double>(pred, pred->getBackPositionOnLane(this) - veh->getVehicleType().getMinGap() - vehPos);
2954 }
2955 }
2956 }
2957 // XXX from here on the code mirrors MSLaneChanger::getRealLeader
2958 if (bestLaneConts.size() > 0) {
2959 double seen = getLength() - vehPos;
2960 double speed = veh->getSpeed();
2961 if (dist < 0) {
2962 dist = veh->getCarFollowModel().brakeGap(speed) + veh->getVehicleType().getMinGap();
2963 }
2964#ifdef DEBUG_CONTEXT
2965 if (DEBUG_COND2(veh)) {
2966 std::cout << " getLeader lane=" << getID() << " seen=" << seen << " dist=" << dist << "\n";
2967 }
2968#endif
2969 if (seen > dist) {
2970 return std::pair<MSVehicle* const, double>(static_cast<MSVehicle*>(nullptr), -1);
2971 }
2972 return getLeaderOnConsecutive(dist, seen, speed, *veh, bestLaneConts);
2973 } else {
2974 return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
2975 }
2976}
2977
2978
2979std::pair<MSVehicle* const, double>
2980MSLane::getLeaderOnConsecutive(double dist, double seen, double speed, const MSVehicle& veh,
2981 const std::vector<MSLane*>& bestLaneConts, bool considerCrossingFoes) const {
2982#ifdef DEBUG_CONTEXT
2983 if (DEBUG_COND2(&veh)) {
2984 std::cout << " getLeaderOnConsecutive lane=" << getID() << " ego=" << veh.getID() << " seen=" << seen << " dist=" << dist << " conts=" << toString(bestLaneConts) << "\n";
2985 }
2986#endif
2987 if (seen > dist && !isInternal()) {
2988 return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
2989 }
2990 int view = 1;
2991 // loop over following lanes
2992 if (myPartialVehicles.size() > 0) {
2993 // XXX
2994 MSVehicle* pred = myPartialVehicles.front();
2995 const double gap = seen - (getLength() - pred->getBackPositionOnLane(this)) - veh.getVehicleType().getMinGap();
2996#ifdef DEBUG_CONTEXT
2997 if (DEBUG_COND2(&veh)) {
2998 std::cout << " predGap=" << gap << " partials=" << toString(myPartialVehicles) << "\n";
2999 }
3000#endif
3001 // make sure pred is really a leader and not doing continous lane-changing behind ego
3002 if (gap > 0) {
3003 return std::pair<MSVehicle* const, double>(pred, gap);
3004 }
3005 }
3006#ifdef DEBUG_CONTEXT
3007 if (DEBUG_COND2(&veh)) {
3008 gDebugFlag1 = true;
3009 }
3010#endif
3011 const MSLane* nextLane = this;
3012 do {
3013 nextLane->getVehiclesSecure(); // lock against running sim when called from GUI for time gap coloring
3014 // get the next link used
3015 std::vector<MSLink*>::const_iterator link = succLinkSec(veh, view, *nextLane, bestLaneConts);
3016 if (nextLane->isLinkEnd(link) && view < veh.getRoute().size() - veh.getRoutePosition()) {
3017 const MSEdge* nextEdge = *(veh.getCurrentRouteEdge() + view);
3018 if (nextEdge->getNumLanes() == 1) {
3019 // lanes are unambiguous on the next route edge, continue beyond bestLaneConts
3020 for (link = nextLane->getLinkCont().begin(); link < nextLane->getLinkCont().end(); link++) {
3021 if ((*link)->getLane() == nextEdge->getLanes().front()) {
3022 break;
3023 }
3024 }
3025 }
3026 }
3027 if (nextLane->isLinkEnd(link)) {
3028#ifdef DEBUG_CONTEXT
3029 if (DEBUG_COND2(&veh)) {
3030 std::cout << " cannot continue after nextLane=" << nextLane->getID() << "\n";
3031 }
3032#endif
3033 nextLane->releaseVehicles();
3034 break;
3035 }
3036 // check for link leaders
3037 const bool laneChanging = veh.getLane() != this;
3038 const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(&veh, seen);
3039 nextLane->releaseVehicles();
3040 if (linkLeaders.size() > 0) {
3041 std::pair<MSVehicle*, double> result;
3042 double shortestGap = std::numeric_limits<double>::max();
3043 for (auto ll : linkLeaders) {
3044 double gap = ll.vehAndGap.second;
3045 MSVehicle* lVeh = ll.vehAndGap.first;
3046 if (lVeh != nullptr) {
3047 // leader is a vehicle, not a pedestrian
3048 gap += lVeh->getCarFollowModel().brakeGap(lVeh->getSpeed(), lVeh->getCarFollowModel().getMaxDecel(), 0);
3049 }
3050#ifdef DEBUG_CONTEXT
3051 if (DEBUG_COND2(&veh)) {
3052 std::cout << " linkLeader candidate " << Named::getIDSecure(lVeh)
3053 << " isLeader=" << veh.isLeader(*link, lVeh, ll.vehAndGap.second)
3054 << " gap=" << ll.vehAndGap.second
3055 << " gap+brakeing=" << gap
3056 << "\n";
3057 }
3058#endif
3059 // skip vehicles which do not share the outgoing edge (to get only real leader vehicles in TraCI #13842)
3060 if (!considerCrossingFoes && !ll.sameTarget()) {
3061 continue;
3062 }
3063 // in the context of lane-changing, all candidates are leaders
3064 if (lVeh != nullptr && !laneChanging && !veh.isLeader(*link, lVeh, ll.vehAndGap.second)) {
3065 continue;
3066 }
3067 if (gap < shortestGap) {
3068 shortestGap = gap;
3069 if (ll.vehAndGap.second < 0 && !MSGlobals::gComputeLC) {
3070 // can always continue up to the stop line or crossing point
3071 // @todo: figure out whether this should also impact lane changing
3072 ll.vehAndGap.second = MAX2(seen - nextLane->getLength(), ll.distToCrossing);
3073 }
3074 result = ll.vehAndGap;
3075 }
3076 }
3077 if (shortestGap != std::numeric_limits<double>::max()) {
3078#ifdef DEBUG_CONTEXT
3079 if (DEBUG_COND2(&veh)) {
3080 std::cout << " found linkLeader after nextLane=" << nextLane->getID() << "\n";
3081 gDebugFlag1 = false;
3082 }
3083#endif
3084 return result;
3085 }
3086 }
3087 bool nextInternal = (*link)->getViaLane() != nullptr;
3088 nextLane = (*link)->getViaLaneOrLane();
3089 if (nextLane == nullptr) {
3090 break;
3091 }
3092 nextLane->getVehiclesSecure(); // lock against running sim when called from GUI for time gap coloring
3093 MSVehicle* leader = nextLane->getLastAnyVehicle();
3094 if (leader != nullptr) {
3095#ifdef DEBUG_CONTEXT
3096 if (DEBUG_COND2(&veh)) {
3097 std::cout << " found leader " << leader->getID() << " on nextLane=" << nextLane->getID() << "\n";
3098 }
3099#endif
3100 const double leaderDist = seen + leader->getBackPositionOnLane(nextLane) - veh.getVehicleType().getMinGap();
3101 nextLane->releaseVehicles();
3102 return std::make_pair(leader, leaderDist);
3103 }
3104 nextLane->releaseVehicles();
3105 if (nextLane->getVehicleMaxSpeed(&veh) < speed) {
3106 dist = veh.getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(&veh));
3107 }
3108 seen += nextLane->getLength();
3109 if (!nextInternal) {
3110 view++;
3111 }
3112 } while (seen <= dist || nextLane->isInternal());
3113#ifdef DEBUG_CONTEXT
3114 gDebugFlag1 = false;
3115#endif
3116 return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
3117}
3118
3119
3120std::pair<MSVehicle* const, double>
3121MSLane::getCriticalLeader(double dist, double seen, double speed, const MSVehicle& veh) const {
3122#ifdef DEBUG_CONTEXT
3123 if (DEBUG_COND2(&veh)) {
3124 std::cout << SIMTIME << " getCriticalLeader. lane=" << getID() << " veh=" << veh.getID() << "\n";
3125 }
3126#endif
3127 const std::vector<MSLane*>& bestLaneConts = veh.getBestLanesContinuation(this);
3128 std::pair<MSVehicle*, double> result = std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
3129 double safeSpeed = std::numeric_limits<double>::max();
3130 int view = 1;
3131 // loop over following lanes
3132 // @note: we don't check the partial occupator for this lane since it was
3133 // already checked in MSLaneChanger::getRealLeader()
3134 const MSLane* nextLane = this;
3135 SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / MAX2(speed, NUMERICAL_EPS));
3136 do {
3137 // get the next link used
3138 std::vector<MSLink*>::const_iterator link = succLinkSec(veh, view, *nextLane, bestLaneConts);
3139 if (nextLane->isLinkEnd(link) || !(*link)->opened(arrivalTime, speed, speed, veh.getVehicleType().getLength(),
3140 veh.getImpatience(), veh.getCarFollowModel().getMaxDecel(), 0, veh.getLateralPositionOnLane(), nullptr, false, &veh) || (*link)->haveRed()) {
3141 return result;
3142 }
3143 // check for link leaders
3144#ifdef DEBUG_CONTEXT
3145 if (DEBUG_COND2(&veh)) {
3146 gDebugFlag1 = true; // See MSLink::getLeaderInfo
3147 }
3148#endif
3149 const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(&veh, seen);
3150#ifdef DEBUG_CONTEXT
3151 if (DEBUG_COND2(&veh)) {
3152 gDebugFlag1 = false; // See MSLink::getLeaderInfo
3153 }
3154#endif
3155 for (MSLink::LinkLeaders::const_iterator it = linkLeaders.begin(); it != linkLeaders.end(); ++it) {
3156 const MSVehicle* leader = (*it).vehAndGap.first;
3157 if (leader != nullptr && leader != result.first) {
3158 // XXX ignoring pedestrians here!
3159 // XXX ignoring the fact that the link leader may alread by following us
3160 // XXX ignoring the fact that we may drive up to the crossing point
3161 double tmpSpeed = safeSpeed;
3162 veh.adaptToJunctionLeader((*it).vehAndGap, seen, nullptr, nextLane, tmpSpeed, tmpSpeed, (*it).distToCrossing);
3163#ifdef DEBUG_CONTEXT
3164 if (DEBUG_COND2(&veh)) {
3165 std::cout << " linkLeader=" << leader->getID() << " gap=" << result.second << " tmpSpeed=" << tmpSpeed << " safeSpeed=" << safeSpeed << "\n";
3166 }
3167#endif
3168 if (tmpSpeed < safeSpeed) {
3169 safeSpeed = tmpSpeed;
3170 result = (*it).vehAndGap;
3171 }
3172 }
3173 }
3174 bool nextInternal = (*link)->getViaLane() != nullptr;
3175 nextLane = (*link)->getViaLaneOrLane();
3176 if (nextLane == nullptr) {
3177 break;
3178 }
3179 MSVehicle* leader = nextLane->getLastAnyVehicle();
3180 if (leader != nullptr && leader != result.first) {
3181 const double gap = seen + leader->getBackPositionOnLane(nextLane) - veh.getVehicleType().getMinGap();
3182 const double tmpSpeed = veh.getCarFollowModel().insertionFollowSpeed(&veh, speed, gap, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel(), leader);
3183 if (tmpSpeed < safeSpeed) {
3184 safeSpeed = tmpSpeed;
3185 result = std::make_pair(leader, gap);
3186 }
3187 }
3188 if (nextLane->getVehicleMaxSpeed(&veh) < speed) {
3189 dist = veh.getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(&veh));
3190 }
3191 seen += nextLane->getLength();
3192 if (seen <= dist) {
3193 // delaying the update of arrivalTime and making it conditional to avoid possible integer overflows
3194 arrivalTime += TIME2STEPS(nextLane->getLength() / MAX2(speed, NUMERICAL_EPS));
3195 }
3196 if (!nextInternal) {
3197 view++;
3198 }
3199 } while (seen <= dist || nextLane->isInternal());
3200 return result;
3201}
3202
3203
3204MSLane*
3206 if (myLogicalPredecessorLane == nullptr) {
3208 // get only those edges which connect to this lane
3209 for (MSEdgeVector::iterator i = pred.begin(); i != pred.end();) {
3210 std::vector<IncomingLaneInfo>::const_iterator j = find_if(myIncomingLanes.begin(), myIncomingLanes.end(), edge_finder(*i));
3211 if (j == myIncomingLanes.end()) {
3212 i = pred.erase(i);
3213 } else {
3214 ++i;
3215 }
3216 }
3217 // get the lane with the "straightest" connection
3218 if (pred.size() != 0) {
3219 std::sort(pred.begin(), pred.end(), by_connections_to_sorter(&getEdge()));
3220 MSEdge* best = *pred.begin();
3221 std::vector<IncomingLaneInfo>::const_iterator j = find_if(myIncomingLanes.begin(), myIncomingLanes.end(), edge_finder(best));
3222 myLogicalPredecessorLane = j->lane;
3223 }
3224 }
3226}
3227
3228
3229const MSLane*
3231 if (isInternal()) {
3233 } else {
3234 return this;
3235 }
3236}
3237
3238
3239const MSLane*
3241 if (isInternal()) {
3243 } else {
3244 return this;
3245 }
3246}
3247
3248
3249MSLane*
3251 for (const IncomingLaneInfo& cand : myIncomingLanes) {
3252 if (&(cand.lane->getEdge()) == &fromEdge) {
3253 return cand.lane;
3254 }
3255 }
3256 return nullptr;
3257}
3258
3259
3260MSLane*
3262 if (myCanonicalPredecessorLane != nullptr) {
3264 }
3265 if (myIncomingLanes.empty()) {
3266 return nullptr;
3267 }
3268 // myCanonicalPredecessorLane has not yet been determined and there exist incoming lanes
3269 // get the lane with the priorized (or if this does not apply the "straightest") connection
3270 const auto bestLane = std::min_element(myIncomingLanes.begin(), myIncomingLanes.end(), incoming_lane_priority_sorter(this));
3271 {
3272#ifdef HAVE_FOX
3273 ScopedLocker<> lock(myLeaderInfoMutex, MSGlobals::gNumSimThreads > 1);
3274#endif
3275 myCanonicalPredecessorLane = bestLane->lane;
3276 }
3277#ifdef DEBUG_LANE_SORTER
3278 std::cout << "\nBest predecessor lane for lane '" << myID << "': '" << myCanonicalPredecessorLane->getID() << "'" << std::endl;
3279#endif
3281}
3282
3283
3284MSLane*
3286 if (myCanonicalSuccessorLane != nullptr) {
3288 }
3289 if (myLinks.empty()) {
3290 return nullptr;
3291 }
3292 // myCanonicalSuccessorLane has not yet been determined and there exist outgoing links
3293 std::vector<MSLink*> candidateLinks = myLinks;
3294 // get the lane with the priorized (or if this does not apply the "straightest") connection
3295 std::sort(candidateLinks.begin(), candidateLinks.end(), outgoing_lane_priority_sorter(this));
3296 MSLane* best = (*candidateLinks.begin())->getViaLaneOrLane();
3297#ifdef DEBUG_LANE_SORTER
3298 std::cout << "\nBest successor lane for lane '" << myID << "': '" << best->getID() << "'" << std::endl;
3299#endif
3302}
3303
3304
3307 const MSLane* const pred = getLogicalPredecessorLane();
3308 if (pred == nullptr) {
3309 return LINKSTATE_DEADEND;
3310 } else {
3311 return pred->getLinkTo(this)->getState();
3312 }
3313}
3314
3315
3316const std::vector<std::pair<const MSLane*, const MSEdge*> >
3318 std::vector<std::pair<const MSLane*, const MSEdge*> > result;
3319 for (const MSLink* link : myLinks) {
3320 assert(link->getLane() != nullptr);
3321 result.push_back(std::make_pair(link->getLane(), link->getViaLane() == nullptr ? nullptr : &link->getViaLane()->getEdge()));
3322 }
3323 return result;
3324}
3325
3326std::vector<const MSLane*>
3328 std::vector<const MSLane*> result = {};
3329 for (std::map<MSEdge*, std::vector<MSLane*> >::const_iterator it = myApproachingLanes.begin(); it != myApproachingLanes.end(); ++it) {
3330 for (std::vector<MSLane*>::const_iterator it_lane = (*it).second.begin(); it_lane != (*it).second.end(); ++it_lane) {
3331 if (!((*it_lane)->isInternal())) {
3332 result.push_back(*it_lane);
3333 }
3334 }
3335 }
3336 return result;
3337}
3338
3339
3340void
3345
3346
3347void
3352
3353
3354int
3356 for (std::vector<MSLink*>::const_iterator i = myLinks.begin(); i != myLinks.end(); ++i) {
3357 if ((*i)->getLane()->getEdge().isCrossing()) {
3358 return (int)(i - myLinks.begin());
3359 }
3360 }
3361 return -1;
3362}
3363
3364// ------------ Current state retrieval
3365double
3367 double sum = 0;
3368 if (myPartialVehicles.size() > 0) {
3369 const MSLane* bidi = getBidiLane();
3370 for (MSVehicle* cand : myPartialVehicles) {
3371 if (MSGlobals::gSublane && cand->getLaneChangeModel().getShadowLane() == this) {
3372 continue;
3373 }
3374 if (cand->getLane() == bidi) {
3375 sum += (brutto ? cand->getVehicleType().getLengthWithGap() : cand->getVehicleType().getLength());
3376 } else {
3377 sum += myLength - cand->getBackPositionOnLane(this);
3378 }
3379 }
3380 }
3381 return sum;
3382}
3383
3384double
3387 double fractions = getFractionalVehicleLength(true);
3388 if (myVehicles.size() != 0) {
3389 MSVehicle* lastVeh = myVehicles.front();
3390 if (lastVeh->getPositionOnLane() < lastVeh->getVehicleType().getLength()) {
3391 fractions -= (lastVeh->getVehicleType().getLength() - lastVeh->getPositionOnLane());
3392 }
3393 }
3395 return MIN2(1., (myBruttoVehicleLengthSum + fractions) / myLength);
3396}
3397
3398
3399double
3402 double fractions = getFractionalVehicleLength(false);
3403 if (myVehicles.size() != 0) {
3404 MSVehicle* lastVeh = myVehicles.front();
3405 if (lastVeh->getPositionOnLane() < lastVeh->getVehicleType().getLength()) {
3406 fractions -= (lastVeh->getVehicleType().getLength() - lastVeh->getPositionOnLane());
3407 }
3408 }
3410 return (myNettoVehicleLengthSum + fractions) / myLength;
3411}
3412
3413
3414double
3416 if (myVehicles.size() == 0) {
3417 return 0;
3418 }
3419 double wtime = 0;
3420 for (VehCont::const_iterator i = myVehicles.begin(); i != myVehicles.end(); ++i) {
3421 wtime += (*i)->getWaitingSeconds();
3422 }
3423 return wtime;
3424}
3425
3426
3427double
3429 if (myVehicles.size() == 0) {
3430 return myMaxSpeed;
3431 }
3432 double v = 0;
3433 int numVehs = 0;
3434 for (const MSVehicle* const veh : getVehiclesSecure()) {
3435 if (!veh->isStopped() || !myEdge->hasLaneChanger()) {
3436 v += veh->getSpeed();
3437 numVehs++;
3438 }
3439 }
3441 if (numVehs == 0) {
3442 return myMaxSpeed;
3443 }
3444 return v / numVehs;
3445}
3446
3447
3448double
3450 // @note: redundant code with getMeanSpeed to avoid extra checks in a function that is called very often
3451 if (myVehicles.size() == 0) {
3452 return myMaxSpeed;
3453 }
3454 double v = 0;
3455 int numBikes = 0;
3456 for (MSVehicle* veh : getVehiclesSecure()) {
3457 if (veh->getVClass() == SVC_BICYCLE) {
3458 v += veh->getSpeed();
3459 numBikes++;
3460 }
3461 }
3462 double ret;
3463 if (numBikes > 0) {
3464 ret = v / (double) myVehicles.size();
3465 } else {
3466 ret = myMaxSpeed;
3467 }
3469 return ret;
3470}
3471
3472
3473double
3475 double ret = 0;
3476 const MSLane::VehCont& vehs = getVehiclesSecure();
3477 if (vehs.size() == 0) {
3479 return 0;
3480 }
3481 for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
3482 double sv = (*i)->getHarmonoise_NoiseEmissions();
3483 ret += (double) pow(10., (sv / 10.));
3484 }
3486 return HelpersHarmonoise::sum(ret);
3487}
3488
3489
3490int
3492 const double pos1 = v1->getBackPositionOnLane(myLane);
3493 const double pos2 = v2->getBackPositionOnLane(myLane);
3494 if (pos1 != pos2) {
3495 return pos1 > pos2;
3496 } else {
3497 return v1->getNumericalID() > v2->getNumericalID();
3498 }
3499}
3500
3501
3502int
3504 const double pos1 = v1->getBackPositionOnLane(myLane);
3505 const double pos2 = v2->getBackPositionOnLane(myLane);
3506 if (pos1 != pos2) {
3507 return pos1 < pos2;
3508 } else {
3510 }
3511}
3512
3513
3515 myEdge(e),
3516 myLaneDir(e->getLanes()[0]->getShape().angleAt2D(0)) {
3517}
3518
3519
3520int
3521MSLane::by_connections_to_sorter::operator()(const MSEdge* const e1, const MSEdge* const e2) const {
3522// std::cout << "\nby_connections_to_sorter()";
3523
3524 const std::vector<MSLane*>* ae1 = e1->allowedLanes(*myEdge);
3525 const std::vector<MSLane*>* ae2 = e2->allowedLanes(*myEdge);
3526 double s1 = 0;
3527 if (ae1 != nullptr && ae1->size() != 0) {
3528// std::cout << "\nsize 1 = " << ae1->size()
3529// << " anglediff 1 = " << fabs(GeomHelper::angleDiff((*ae1)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.
3530// << "\nallowed lanes: ";
3531// for (std::vector<MSLane*>::const_iterator j = ae1->begin(); j != ae1->end(); ++j){
3532// std::cout << "\n" << (*j)->getID();
3533// }
3534 s1 = (double) ae1->size() + fabs(GeomHelper::angleDiff((*ae1)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.;
3535 }
3536 double s2 = 0;
3537 if (ae2 != nullptr && ae2->size() != 0) {
3538// std::cout << "\nsize 2 = " << ae2->size()
3539// << " anglediff 2 = " << fabs(GeomHelper::angleDiff((*ae2)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.
3540// << "\nallowed lanes: ";
3541// for (std::vector<MSLane*>::const_iterator j = ae2->begin(); j != ae2->end(); ++j){
3542// std::cout << "\n" << (*j)->getID();
3543// }
3544 s2 = (double) ae2->size() + fabs(GeomHelper::angleDiff((*ae2)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.;
3545 }
3546
3547// std::cout << "\ne1 = " << e1->getID() << " e2 = " << e2->getID()
3548// << "\ns1 = " << s1 << " s2 = " << s2
3549// << std::endl;
3550
3551 return s1 < s2;
3552}
3553
3554
3556 myLane(targetLane),
3557 myLaneDir(targetLane->getShape().angleAt2D(0)) {}
3558
3559int
3561 const MSLane* noninternal1 = laneInfo1.lane;
3562 while (noninternal1->isInternal()) {
3563 assert(noninternal1->getIncomingLanes().size() == 1);
3564 noninternal1 = noninternal1->getIncomingLanes()[0].lane;
3565 }
3566 MSLane* noninternal2 = laneInfo2.lane;
3567 while (noninternal2->isInternal()) {
3568 assert(noninternal2->getIncomingLanes().size() == 1);
3569 noninternal2 = noninternal2->getIncomingLanes()[0].lane;
3570 }
3571
3572 const MSLink* link1 = noninternal1->getLinkTo(myLane);
3573 const MSLink* link2 = noninternal2->getLinkTo(myLane);
3574
3575#ifdef DEBUG_LANE_SORTER
3576 std::cout << "\nincoming_lane_priority sorter()\n"
3577 << "noninternal predecessor for lane '" << laneInfo1.lane->getID()
3578 << "': '" << noninternal1->getID() << "'\n"
3579 << "noninternal predecessor for lane '" << laneInfo2.lane->getID()
3580 << "': '" << noninternal2->getID() << "'\n";
3581#endif
3582
3583 assert(laneInfo1.lane->isInternal() || link1 == laneInfo1.viaLink);
3584 assert(link1 != 0);
3585 assert(link2 != 0);
3586
3587 // check priority between links
3588 bool priorized1 = true;
3589 bool priorized2 = true;
3590
3591#ifdef DEBUG_LANE_SORTER
3592 std::cout << "FoeLinks of '" << noninternal1->getID() << "'" << std::endl;
3593#endif
3594 for (const MSLink* const foeLink : link1->getFoeLinks()) {
3595#ifdef DEBUG_LANE_SORTER
3596 std::cout << foeLink->getLaneBefore()->getID() << std::endl;
3597#endif
3598 if (foeLink == link2) {
3599 priorized1 = false;
3600 break;
3601 }
3602 }
3603
3604#ifdef DEBUG_LANE_SORTER
3605 std::cout << "FoeLinks of '" << noninternal2->getID() << "'" << std::endl;
3606#endif
3607 for (const MSLink* const foeLink : link2->getFoeLinks()) {
3608#ifdef DEBUG_LANE_SORTER
3609 std::cout << foeLink->getLaneBefore()->getID() << std::endl;
3610#endif
3611 // either link1 is priorized, or it should not appear in link2's foes
3612 if (foeLink == link1) {
3613 priorized2 = false;
3614 break;
3615 }
3616 }
3617 // if one link is subordinate, the other must be priorized (except for
3618 // traffic lights where mutual response is permitted to handle stuck-on-red
3619 // situation)
3620 if (priorized1 != priorized2) {
3621 return priorized1;
3622 }
3623
3624 // both are priorized, compare angle difference
3625 double d1 = fabs(GeomHelper::angleDiff(noninternal1->getShape().angleAt2D(0), myLaneDir));
3626 double d2 = fabs(GeomHelper::angleDiff(noninternal2->getShape().angleAt2D(0), myLaneDir));
3627
3628 return d2 > d1;
3629}
3630
3631
3632
3634 myLaneDir(sourceLane->getShape().angleAt2D(0)) {}
3635
3636int
3638 const MSLane* target1 = link1->getLane();
3639 const MSLane* target2 = link2->getLane();
3640 if (target2 == nullptr) {
3641 return true;
3642 }
3643 if (target1 == nullptr) {
3644 return false;
3645 }
3646
3647#ifdef DEBUG_LANE_SORTER
3648 std::cout << "\noutgoing_lane_priority sorter()\n"
3649 << "noninternal successors for lane '" << myLane->getID()
3650 << "': '" << target1->getID() << "' and "
3651 << "'" << target2->getID() << "'\n";
3652#endif
3653
3654 // priority of targets
3655 int priority1 = target1->getEdge().getPriority();
3656 int priority2 = target2->getEdge().getPriority();
3657
3658 if (priority1 != priority2) {
3659 return priority1 > priority2;
3660 }
3661
3662 // if priority of targets coincides, use angle difference
3663
3664 // both are priorized, compare angle difference
3665 double d1 = fabs(GeomHelper::angleDiff(target1->getShape().angleAt2D(0), myLaneDir));
3666 double d2 = fabs(GeomHelper::angleDiff(target2->getShape().angleAt2D(0), myLaneDir));
3667
3668 return d2 > d1;
3669}
3670
3671void
3675
3676
3677void
3681
3682bool
3684 for (const MSLink* link : myLinks) {
3685 if (link->getApproaching().size() > 0) {
3686 return true;
3687 }
3688 }
3689 return false;
3690}
3691
3692void
3694 const bool toRailJunction = myLinks.size() > 0 && (
3697 const bool hasVehicles = myVehicles.size() > 0;
3698 if (hasVehicles || (toRailJunction && hasApproaching())) {
3701 if (hasVehicles) {
3704 out.closeTag();
3705 }
3706 if (toRailJunction) {
3707 for (const MSLink* link : myLinks) {
3708 if (link->getApproaching().size() > 0) {
3710 out.writeAttr(SUMO_ATTR_TO, link->getViaLaneOrLane()->getID());
3711 for (auto item : link->getApproaching()) {
3713 out.writeAttr(SUMO_ATTR_ID, item.first->getID());
3714 out.writeAttr(SUMO_ATTR_ARRIVALTIME, item.second.arrivalTime);
3715 out.writeAttr(SUMO_ATTR_ARRIVALSPEED, item.second.arrivalSpeed);
3716 out.writeAttr(SUMO_ATTR_DEPARTSPEED, item.second.leaveSpeed);
3717 out.writeAttr(SUMO_ATTR_REQUEST, item.second.willPass);
3718 out.writeAttr(SUMO_ATTR_ARRIVALSPEEDBRAKING, item.second.arrivalSpeedBraking);
3719 out.writeAttr(SUMO_ATTR_WAITINGTIME, item.second.waitingTime);
3720 out.writeAttr(SUMO_ATTR_DISTANCE, item.second.dist);
3721 if (item.second.latOffset != 0) {
3722 out.writeAttr(SUMO_ATTR_POSITION_LAT, item.second.latOffset);
3723 }
3724 out.closeTag();
3725 }
3726 out.closeTag();
3727 }
3728 }
3729 }
3730 out.closeTag();
3731 }
3732}
3733
3734void
3736 myVehicles.clear();
3737 myParkingVehicles.clear();
3738 myPartialVehicles.clear();
3739 myManeuverReservations.clear();
3746 for (MSLink* link : myLinks) {
3747 link->clearState();
3748 }
3749}
3750
3751void
3752MSLane::loadState(const std::vector<SUMOVehicle*>& vehs) {
3753 for (SUMOVehicle* veh : vehs) {
3754 MSVehicle* v = dynamic_cast<MSVehicle*>(veh);
3755 v->updateBestLanes(false, this);
3756 // incorporateVehicle resets the lastActionTime (which has just been loaded from state) so we must restore it
3757 const SUMOTime lastActionTime = v->getLastActionTime();
3760 v->resetActionOffset(lastActionTime - MSNet::getInstance()->getCurrentTimeStep());
3761 v->processNextStop(v->getSpeed());
3762 }
3763}
3764
3765
3766double
3768 if (!myLaneStopOffset.isDefined()) {
3769 return 0;
3770 }
3771 if ((myLaneStopOffset.getPermissions() & veh->getVClass()) != 0) {
3772 return myLaneStopOffset.getOffset();
3773 } else {
3774 return 0;
3775 }
3776}
3777
3778
3779const StopOffset&
3783
3784
3785void
3787 myLaneStopOffset = stopOffset;
3788}
3789
3790
3792MSLane::getFollowersOnConsecutive(const MSVehicle* ego, double backOffset,
3793 bool allSublanes, double searchDist, MinorLinkMode mLinkMode) const {
3794 assert(ego != 0);
3795 // get the follower vehicle on the lane to change to
3796 const double egoPos = backOffset + ego->getVehicleType().getLength();
3797 const double egoLatDist = ego->getLane()->getRightSideOnEdge() - getRightSideOnEdge();
3798 const bool getOppositeLeaders = ((ego->getLaneChangeModel().isOpposite() && ego->getLane() == this)
3799 || (!ego->getLaneChangeModel().isOpposite() && &ego->getLane()->getEdge() != &getEdge()));
3800#ifdef DEBUG_CONTEXT
3801 if (DEBUG_COND2(ego)) {
3802 std::cout << SIMTIME << " getFollowers lane=" << getID() << " ego=" << ego->getID()
3803 << " backOffset=" << backOffset << " pos=" << egoPos
3804 << " allSub=" << allSublanes << " searchDist=" << searchDist << " ignoreMinor=" << mLinkMode
3805 << " egoLatDist=" << egoLatDist
3806 << " getOppositeLeaders=" << getOppositeLeaders
3807 << "\n";
3808 }
3809#endif
3810 MSCriticalFollowerDistanceInfo result(myWidth, allSublanes ? nullptr : ego, allSublanes ? 0 : egoLatDist, getOppositeLeaders);
3811 if (MSGlobals::gLateralResolution > 0 && egoLatDist == 0) {
3812 // check whether ego is outside lane bounds far enough so that another vehicle might
3813 // be between itself and the first "actual" sublane
3814 // shift the offset so that we "see" this vehicle
3819 }
3820#ifdef DEBUG_CONTEXT
3821 if (DEBUG_COND2(ego)) {
3822 std::cout << SIMTIME << " getFollowers lane=" << getID() << " ego=" << ego->getID()
3823 << " egoPosLat=" << ego->getLateralPositionOnLane()
3824 << " egoLatDist=" << ego->getLane()->getRightSideOnEdge() - getRightSideOnEdge()
3825 << " extraOffset=" << result.getSublaneOffset()
3826 << "\n";
3827 }
3828#endif
3829 }
3831 for (AnyVehicleIterator last = anyVehiclesBegin(); last != anyVehiclesEnd(); ++last) {
3832 const MSVehicle* veh = *last;
3833#ifdef DEBUG_CONTEXT
3834 if (DEBUG_COND2(ego)) {
3835 std::cout << " veh=" << veh->getID() << " lane=" << veh->getLane()->getID() << " pos=" << veh->getPositionOnLane(this) << "\n";
3836 }
3837#endif
3838 if (veh != ego && veh->getPositionOnLane(this) < egoPos) {
3839 //const double latOffset = veh->getLane()->getRightSideOnEdge() - getRightSideOnEdge();
3840 const double latOffset = veh->getLatOffset(this);
3841 double dist = backOffset - veh->getPositionOnLane(this) - veh->getVehicleType().getMinGap();
3842 if (veh->isBidiOn(this)) {
3843 dist -= veh->getLength();
3844 }
3845 result.addFollower(veh, ego, dist, latOffset);
3846#ifdef DEBUG_CONTEXT
3847 if (DEBUG_COND2(ego)) {
3848 std::cout << " (1) added veh=" << veh->getID() << " latOffset=" << latOffset << " result=" << result.toString() << "\n";
3849 }
3850#endif
3851 }
3852 }
3853#ifdef DEBUG_CONTEXT
3854 if (DEBUG_COND2(ego)) {
3855 std::cout << " result.numFreeSublanes=" << result.numFreeSublanes() << "\n";
3856 }
3857#endif
3858 if (result.numFreeSublanes() > 0) {
3859 // do a tree search among all follower lanes and check for the most
3860 // important vehicle (the one requiring the largest reargap)
3861 // to get a safe bound on the necessary search depth, we need to consider the maximum speed and minimum
3862 // deceleration of potential follower vehicles
3863 if (searchDist == -1) {
3864 searchDist = getMaximumBrakeDist() - backOffset;
3865#ifdef DEBUG_CONTEXT
3866 if (DEBUG_COND2(ego)) {
3867 std::cout << " computed searchDist=" << searchDist << "\n";
3868 }
3869#endif
3870 }
3871 std::set<const MSEdge*> egoFurther;
3872 for (MSLane* further : ego->getFurtherLanes()) {
3873 egoFurther.insert(&further->getEdge());
3874 }
3875 if (ego->getPositionOnLane() < ego->getVehicleType().getLength() && egoFurther.size() == 0
3876 && ego->getLane()->getLogicalPredecessorLane() != nullptr) {
3877 // on insertion
3878 egoFurther.insert(&ego->getLane()->getLogicalPredecessorLane()->getEdge());
3879 }
3880
3881 // avoid loops
3882 std::set<const MSLane*> visited(myEdge->getLanes().begin(), myEdge->getLanes().end());
3883 if (myEdge->getBidiEdge() != nullptr) {
3884 visited.insert(myEdge->getBidiEdge()->getLanes().begin(), myEdge->getBidiEdge()->getLanes().end());
3885 }
3886 std::vector<MSLane::IncomingLaneInfo> newFound;
3887 std::vector<MSLane::IncomingLaneInfo> toExamine = myIncomingLanes;
3888 while (toExamine.size() != 0) {
3889 for (std::vector<MSLane::IncomingLaneInfo>::iterator it = toExamine.begin(); it != toExamine.end(); ++it) {
3890 MSLane* next = (*it).lane;
3891 searchDist = MAX2(searchDist, next->getMaximumBrakeDist() - backOffset);
3892 MSLeaderInfo first = next->getFirstVehicleInformation(nullptr, 0, false, std::numeric_limits<double>::max(), false);
3893 MSLeaderInfo firstFront = next->getFirstVehicleInformation(nullptr, 0, true);
3894#ifdef DEBUG_CONTEXT
3895 if (DEBUG_COND2(ego)) {
3896 std::cout << " next=" << next->getID() << " seen=" << (*it).length << " first=" << first.toString() << " firstFront=" << firstFront.toString() << " backOffset=" << backOffset << "\n";
3897 gDebugFlag1 = true; // for calling getLeaderInfo
3898 }
3899#endif
3900 if (backOffset + (*it).length - next->getLength() < 0
3901 && egoFurther.count(&next->getEdge()) != 0
3902 ) {
3903 // check for junction foes that would interfere with lane changing
3904 // @note: we are passing the back of ego as its front position so
3905 // we need to add this back to the returned gap
3906 const MSLink::LinkLeaders linkLeaders = (*it).viaLink->getLeaderInfo(ego, -backOffset);
3907 for (const auto& ll : linkLeaders) {
3908 if (ll.vehAndGap.first != nullptr) {
3909 const bool bidiFoe = (*it).viaLink->getLane() == ll.vehAndGap.first->getLane()->getNormalPredecessorLane()->getBidiLane();
3910 const bool egoIsLeader = !bidiFoe && ll.vehAndGap.first->isLeader((*it).viaLink, ego, ll.vehAndGap.second);
3911 // if ego is leader the returned gap still assumes that ego follows the leader
3912 // if the foe vehicle follows ego we need to deduce that gap
3913 const double gap = (egoIsLeader
3914 ? -ll.vehAndGap.second - ll.vehAndGap.first->getVehicleType().getLengthWithGap() - ego->getVehicleType().getMinGap()
3915 : ll.vehAndGap.second + ego->getVehicleType().getLength());
3916 result.addFollower(ll.vehAndGap.first, ego, gap);
3917#ifdef DEBUG_CONTEXT
3918 if (DEBUG_COND2(ego)) {
3919 std::cout << SIMTIME << " ego=" << ego->getID() << " link=" << (*it).viaLink->getViaLaneOrLane()->getID()
3920 << " (3) added veh=" << Named::getIDSecure(ll.vehAndGap.first)
3921 << " gap=" << ll.vehAndGap.second << " dtC=" << ll.distToCrossing
3922 << " bidiFoe=" << bidiFoe
3923 << " egoIsLeader=" << egoIsLeader << " gap2=" << gap
3924 << "\n";
3925 }
3926#endif
3927 }
3928 }
3929 }
3930#ifdef DEBUG_CONTEXT
3931 if (DEBUG_COND2(ego)) {
3932 gDebugFlag1 = false;
3933 }
3934#endif
3935
3936 for (int i = 0; i < first.numSublanes(); ++i) {
3937 const MSVehicle* v = first[i] == ego ? firstFront[i] : first[i];
3938 double agap = 0;
3939
3940 if (v != nullptr && v != ego) {
3941 if (!v->isFrontOnLane(next)) {
3942 // the front of v is already on divergent trajectory from the ego vehicle
3943 // for which this method is called (in the context of MSLaneChanger).
3944 // Therefore, technically v is not a follower but only an obstruction and
3945 // the gap is not between the front of v and the back of ego
3946 // but rather between the flank of v and the back of ego.
3947 agap = (*it).length - next->getLength() + backOffset;
3949 // ego should have left the intersection still occupied by v
3950 agap -= v->getVehicleType().getMinGap();
3951 }
3952#ifdef DEBUG_CONTEXT
3953 if (DEBUG_COND2(ego)) {
3954 std::cout << " agap1=" << agap << "\n";
3955 }
3956#endif
3957 const bool differentEdge = &v->getLane()->getEdge() != &ego->getLane()->getEdge();
3958 if (agap > 0 && differentEdge) {
3959 // Only if ego overlaps we treat v as if it were a real follower
3960 // Otherwise we ignore it and look for another follower
3961 if (!getOppositeLeaders) {
3962 // even if the vehicle is not a real
3963 // follower, it still forms a real
3964 // obstruction in opposite direction driving
3965 v = firstFront[i];
3966 if (v != nullptr && v != ego) {
3967 agap = (*it).length - v->getPositionOnLane() + backOffset - v->getVehicleType().getMinGap();
3968 } else {
3969 v = nullptr;
3970 }
3971 }
3972 } else if (differentEdge && result.hasVehicle(v)) {
3973 // ignore this vehicle as it was already seen on another lane
3974 agap = 0;
3975 }
3976 } else {
3977 if (next->getBidiLane() != nullptr && v->isBidiOn(next)) {
3978 agap = v->getPositionOnLane() + backOffset - v->getVehicleType().getLengthWithGap();
3979 } else {
3980 agap = (*it).length - v->getPositionOnLane() + backOffset - v->getVehicleType().getMinGap();
3981 }
3982 if (!(*it).viaLink->havePriority() && egoFurther.count(&(*it).lane->getEdge()) == 0
3983 && ego->isOnRoad() // during insertion, this can lead to collisions because ego's further lanes are not set (see #3053)
3984 && !ego->getLaneChangeModel().isOpposite()
3986 ) {
3987 // if v is stopped on a minor side road it should not block lane changing
3988 agap = MAX2(agap, 0.0);
3989 }
3990 }
3991 result.addFollower(v, ego, agap, 0, i);
3992#ifdef DEBUG_CONTEXT
3993 if (DEBUG_COND2(ego)) {
3994 std::cout << " (2) added veh=" << Named::getIDSecure(v) << " agap=" << agap << " next=" << next->getID() << " result=" << result.toString() << "\n";
3995 }
3996#endif
3997 }
3998 }
3999 if ((*it).length < searchDist) {
4000 const std::vector<MSLane::IncomingLaneInfo>& followers = next->getIncomingLanes();
4001 for (std::vector<MSLane::IncomingLaneInfo>::const_iterator j = followers.begin(); j != followers.end(); ++j) {
4002 if (visited.find((*j).lane) == visited.end() && (((*j).viaLink->havePriority() && !(*j).viaLink->isTurnaround())
4003 || mLinkMode == MinorLinkMode::FOLLOW_ALWAYS
4004 || (mLinkMode == MinorLinkMode::FOLLOW_ONCOMING && (*j).viaLink->getDirection() == LinkDirection::STRAIGHT))) {
4005 visited.insert((*j).lane);
4007 ili.lane = (*j).lane;
4008 ili.length = (*j).length + (*it).length;
4009 ili.viaLink = (*j).viaLink;
4010 newFound.push_back(ili);
4011 }
4012 }
4013 }
4014 }
4015 toExamine.clear();
4016 swap(newFound, toExamine);
4017 }
4018 //return result;
4019
4020 }
4021 return result;
4022}
4023
4024
4025void
4026MSLane::getLeadersOnConsecutive(double dist, double seen, double speed, const MSVehicle* ego,
4027 const std::vector<MSLane*>& bestLaneConts, MSLeaderDistanceInfo& result,
4028 bool oppositeDirection) const {
4029 if (seen > dist && !(isInternal() && MSGlobals::gComputeLC)) {
4030 return;
4031 }
4032 // check partial vehicles (they might be on a different route and thus not
4033 // found when iterating along bestLaneConts)
4034 for (VehCont::const_iterator it = myPartialVehicles.begin(); it != myPartialVehicles.end(); ++it) {
4035 MSVehicle* veh = *it;
4036 if (!veh->isFrontOnLane(this)) {
4037 result.addLeader(veh, seen, veh->getLatOffset(this));
4038 } else {
4039 break;
4040 }
4041 }
4042#ifdef DEBUG_CONTEXT
4043 if (DEBUG_COND2(ego)) {
4044 gDebugFlag1 = true;
4045 }
4046#endif
4047 const MSLane* nextLane = this;
4048 int view = 1;
4049 // loop over following lanes
4050 while ((seen < dist || nextLane->isInternal()) && result.numFreeSublanes() > 0) {
4051 // get the next link used
4052 bool nextInternal = false;
4053 if (oppositeDirection) {
4054 if (view >= (int)bestLaneConts.size()) {
4055 break;
4056 }
4057 nextLane = bestLaneConts[view];
4058 } else {
4059 std::vector<MSLink*>::const_iterator link = succLinkSec(*ego, view, *nextLane, bestLaneConts);
4060 if (nextLane->isLinkEnd(link)) {
4061 break;
4062 }
4063 // check for link leaders
4064 const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(ego, seen);
4065 if (linkLeaders.size() > 0) {
4066 const MSLink::LinkLeader ll = linkLeaders[0];
4067 MSVehicle* veh = ll.vehAndGap.first;
4068 // in the context of lane changing all junction leader candidates must be respected
4069 if (veh != 0 && (ego->isLeader(*link, veh, ll.vehAndGap.second)
4072 < veh->getCarFollowModel().brakeGap(veh->getSpeed())))) {
4073#ifdef DEBUG_CONTEXT
4074 if (DEBUG_COND2(ego)) {
4075 std::cout << " linkleader=" << veh->getID() << " gap=" << ll.vehAndGap.second << " leaderOffset=" << ll.latOffset << " flags=" << ll.llFlags << "\n";
4076 }
4077#endif
4078 if (ll.sameTarget() || ll.sameSource()) {
4079 result.addLeader(veh, ll.vehAndGap.second, ll.latOffset);
4080 } else {
4081 // add link leader to all sublanes and return
4082 for (int i = 0; i < result.numSublanes(); ++i) {
4083 result.addLeader(veh, ll.vehAndGap.second, 0, i);
4084 }
4085 }
4086#ifdef DEBUG_CONTEXT
4087 gDebugFlag1 = false;
4088#endif
4089 return;
4090 } // XXX else, deal with pedestrians
4091 }
4092 nextInternal = (*link)->getViaLane() != nullptr;
4093 nextLane = (*link)->getViaLaneOrLane();
4094 if (nextLane == nullptr) {
4095 break;
4096 }
4097 }
4098
4099 MSLeaderInfo leaders = nextLane->getLastVehicleInformation(nullptr, 0, 0, false);
4100#ifdef DEBUG_CONTEXT
4101 if (DEBUG_COND2(ego)) {
4102 std::cout << SIMTIME << " getLeadersOnConsecutive lane=" << getID() << " nextLane=" << nextLane->getID() << " leaders=" << leaders.toString() << "\n";
4103 }
4104#endif
4105 // @todo check alignment issues if the lane width changes
4106 const int iMax = MIN2(leaders.numSublanes(), result.numSublanes());
4107 for (int i = 0; i < iMax; ++i) {
4108 const MSVehicle* veh = leaders[i];
4109 if (veh != nullptr) {
4110#ifdef DEBUG_CONTEXT
4111 if (DEBUG_COND2(ego)) std::cout << " lead=" << veh->getID()
4112 << " seen=" << seen
4113 << " minGap=" << ego->getVehicleType().getMinGap()
4114 << " backPos=" << veh->getBackPositionOnLane(nextLane)
4115 << " gap=" << seen - ego->getVehicleType().getMinGap() + veh->getBackPositionOnLane(nextLane)
4116 << "\n";
4117#endif
4118 result.addLeader(veh, seen - ego->getVehicleType().getMinGap() + veh->getBackPositionOnLane(nextLane), 0, i);
4119 }
4120 }
4121
4122 if (nextLane->getVehicleMaxSpeed(ego) < speed) {
4123 dist = ego->getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(ego));
4124 }
4125 seen += nextLane->getLength();
4126 if (!nextInternal) {
4127 view++;
4128 }
4129 }
4130#ifdef DEBUG_CONTEXT
4131 gDebugFlag1 = false;
4132#endif
4133}
4134
4135
4136void
4137MSLane::addLeaders(const MSVehicle* vehicle, double vehPos, MSLeaderDistanceInfo& result, bool opposite) {
4138 // if there are vehicles on the target lane with the same position as ego,
4139 // they may not have been added to 'ahead' yet
4140#ifdef DEBUG_SURROUNDING
4141 if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4142 std::cout << " addLeaders lane=" << getID() << " veh=" << vehicle->getID() << " vehPos=" << vehPos << " opposite=" << opposite << "\n";
4143 }
4144#endif
4145 const MSLeaderInfo& aheadSamePos = getLastVehicleInformation(nullptr, 0, vehPos, false);
4146 for (int i = 0; i < aheadSamePos.numSublanes(); ++i) {
4147 const MSVehicle* veh = aheadSamePos[i];
4148 if (veh != nullptr && veh != vehicle) {
4149 const double gap = veh->getBackPositionOnLane(this) - vehPos - vehicle->getVehicleType().getMinGap();
4150#ifdef DEBUG_SURROUNDING
4151 if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4152 std::cout << " further lead=" << veh->getID() << " leadBack=" << veh->getBackPositionOnLane(this) << " gap=" << gap << "\n";
4153 }
4154#endif
4155 result.addLeader(veh, gap, 0, i);
4156 }
4157 }
4158
4159 if (result.numFreeSublanes() > 0) {
4160 double seen = vehicle->getLane()->getLength() - vehPos;
4161 double speed = vehicle->getSpeed();
4162 // leader vehicle could be link leader on the next junction
4163 double dist = MAX2(vehicle->getCarFollowModel().brakeGap(speed), 10.0) + vehicle->getVehicleType().getMinGap();
4164 if (getBidiLane() != nullptr) {
4165 dist = MAX2(dist, myMaxSpeed * 20);
4166 }
4167 // check for link leaders when on internal
4168 if (seen > dist && !(isInternal() && MSGlobals::gComputeLC)) {
4169#ifdef DEBUG_SURROUNDING
4170 if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4171 std::cout << " aborting forward search. dist=" << dist << " seen=" << seen << "\n";
4172 }
4173#endif
4174 return;
4175 }
4176#ifdef DEBUG_SURROUNDING
4177 if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4178 std::cout << " add consecutive before=" << result.toString() << " seen=" << seen << " dist=" << dist;
4179 }
4180#endif
4181 if (opposite) {
4182 const std::vector<MSLane*> bestLaneConts = vehicle->getUpstreamOppositeLanes();
4183#ifdef DEBUG_SURROUNDING
4184 if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4185 std::cout << " upstreamOpposite=" << toString(bestLaneConts);
4186 }
4187#endif
4188 getLeadersOnConsecutive(dist, seen, speed, vehicle, bestLaneConts, result, opposite);
4189 } else {
4190 const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation(this);
4191 getLeadersOnConsecutive(dist, seen, speed, vehicle, bestLaneConts, result);
4192 }
4193#ifdef DEBUG_SURROUNDING
4194 if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4195 std::cout << " after=" << result.toString() << "\n";
4196 }
4197#endif
4198 }
4199}
4200
4201
4202MSVehicle*
4204 for (VehCont::const_reverse_iterator i = myPartialVehicles.rbegin(); i != myPartialVehicles.rend(); ++i) {
4205 MSVehicle* veh = *i;
4206 if (veh->isFrontOnLane(this)
4207 && veh != ego
4208 && veh->getPositionOnLane() <= ego->getPositionOnLane()) {
4209#ifdef DEBUG_CONTEXT
4210 if (DEBUG_COND2(ego)) {
4211 std::cout << SIMTIME << " getPartialBehind lane=" << getID() << " ego=" << ego->getID() << " found=" << veh->getID() << "\n";
4212 }
4213#endif
4214 return veh;
4215 }
4216 }
4217#ifdef DEBUG_CONTEXT
4218 if (DEBUG_COND2(ego)) {
4219 std::cout << SIMTIME << " getPartialBehind lane=" << getID() << " ego=" << ego->getID() << " nothing found. partials=" << toString(myPartialVehicles) << "\n";
4220 }
4221#endif
4222 return nullptr;
4223}
4224
4227 MSLeaderInfo result(myWidth);
4228 for (VehCont::const_iterator it = myPartialVehicles.begin(); it != myPartialVehicles.end(); ++it) {
4229 MSVehicle* veh = *it;
4230 if (!veh->isFrontOnLane(this)) {
4231 result.addLeader(veh, false, veh->getLatOffset(this));
4232 } else {
4233 break;
4234 }
4235 }
4236 return result;
4237}
4238
4239
4240std::set<MSVehicle*>
4241MSLane::getSurroundingVehicles(double startPos, double downstreamDist, double upstreamDist, std::shared_ptr<LaneCoverageInfo> checkedLanes) const {
4242 assert(checkedLanes != nullptr);
4243 if (checkedLanes->find(this) != checkedLanes->end()) {
4244#ifdef DEBUG_SURROUNDING
4245 std::cout << "Skipping previously scanned lane: " << getID() << std::endl;
4246#endif
4247 return std::set<MSVehicle*>();
4248 } else {
4249 // Add this lane's coverage to the lane coverage info
4250 (*checkedLanes)[this] = std::make_pair(MAX2(0.0, startPos - upstreamDist), MIN2(startPos + downstreamDist, getLength()));
4251 }
4252#ifdef DEBUG_SURROUNDING
4253 std::cout << "Scanning on lane " << myID << "(downstr. " << downstreamDist << ", upstr. " << upstreamDist << ", startPos " << startPos << "): " << std::endl;
4254#endif
4255 std::set<MSVehicle*> foundVehicles = getVehiclesInRange(MAX2(0., startPos - upstreamDist), MIN2(myLength, startPos + downstreamDist));
4256 if (startPos < upstreamDist) {
4257 // scan incoming lanes
4258 for (const IncomingLaneInfo& incomingInfo : getIncomingLanes()) {
4259 MSLane* incoming = incomingInfo.lane;
4260#ifdef DEBUG_SURROUNDING
4261 std::cout << "Checking on incoming: " << incoming->getID() << std::endl;
4262 if (checkedLanes->find(incoming) != checkedLanes->end()) {
4263 std::cout << "Skipping previous: " << incoming->getID() << std::endl;
4264 }
4265#endif
4266 std::set<MSVehicle*> newVehs = incoming->getSurroundingVehicles(incoming->getLength(), 0.0, upstreamDist - startPos, checkedLanes);
4267 foundVehicles.insert(newVehs.begin(), newVehs.end());
4268 }
4269 }
4270
4271 if (getLength() < startPos + downstreamDist) {
4272 // scan successive lanes
4273 const std::vector<MSLink*>& lc = getLinkCont();
4274 for (MSLink* l : lc) {
4275#ifdef DEBUG_SURROUNDING
4276 std::cout << "Checking on outgoing: " << l->getViaLaneOrLane()->getID() << std::endl;
4277#endif
4278 std::set<MSVehicle*> newVehs = l->getViaLaneOrLane()->getSurroundingVehicles(0.0, downstreamDist - (myLength - startPos), upstreamDist, checkedLanes);
4279 foundVehicles.insert(newVehs.begin(), newVehs.end());
4280 }
4281 }
4282#ifdef DEBUG_SURROUNDING
4283 std::cout << "On lane (2) " << myID << ": \nFound vehicles: " << std::endl;
4284 for (MSVehicle* v : foundVehicles) {
4285 std::cout << v->getID() << " pos = " << v->getPositionOnLane() << std::endl;
4286 }
4287#endif
4288 return foundVehicles;
4289}
4290
4291
4292std::set<MSVehicle*>
4293MSLane::getVehiclesInRange(const double a, const double b) const {
4294 std::set<MSVehicle*> res;
4295 const VehCont& vehs = getVehiclesSecure();
4296
4297 if (!vehs.empty()) {
4298 for (MSVehicle* const veh : vehs) {
4299 if (veh->getPositionOnLane() >= a) {
4300 if (veh->getBackPositionOnLane() > b) {
4301 break;
4302 }
4303 res.insert(veh);
4304 }
4305 }
4306 }
4308 return res;
4309}
4310
4311
4312std::vector<const MSJunction*>
4313MSLane::getUpcomingJunctions(double pos, double range, const std::vector<MSLane*>& contLanes) const {
4314 // set of upcoming junctions and the corresponding conflict links
4315 std::vector<const MSJunction*> junctions;
4316 for (auto l : getUpcomingLinks(pos, range, contLanes)) {
4317 junctions.insert(junctions.end(), l->getJunction());
4318 }
4319 return junctions;
4320}
4321
4322
4323std::vector<const MSLink*>
4324MSLane::getUpcomingLinks(double pos, double range, const std::vector<MSLane*>& contLanes) const {
4325#ifdef DEBUG_SURROUNDING
4326 std::cout << "getUpcoming links on lane '" << getID() << "' with pos=" << pos
4327 << " range=" << range << std::endl;
4328#endif
4329 // set of upcoming junctions and the corresponding conflict links
4330 std::vector<const MSLink*> links;
4331
4332 // Currently scanned lane
4333 const MSLane* lane = this;
4334
4335 // continuation lanes for the vehicle
4336 std::vector<MSLane*>::const_iterator contLanesIt = contLanes.begin();
4337 // scanned distance so far
4338 double dist = 0.0;
4339 // link to be crossed by the vehicle
4340 const MSLink* link = nullptr;
4341 if (lane->isInternal()) {
4342 assert(*contLanesIt == nullptr); // is called with vehicle's bestLane structure
4343 link = lane->getEntryLink();
4344 links.insert(links.end(), link);
4345 dist += link->getInternalLengthsAfter();
4346 // next non-internal lane behind junction
4347 lane = link->getLane();
4348 pos = 0.0;
4349 assert(*(contLanesIt + 1) == lane);
4350 }
4351 while (++contLanesIt != contLanes.end()) {
4352 assert(!lane->isInternal());
4353 dist += lane->getLength() - pos;
4354 pos = 0.;
4355#ifdef DEBUG_SURROUNDING
4356 std::cout << "Distance until end of lane '" << lane->getID() << "' is " << dist << "." << std::endl;
4357#endif
4358 if (dist > range) {
4359 break;
4360 }
4361 link = lane->getLinkTo(*contLanesIt);
4362 if (link != nullptr) {
4363 links.insert(links.end(), link);
4364 }
4365 lane = *contLanesIt;
4366 }
4367 return links;
4368}
4369
4370
4371MSLane*
4373 return myOpposite;
4374}
4375
4376
4377MSLane*
4379 return myEdge->getLanes().back()->getOpposite();
4380}
4381
4382
4383double
4384MSLane::getOppositePos(double pos) const {
4385 return MAX2(0., myLength - pos);
4386}
4387
4388std::pair<MSVehicle* const, double>
4389MSLane::getFollower(const MSVehicle* ego, double egoPos, double dist, MinorLinkMode mLinkMode) const {
4390 for (AnyVehicleIterator first = anyVehiclesUpstreamBegin(); first != anyVehiclesUpstreamEnd(); ++first) {
4391 // XXX refactor leaderInfo to use a const vehicle all the way through the call hierarchy
4392 MSVehicle* pred = (MSVehicle*)*first;
4393#ifdef DEBUG_CONTEXT
4394 if (DEBUG_COND2(ego)) {
4395 std::cout << " getFollower lane=" << getID() << " egoPos=" << egoPos << " pred=" << pred->getID() << " predPos=" << pred->getPositionOnLane(this) << "\n";
4396 }
4397#endif
4398 if (pred != ego && pred->getPositionOnLane(this) < egoPos) {
4399 return std::pair<MSVehicle* const, double>(pred, egoPos - pred->getPositionOnLane(this) - ego->getVehicleType().getLength() - pred->getVehicleType().getMinGap());
4400 }
4401 }
4402 const double backOffset = egoPos - ego->getVehicleType().getLength();
4403 if (dist > 0 && backOffset > dist) {
4404 return std::make_pair(nullptr, -1);
4405 }
4406 const MSLeaderDistanceInfo followers = getFollowersOnConsecutive(ego, backOffset, true, dist, mLinkMode);
4407 CLeaderDist result = followers.getClosest();
4408 return std::make_pair(const_cast<MSVehicle*>(result.first), result.second);
4409}
4410
4411std::pair<MSVehicle* const, double>
4412MSLane::getOppositeLeader(const MSVehicle* ego, double dist, bool oppositeDir, MinorLinkMode mLinkMode) const {
4413#ifdef DEBUG_OPPOSITE
4414 if (DEBUG_COND2(ego)) std::cout << SIMTIME << " getOppositeLeader lane=" << getID()
4415 << " ego=" << ego->getID()
4416 << " pos=" << ego->getPositionOnLane()
4417 << " posOnOpposite=" << getOppositePos(ego->getPositionOnLane())
4418 << " dist=" << dist
4419 << " oppositeDir=" << oppositeDir
4420 << "\n";
4421#endif
4422 if (!oppositeDir) {
4423 return getLeader(ego, getOppositePos(ego->getPositionOnLane()), ego->getBestLanesContinuation(this));
4424 } else {
4425 const double egoLength = ego->getVehicleType().getLength();
4426 const double egoPos = ego->getLaneChangeModel().isOpposite() ? ego->getPositionOnLane() : getOppositePos(ego->getPositionOnLane());
4427 std::pair<MSVehicle* const, double> result = getFollower(ego, egoPos + egoLength, dist, mLinkMode);
4428 if (result.first != nullptr) {
4429 result.second -= ego->getVehicleType().getMinGap();
4430 if (result.first->getLaneChangeModel().isOpposite()) {
4431 result.second -= result.first->getVehicleType().getLength();
4432 }
4433 }
4434 return result;
4435 }
4436}
4437
4438
4439std::pair<MSVehicle* const, double>
4441#ifdef DEBUG_OPPOSITE
4442 if (DEBUG_COND2(ego)) std::cout << SIMTIME << " getOppositeFollower lane=" << getID()
4443 << " ego=" << ego->getID()
4444 << " backPos=" << ego->getBackPositionOnLane()
4445 << " posOnOpposite=" << getOppositePos(ego->getBackPositionOnLane())
4446 << "\n";
4447#endif
4448 if (ego->getLaneChangeModel().isOpposite()) {
4449 std::pair<MSVehicle* const, double> result = getFollower(ego, getOppositePos(ego->getPositionOnLane()), -1, MinorLinkMode::FOLLOW_NEVER);
4450 return result;
4451 } else {
4452 double vehPos = getOppositePos(ego->getPositionOnLane() - ego->getVehicleType().getLength());
4453 std::pair<MSVehicle*, double> result = getLeader(ego, vehPos, std::vector<MSLane*>());
4454 double dist = getMaximumBrakeDist() + getOppositePos(ego->getPositionOnLane() - getLength());
4455 MSLane* next = const_cast<MSLane*>(this);
4456 while (result.first == nullptr && dist > 0) {
4457 // cannot call getLeadersOnConsecutive because succLinkSec doesn't
4458 // uses the vehicle's route and doesn't work on the opposite side
4459 vehPos -= next->getLength();
4460 next = next->getCanonicalSuccessorLane();
4461 if (next == nullptr) {
4462 break;
4463 }
4464 dist -= next->getLength();
4465 result = next->getLeader(ego, vehPos, std::vector<MSLane*>());
4466 }
4467 if (result.first != nullptr) {
4468 if (result.first->getLaneChangeModel().isOpposite()) {
4469 result.second -= result.first->getVehicleType().getLength();
4470 } else {
4471 if (result.second > POSITION_EPS) {
4472 // follower can be safely ignored since it is going the other way
4473 return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
4474 }
4475 }
4476 }
4477 return result;
4478 }
4479}
4480
4481void
4482MSLane::initCollisionAction(const OptionsCont& oc, const std::string& option, CollisionAction& myAction) {
4483 const std::string action = oc.getString(option);
4484 if (action == "none") {
4485 myAction = COLLISION_ACTION_NONE;
4486 } else if (action == "warn") {
4487 myAction = COLLISION_ACTION_WARN;
4488 } else if (action == "teleport") {
4489 myAction = COLLISION_ACTION_TELEPORT;
4490 } else if (action == "remove") {
4491 myAction = COLLISION_ACTION_REMOVE;
4492 } else {
4493 WRITE_ERROR(TLF("Invalid % '%'.", option, action));
4494 }
4495}
4496
4497void
4499 initCollisionAction(oc, "collision.action", myCollisionAction);
4500 initCollisionAction(oc, "intermodal-collision.action", myIntermodalCollisionAction);
4501 myCheckJunctionCollisions = oc.getBool("collision.check-junctions");
4502 myCheckJunctionCollisionMinGap = oc.getFloat("collision.check-junctions.mingap");
4503 myCollisionStopTime = string2time(oc.getString("collision.stoptime"));
4504 myIntermodalCollisionStopTime = string2time(oc.getString("intermodal-collision.stoptime"));
4505 myCollisionMinGapFactor = oc.getFloat("collision.mingap-factor");
4506 myExtrapolateSubstepDepart = oc.getBool("extrapolate-departpos");
4507}
4508
4509
4510void
4511MSLane::setPermissions(SVCPermissions permissions, long long transientID) {
4512 if (transientID == CHANGE_PERMISSIONS_PERMANENT) {
4513 myPermissions = permissions;
4514 myOriginalPermissions = permissions;
4515 } else {
4516 myPermissionChanges[transientID] = permissions;
4518 }
4519}
4520
4521
4522void
4523MSLane::resetPermissions(long long transientID) {
4524 myPermissionChanges.erase(transientID);
4525 if (myPermissionChanges.empty()) {
4527 } else {
4528 // combine all permission changes
4530 for (const auto& item : myPermissionChanges) {
4531 myPermissions &= item.second;
4532 }
4533 }
4534}
4535
4536
4537bool
4539 return !myPermissionChanges.empty();
4540}
4541
4542
4543void
4545 myChangeLeft = permissions;
4546}
4547
4548
4549void
4551 myChangeRight = permissions;
4552}
4553
4554
4555bool
4557 MSNet* const net = MSNet::getInstance();
4558 return net->hasPersons() && net->getPersonControl().getMovementModel()->hasPedestrians(this);
4559}
4560
4561
4563MSLane::nextBlocking(double minPos, double minRight, double maxLeft, double stopTime, bool bidi) const {
4564 return MSNet::getInstance()->getPersonControl().getMovementModel()->nextBlocking(this, minPos, minRight, maxLeft, stopTime, bidi);
4565}
4566
4567
4568bool
4569MSLane::checkForPedestrians(const MSVehicle* aVehicle, double& speed, double& dist, double pos, bool patchSpeed) const {
4570 if (getEdge().getPersons().size() > 0 && hasPedestrians()) {
4571#ifdef DEBUG_INSERTION
4572 if (DEBUG_COND2(aVehicle)) {
4573 std::cout << SIMTIME << " check for pedestrians on lane=" << getID() << " pos=" << pos << "\n";
4574 }
4575#endif
4576 PersonDist leader = nextBlocking(pos - aVehicle->getVehicleType().getLength(),
4577 aVehicle->getRightSideOnLane(), aVehicle->getRightSideOnLane() + aVehicle->getVehicleType().getWidth(), ceil(speed / aVehicle->getCarFollowModel().getMaxDecel()));
4578 if (leader.first != 0) {
4579 const double gap = leader.second - aVehicle->getVehicleType().getLengthWithGap();
4580 const double stopSpeed = aVehicle->getCarFollowModel().stopSpeed(aVehicle, speed, gap, MSCFModel::CalcReason::FUTURE);
4581 if ((gap < 0 && (aVehicle->getInsertionChecks() & ((int)InsertionCheck::COLLISION | (int)InsertionCheck::PEDESTRIAN)) != 0)
4582 || checkFailure(aVehicle, speed, dist, stopSpeed, patchSpeed, "", InsertionCheck::PEDESTRIAN)) {
4583 // we may not drive with the given velocity - we crash into the pedestrian
4584#ifdef DEBUG_INSERTION
4585 if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
4586 << " isInsertionSuccess lane=" << getID()
4587 << " veh=" << aVehicle->getID()
4588 << " pos=" << pos
4589 << " posLat=" << aVehicle->getLateralPositionOnLane()
4590 << " patchSpeed=" << patchSpeed
4591 << " speed=" << speed
4592 << " stopSpeed=" << stopSpeed
4593 << " pedestrianLeader=" << leader.first->getID()
4594 << " failed (@796)!\n";
4595#endif
4596 return false;
4597 }
4598 }
4599 }
4600 double backLength = aVehicle->getLength() - pos;
4601 if (backLength > 0 && MSNet::getInstance()->hasPersons()) {
4602 // look upstream for pedestrian crossings
4603 const MSLane* prev = getLogicalPredecessorLane();
4604 const MSLane* cur = this;
4605 while (backLength > 0 && prev != nullptr) {
4606 const MSLink* link = prev->getLinkTo(cur);
4607 if (link->hasFoeCrossing()) {
4608 for (const MSLane* foe : link->getFoeLanes()) {
4609 if (foe->isCrossing() && (foe->hasPedestrians() ||
4610 (foe->getIncomingLanes()[0].viaLink->getApproachingPersons() != nullptr
4611 && foe->getIncomingLanes()[0].viaLink->getApproachingPersons()->size() > 0))) {
4612#ifdef DEBUG_INSERTION
4613 if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
4614 << " isInsertionSuccess lane=" << getID()
4615 << " veh=" << aVehicle->getID()
4616 << " pos=" << pos
4617 << " backCrossing=" << foe->getID()
4618 << " peds=" << joinNamedToString(foe->getEdge().getPersons(), " ")
4619 << " approaching=" << foe->getIncomingLanes()[0].viaLink->getApproachingPersons()->size()
4620 << " failed (@4550)!\n";
4621#endif
4622 return false;
4623 }
4624 }
4625 }
4626 backLength -= prev->getLength();
4627 cur = prev;
4628 prev = prev->getLogicalPredecessorLane();
4629 }
4630 }
4631 return true;
4632}
4633
4634
4635void
4637 myRNGs.clear();
4638 const int numRNGs = oc.getInt("thread-rngs");
4639 const bool random = oc.getBool("random");
4640 int seed = oc.getInt("seed");
4641 myRNGs.reserve(numRNGs); // this is needed for stable pointers on debugging
4642 for (int i = 0; i < numRNGs; i++) {
4643 myRNGs.push_back(SumoRNG("lanes_" + toString(i)));
4644 RandHelper::initRand(&myRNGs.back(), random, seed++);
4645 }
4646}
4647
4648void
4650 for (int i = 0; i < getNumRNGs(); i++) {
4652 out.writeAttr(SUMO_ATTR_INDEX, i);
4654 out.closeTag();
4655 }
4656}
4657
4658void
4659MSLane::loadRNGState(int index, const std::string& state) {
4660 if (index >= getNumRNGs()) {
4661 throw ProcessError(TLF("State was saved with more than % threads. Change the number of threads or do not load RNG state", toString(getNumRNGs())));
4662 }
4663 RandHelper::loadState(state, &myRNGs[index]);
4664}
4665
4666
4667MSLane*
4669 return myBidiLane;
4670}
4671
4672
4673bool
4676 myLinks.front()->getFoeLanes().size() > 0
4677 || myLinks.front()->getWalkingAreaFoe() != nullptr
4678 || myLinks.front()->getWalkingAreaFoeExit() != nullptr);
4679}
4680
4681
4682double
4683MSLane::getSpaceTillLastStanding(const MSVehicle* ego, bool& foundStopped) const {
4685 double lengths = 0;
4686 for (const MSVehicle* last : myVehicles) {
4687 if (last->getSpeed() < SUMO_const_haltingSpeed && !last->getLane()->getEdge().isRoundabout()
4688 && last != ego
4689 // @todo recheck
4690 && last->isFrontOnLane(this)) {
4691 foundStopped = true;
4692 const double lastBrakeGap = last->getCarFollowModel().brakeGap(last->getSpeed());
4693 const double ret = last->getBackPositionOnLane() + lastBrakeGap - lengths;
4694 return ret;
4695 }
4696 if (MSGlobals::gSublane && ego->getVehicleType().getWidth() + last->getVehicleType().getWidth() < getWidth()) {
4697 lengths += last->getVehicleType().getLengthWithGap() * (last->getVehicleType().getWidth() + last->getVehicleType().getMinGapLat()) / getWidth();
4698 } else {
4699 lengths += last->getVehicleType().getLengthWithGap();
4700 }
4701 }
4702 return getLength() - lengths;
4703}
4704
4705
4706bool
4707MSLane::allowsVehicleClass(SUMOVehicleClass vclass, int routingMode) const {
4708 return (((routingMode & libsumo::ROUTING_MODE_IGNORE_TRANSIENT_PERMISSIONS) ? myOriginalPermissions : myPermissions) & vclass) == vclass;
4709}
4710
4711/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define RAD2DEG(x)
Definition GeomHelper.h:36
#define DEBUG_COND2(obj)
Definition MESegment.cpp:54
#define INVALID_SPEED
Definition MSCFModel.h:33
std::vector< MSEdge * > MSEdgeVector
Definition MSEdge.h:73
#define LANE_RTREE_QUAL
Definition MSLane.h:1809
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:288
#define WRITE_ERRORF(...)
Definition MsgHandler.h:297
#define WRITE_ERROR(msg)
Definition MsgHandler.h:296
#define WRITE_WARNING(msg)
Definition MsgHandler.h:287
#define TL(string)
Definition MsgHandler.h:305
#define TLF(string,...)
Definition MsgHandler.h:307
SUMOTime DELTA_T
Definition SUMOTime.cpp:38
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition SUMOTime.cpp:46
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition SUMOTime.cpp:91
#define STEPS2TIME(x)
Definition SUMOTime.h:55
#define SPEED2DIST(x)
Definition SUMOTime.h:45
#define SIMSTEP
Definition SUMOTime.h:61
#define SUMOTime_MIN
Definition SUMOTime.h:35
#define SIMTIME
Definition SUMOTime.h:62
#define TIME2STEPS(x)
Definition SUMOTime.h:57
const SVCPermissions SVCAll
all VClasses are allowed
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permissions is a (exclusive) railway 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_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_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:26
int gPrecisionRandom
Definition StdDefs.cpp:29
double roundDecimal(double x, int precision)
round to the given number of decimal digits
Definition StdDefs.cpp:57
bool gDebugFlag1
global utility flags for debugging
Definition StdDefs.cpp:40
#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:326
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
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:340
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:236
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:57
double getCollisionMinGapFactor() const
Get the factor of minGap that must be maintained to avoid a collision event.
Definition MSCFModel.h:321
double getEmergencyDecel() const
Get the vehicle type's maximal physically possible deceleration [m/s^2].
Definition MSCFModel.h:277
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:83
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:408
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
Definition MSCFModel.h:269
double stopSpeed(const MSVehicle *const veh, const double speed, double gap, const CalcReason usage=CalcReason::CURRENT) const
Computes the vehicle's safe speed for approaching a non-moving obstacle (no dawdling)
Definition MSCFModel.h:173
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)
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:77
void changeLanes(SUMOTime t) const
Performs lane changing on this edge.
Definition MSEdge.cpp:898
bool isCrossing() const
return whether this edge is a pedestrian crossing
Definition MSEdge.h:273
int getPriority() const
Returns the priority of the edge.
Definition MSEdge.h:328
const std::set< MSTransportable *, ComparatorNumericalIdLess > & getPersons() const
Returns this edge's persons set.
Definition MSEdge.h:204
bool isWalkingArea() const
return whether this edge is walking area
Definition MSEdge.h:287
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition MSEdge.h:168
const MSEdge * getNormalSuccessor() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
Definition MSEdge.cpp:953
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:480
const MSEdge * getBidiEdge() const
return opposite superposable/congruent edge, if it exist and 0 else
Definition MSEdge.h:282
bool isNormal() const
return whether this edge is an internal edge
Definition MSEdge.h:263
std::vector< MSTransportable * > getSortedPersons(SUMOTime timestep, bool includeRiding=false) const
Returns this edge's persons sorted by pos.
Definition MSEdge.cpp:1212
void recalcCache()
Recalculates the cached values.
Definition MSEdge.cpp:120
bool hasLaneChanger() const
Definition MSEdge.h:738
const MSJunction * getToJunction() const
Definition MSEdge.h:418
int getNumLanes() const
Definition MSEdge.h:172
bool isInternal() const
return whether this edge is an internal edge
Definition MSEdge.h:268
bool isVaporizing() const
Returns whether vehicles on this edge shall be vaporized.
Definition MSEdge.h:434
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:463
const std::string & getEdgeType() const
Returns the type of the edge.
Definition MSEdge.h:319
void markDelayed() const
Definition MSEdge.h:729
const MSEdgeVector & getPredecessors() const
Definition MSEdge.h:409
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:112
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:143
static bool gComputeLC
whether the simulationLoop is in the lane changing phase
Definition MSGlobals.h:140
static bool gEmergencyInsert
Definition MSGlobals.h:94
static int gNumSimThreads
how many threads to use for simulation
Definition MSGlobals.h:146
static SUMOTime gIgnoreJunctionBlocker
Definition MSGlobals.h:85
static bool gSublane
whether sublane simulation is enabled (sublane model or continuous lanechanging)
Definition MSGlobals.h:165
static SUMOTime gLaneChangeDuration
Definition MSGlobals.h:97
static bool gUnitTests
whether unit tests are being run
Definition MSGlobals.h:137
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)
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:1694
by_connections_to_sorter(const MSEdge *const e)
constructor
Definition MSLane.cpp:3514
int operator()(const MSEdge *const e1, const MSEdge *const e2) const
comparing operator
Definition MSLane.cpp:3521
Sorts lanes (IncomingLaneInfos) by their priority or, if this doesn't apply, wrt. the angle differenc...
Definition MSLane.h:1713
incoming_lane_priority_sorter(const MSLane *targetLane)
constructor
Definition MSLane.cpp:3555
int operator()(const IncomingLaneInfo &lane1, const IncomingLaneInfo &lane2) const
comparing operator
Definition MSLane.cpp:3560
Sorts lanes (their origin link) by the priority of their noninternal target edges or,...
Definition MSLane.h:1731
outgoing_lane_priority_sorter(const MSLane *sourceLane)
constructor
Definition MSLane.cpp:3633
int operator()(const MSLink *link1, const MSLink *link2) const
comparing operator
Definition MSLane.cpp:3637
int operator()(MSVehicle *v1, MSVehicle *v2) const
Comparing operator.
Definition MSLane.cpp:3503
Sorts vehicles by their position (descending)
Definition MSLane.h:1648
int operator()(MSVehicle *v1, MSVehicle *v2) const
Comparing operator.
Definition MSLane.cpp:3491
Representation of a lane in the micro simulation.
Definition MSLane.h:84
void addApproachingLane(MSLane *lane, bool warnMultiCon)
Definition MSLane.cpp:2855
void loadState(const std::vector< SUMOVehicle * > &vehs)
Loads the state of this segment with the given parameters.
Definition MSLane.cpp:3752
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:1928
static SUMOTime myIntermodalCollisionStopTime
Definition MSLane.h:1639
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:1495
SVCPermissions myPermissions
The vClass permissions for this lane.
Definition MSLane.h:1536
MSLane * myLogicalPredecessorLane
Definition MSLane.h:1552
static void initCollisionAction(const OptionsCont &oc, const std::string &option, CollisionAction &myAction)
Definition MSLane.cpp:4482
std::set< const MSBaseVehicle * > myParkingVehicles
Definition MSLane.h:1508
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:4569
std::pair< MSVehicle *const, double > getFollower(const MSVehicle *ego, double egoPos, double dist, MinorLinkMode mLinkMode) const
Find follower vehicle for the given ego vehicle (which may be on the opposite direction lane)
Definition MSLane.cpp:4389
static double myDefaultDepartSpeed
Definition MSLane.h:1643
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:4563
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:2839
double myRightSideOnEdge
the combined width of all lanes with lower index on myEdge
Definition MSLane.h:1602
const StopOffset & getLaneStopOffsets() const
Returns vehicle class specific stopOffsets.
Definition MSLane.cpp:3780
virtual void removeParking(MSBaseVehicle *veh)
remove parking vehicle. This must be syncrhonized when running with GUI
Definition MSLane.cpp:3678
virtual ~MSLane()
Destructor.
Definition MSLane.cpp:307
bool insertVehicle(MSVehicle &v)
Tries to insert the given vehicle.
Definition MSLane.cpp:692
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:1490
virtual void integrateNewVehicles()
Insert buffered vehicle into the real lane.
Definition MSLane.cpp:2555
double myLength
Lane length [m].
Definition MSLane.h:1511
bool isApproachedFrom(MSEdge *const edge)
Definition MSLane.h:961
double getNettoOccupancy() const
Returns the netto (excluding minGaps) occupancy of this lane during the last step (including minGaps)
Definition MSLane.cpp:3400
virtual MSVehicle * removeVehicle(MSVehicle *remVehicle, MSMoveReminder::Notification notification, bool notify=true)
Definition MSLane.cpp:2821
int getCrossingIndex() const
return the index of the link to the next crossing if this is walkingArea, else -1
Definition MSLane.cpp:3355
PositionVector myShape
The shape of the lane.
Definition MSLane.h:1456
PositionVector * myOutlineShape
the outline of the lane (optional)
Definition MSLane.h:1459
std::map< long long, SVCPermissions > myPermissionChanges
Definition MSLane.h:1616
const std::map< SUMOVehicleClass, double > * myRestrictions
The vClass speed restrictions for this lane.
Definition MSLane.h:1546
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:1631
bool hasApproaching() const
Definition MSLane.cpp:3683
void addParking(MSBaseVehicle *veh)
add parking vehicle. This should only used during state loading
Definition MSLane.cpp:3672
VehCont myTmpVehicles
Container for lane-changing vehicles. After completion of lane-change- process, the containers will b...
Definition MSLane.h:1491
static DepartSpeedDefinition myDefaultDepartSpeedDefinition
Definition MSLane.h:1642
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:254
double getDepartSpeed(const MSVehicle &veh, bool &patchSpeed)
Definition MSLane.cpp:607
MSLeaderInfo myFollowerInfo
followers on all sublanes as seen by vehicles on consecutive lanes (cached)
Definition MSLane.h:1585
const MSLane * getNormalSuccessorLane() const
get normal lane following this internal lane, for normal lanes, the lane itself is returned
Definition MSLane.cpp:3240
int getVehicleNumber() const
Returns the number of vehicles on this lane (for which this lane is responsible)
Definition MSLane.h:456
static SUMOTime myCollisionStopTime
Definition MSLane.h:1638
static CollisionAction myCollisionAction
the action to take on collisions
Definition MSLane.h:1634
MSLane * myCanonicalSuccessorLane
Main successor lane,.
Definition MSLane.h:1558
SVCPermissions myChangeLeft
The vClass permissions for changing from this lane.
Definition MSLane.h:1539
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:4026
std::vector< IncomingLaneInfo > myIncomingLanes
All direct predecessor lanes.
Definition MSLane.h:1549
AnyVehicleIterator anyVehiclesEnd() const
end iterator for iterating over all vehicles touching this lane in downstream direction
Definition MSLane.h:495
static void insertIDs(std::vector< std::string > &into)
Adds the ids of all stored lanes into the given vector.
Definition MSLane.cpp:2510
bool hadPermissionChanges() const
Definition MSLane.cpp:4538
void sortPartialVehicles()
sorts myPartialVehicles
Definition MSLane.cpp:2582
double myFrictionCoefficient
Lane-wide friction coefficient [0..1].
Definition MSLane.h:1527
MSVehicle * getFirstAnyVehicle() const
returns the first vehicle that is fully or partially on this lane
Definition MSLane.cpp:2669
const MSLink * getEntryLink() const
Returns the entry link if this is an internal lane, else nullptr.
Definition MSLane.cpp:2757
int getVehicleNumberWithPartials() const
Returns the number of vehicles on this lane (including partial occupators)
Definition MSLane.h:464
static bool myCheckJunctionCollisions
Definition MSLane.h:1636
static void clear()
Clears the dictionary.
Definition MSLane.cpp:2501
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:1543
MSEdge *const myEdge
The lane's edge, for routing only.
Definition MSLane.h:1522
double myNettoVehicleLengthSum
The current length of all vehicles on this lane, excluding their minGaps.
Definition MSLane.h:1564
static std::vector< MSLink * >::const_iterator succLinkSec(const SUMOVehicle &veh, int nRouteSuccs, const MSLane &succLinkSource, const std::vector< MSLane * > &conts)
Definition MSLane.cpp:2683
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:1887
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:2880
double myMaxSpeed
Lane-wide speed limit [m/s].
Definition MSLane.h:1525
void saveState(OutputDevice &out)
Saves the state of this lane into the given stream.
Definition MSLane.cpp:3693
void markRecalculateBruttoSum()
Set a flag to recalculate the brutto (including minGaps) occupancy of this lane (used if mingap is ch...
Definition MSLane.cpp:2422
const MSLink * getLinkTo(const MSLane *const) const
returns the link to the given lane or nullptr, if it is not connected
Definition MSLane.cpp:2734
int myRightmostSublane
the index of the rightmost sublane of this lane on myEdge
Definition MSLane.h:1604
void setChangeRight(SVCPermissions permissions)
Sets the permissions for changing to the right neighbour lane.
Definition MSLane.cpp:4550
const bool myIsRampAccel
whether this lane is an acceleration lane
Definition MSLane.h:1596
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:1545
static void saveRNGStates(OutputDevice &out)
save random number generator states to the given output device
Definition MSLane.cpp:4649
SUMOTime myFollowerInfoTime
time step for which myFollowerInfo was last updated
Definition MSLane.h:1590
MSLeaderInfo myLeaderInfo
leaders on all sublanes as seen by approaching vehicles (cached)
Definition MSLane.h:1583
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:851
void forceVehicleInsertion(MSVehicle *veh, double pos, MSMoveReminder::Notification notification, double posLat=0)
Inserts the given vehicle at the given position.
Definition MSLane.cpp:1381
double getVehicleStopOffset(const MSVehicle *veh) const
Returns vehicle class specific stopOffset for the vehicle.
Definition MSLane.cpp:3767
static void initCollisionOptions(const OptionsCont &oc)
Definition MSLane.cpp:4498
int myNumericalID
Unique numerical ID (set on reading by netload)
Definition MSLane.h:1453
VehCont myVehicles
The lane's vehicles. This container holds all vehicles that have their front (longitudinally) and the...
Definition MSLane.h:1475
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition MSLane.h:597
MSLeaderInfo getPartialBeyond() const
get all vehicles that are inlapping from consecutive edges
Definition MSLane.cpp:4226
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:1625
static void fill(RTREE &into)
Fills the given RTree with lane instances.
Definition MSLane.cpp:2518
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:1392
MSLane * myBidiLane
Definition MSLane.h:1613
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:4313
void addIncomingLane(MSLane *lane, MSLink *viaLink)
Definition MSLane.cpp:2845
bool isWalkingArea() const
Definition MSLane.cpp:2626
const MSEdge * getNextNormal() const
Returns the lane's follower if it is an internal lane, the edge of the lane otherwise.
Definition MSLane.cpp:2454
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:4293
void enteredByLaneChange(MSVehicle *v)
Definition MSLane.cpp:3348
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:4412
SVCPermissions getPermissions() const
Returns the vehicle class permissions for this lane.
Definition MSLane.h:619
LinkState getIncomingLinkState() const
get the state of the link from the logical predecessor to this lane
Definition MSLane.cpp:3306
void updateLengthSum()
updated current vehicle length sum (delayed to avoid lane-order-dependency)
Definition MSLane.cpp:2428
const std::vector< IncomingLaneInfo > & getIncomingLanes() const
Definition MSLane.h:955
static const long CHANGE_PERMISSIONS_PERMANENT
Definition MSLane.h:1379
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:3261
void resetPermissions(long long transientID)
Definition MSLane.cpp:4523
MSVehicle * getLastFullVehicle() const
returns the last vehicle for which this lane is responsible or 0
Definition MSLane.cpp:2632
static void loadRNGState(int index, const std::string &state)
load random number generator state for the given rng index
Definition MSLane.cpp:4659
const std::string myLaneType
the type of this lane
Definition MSLane.h:1599
int myRNGIndex
Definition MSLane.h:1619
VehCont myManeuverReservations
The vehicles which registered maneuvering into the lane within their current action step....
Definition MSLane.h:1503
void addLeaders(const MSVehicle *vehicle, double vehPos, MSLeaderDistanceInfo &result, bool oppositeDirection=false)
get leaders for ego on the given lane
Definition MSLane.cpp:4137
static double myCheckJunctionCollisionMinGap
Definition MSLane.h:1637
double getLength() const
Returns the lane's length.
Definition MSLane.h:611
double myBruttoVehicleLengthSum
The current length of all vehicles on this lane, including their minGaps.
Definition MSLane.h:1561
const PositionVector & getShape() const
Returns this lane's shape.
Definition MSLane.h:533
static bool isFrontalCollision(const MSVehicle *collider, const MSVehicle *victim)
detect frontal collisions
Definition MSLane.cpp:2249
void setChangeLeft(SVCPermissions permissions)
Sets the permissions for changing to the left neighbour lane.
Definition MSLane.cpp:4544
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:4324
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:2460
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:2035
double getMaximumBrakeDist() const
compute maximum braking distance on this lane
Definition MSLane.cpp:2896
static CollisionAction myIntermodalCollisionAction
Definition MSLane.h:1635
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:2746
static std::vector< SumoRNG > myRNGs
Definition MSLane.h:1627
virtual void swapAfterLaneChange(SUMOTime t)
moves myTmpVehicles int myVehicles after a lane change procedure
Definition MSLane.cpp:2804
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:3121
StopOffset myLaneStopOffset
Definition MSLane.h:1519
const MSLeaderInfo getLastVehicleInformation(const MSVehicle *ego, double latOffset, double minPos=0, bool allowCached=true) const
Returns the last vehicles on the lane.
Definition MSLane.cpp:1434
static void initRNGs(const OptionsCont &oc)
initialize rngs
Definition MSLane.cpp:4636
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:2980
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:4241
bool myRecalculateBruttoSum
Flag to recalculate the occupancy (including minGaps) after a change in minGap.
Definition MSLane.h:1573
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:3735
MSLane * myCanonicalPredecessorLane
Similar to LogicalPredecessorLane,.
Definition MSLane.h:1555
bool myNeedsCollisionCheck
whether a collision check is currently needed
Definition MSLane.h:1607
bool isLinkEnd(std::vector< MSLink * >::const_iterator &i) const
Definition MSLane.h:858
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition MSLane.h:930
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:574
void setBidiLane(MSLane *bidyLane)
Adds the (overlapping) reverse direction lane to this lane.
Definition MSLane.cpp:349
double getRightSideOnEdge() const
Definition MSLane.h:1200
void checkBufferType()
Definition MSLane.cpp:323
std::pair< MSVehicle *const, double > getOppositeFollower(const MSVehicle *ego) const
Definition MSLane.cpp:4440
bool mySpeedByTraCI
Whether the current speed limit has been set through TraCI.
Definition MSLane.h:1533
bool hasPedestrians() const
whether the lane has pedestrians on it
Definition MSLane.cpp:4556
const std::vector< std::pair< const MSLane *, const MSEdge * > > getOutgoingViaLanes() const
get the list of outgoing lanes
Definition MSLane.cpp:3317
MSVehicle * getPartialBehind(const MSVehicle *ego) const
Definition MSLane.cpp:4203
void setLaneStopOffset(const StopOffset &stopOffset)
Set vehicle class specific stopOffsets.
Definition MSLane.cpp:3786
double myBruttoVehicleLengthSumToRemove
The length of all vehicles that have left this lane in the current step (this lane,...
Definition MSLane.h:1567
void leftByLaneChange(MSVehicle *v)
Definition MSLane.cpp:3341
MSLane * getCanonicalSuccessorLane() const
Definition MSLane.cpp:3285
std::vector< StopWatch< std::chrono::nanoseconds > > myStopWatch
Definition MSLane.h:1796
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:4511
const double myWidth
Lane width [m].
Definition MSLane.h:1514
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:2448
double getOppositePos(double pos) const
return the corresponding position on the opposite lane
Definition MSLane.cpp:4384
SVCPermissions myChangeRight
Definition MSLane.h:1540
const double myLengthGeometryFactor
precomputed myShape.length / myLength
Definition MSLane.h:1593
virtual void executeMovements(const SUMOTime t)
Executes planned vehicle movements with regards to right-of-way.
Definition MSLane.cpp:2268
const std::set< const MSBaseVehicle * > & getParkingVehicles() const
retrieve the parking vehicles (see GUIParkingArea)
Definition MSLane.h:1259
MSLane * getLogicalPredecessorLane() const
get the most likely precedecessor lane (sorted using by_connections_to_sorter). The result is cached ...
Definition MSLane.cpp:3205
double getBruttoOccupancy() const
Returns the brutto (including minGaps) occupancy of this lane during the last step.
Definition MSLane.cpp:3385
AnyVehicleIterator anyVehiclesUpstreamEnd() const
end iterator for iterating over all vehicles touching this lane in upstream direction
Definition MSLane.h:507
int myIndex
The lane index.
Definition MSLane.h:1462
bool isNormal() const
Definition MSLane.cpp:2615
bool isCrossing() const
Definition MSLane.cpp:2621
double getMeanSpeedBike() const
get the mean speed of all bicycles on this lane
Definition MSLane.cpp:3449
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:1593
double getWaitingSeconds() const
Returns the overall waiting time on this lane.
Definition MSLane.cpp:3415
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition MSLane.cpp:2478
virtual void detectCollisions(SUMOTime timestep, const std::string &stage)
Check if vehicles are too close.
Definition MSLane.cpp:1646
std::vector< MSLink * > myLinks
Definition MSLane.h:1577
MSVehicle * getLastAnyVehicle() const
returns the last vehicle that is fully or partially on this lane
Definition MSLane.cpp:2650
bool isInternal() const
Definition MSLane.cpp:2609
VehCont myPartialVehicles
The lane's partial vehicles. This container holds all vehicles that are partially on this lane but wh...
Definition MSLane.h:1487
void sortManeuverReservations()
sorts myManeuverReservations
Definition MSLane.cpp:2590
MinorLinkMode
determine whether/how getFollowers looks upstream beyond minor links
Definition MSLane.h:978
@ FOLLOW_ONCOMING
Definition MSLane.h:981
@ FOLLOW_ALWAYS
Definition MSLane.h:980
@ FOLLOW_NEVER
Definition MSLane.h:979
AnyVehicleIterator anyVehiclesUpstreamBegin() const
begin iterator for iterating over all vehicles touching this lane in upstream direction
Definition MSLane.h:501
std::vector< const MSLane * > getNormalIncomingLanes() const
get the list of all direct (disregarding internal predecessors) non-internal predecessor lanes of thi...
Definition MSLane.cpp:3327
bool mySpeedByVSS
Whether the current speed limit is set by a variable speed sign (VSS)
Definition MSLane.h:1530
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:489
double getHarmonoise_NoiseEmissions() const
Returns the sum of last step noise emissions.
Definition MSLane.cpp:3474
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:2908
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:2172
static bool myExtrapolateSubstepDepart
Definition MSLane.h:1641
MSLane * getOpposite() const
return the neighboring opposite direction lane for lane changing or nullptr
Definition MSLane.cpp:4372
void setLength(double val)
Sets a new length for the lane (used by TraCI only)
Definition MSLane.cpp:2797
std::map< MSEdge *, std::vector< MSLane * > > myApproachingLanes
All direct internal and direct (disregarding internal predecessors) non-internal predecessor lanes of...
Definition MSLane.h:1580
virtual const VehCont & getVehiclesSecure() const
Returns the vehicles container; locks it for microsimulation.
Definition MSLane.h:483
virtual void releaseVehicles() const
Allows to use the container for microsimulation again.
Definition MSLane.h:513
bool mustCheckJunctionCollisions() const
whether this lane must check for junction collisions
Definition MSLane.cpp:4674
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:1585
MSLane * getBidiLane() const
retrieve bidirectional lane or nullptr
Definition MSLane.cpp:4668
static double myCollisionMinGapFactor
Definition MSLane.h:1640
SUMOTime myLeaderInfoTime
time step for which myLeaderInfo was last updated
Definition MSLane.h:1588
MSLane * myOpposite
Definition MSLane.h:1610
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:4378
std::map< std::string, MSLane * > DictType
definition of the static dictionary type
Definition MSLane.h:1622
double getFractionalVehicleLength(bool brutto) const
return length of fractional vehicles on this lane
Definition MSLane.cpp:3366
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:769
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:4683
const MSLane * getNormalPredecessorLane() const
get normal lane leading to this internal lane, for normal lanes, the lane itself is returned
Definition MSLane.cpp:3230
virtual bool appropriate(const MSVehicle *veh) const
Definition MSLane.cpp:2534
MSLeaderDistanceInfo getFollowersOnConsecutive(const MSVehicle *ego, double backOffset, bool allSublanes, double searchDist=-1, MinorLinkMode mLinkMode=FOLLOW_ALWAYS) const
return the sublane followers with the largest missing rear gap among all predecessor lanes (within di...
Definition MSLane.cpp:3792
double getWidth() const
Returns the lane's width.
Definition MSLane.h:640
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
Definition MSLane.h:729
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
void setMaxSpeed(double val, bool byVSS=false, bool byTraCI=false, double jamThreshold=-1)
Sets a new maximum speed for the lane (used by TraCI and MSCalibrator)
Definition MSLane.cpp:2774
MSVehicle * getFirstFullVehicle() const
returns the first vehicle for which this lane is responsible or 0
Definition MSLane.cpp:2641
double getMeanSpeed() const
Returns the mean speed on this lane.
Definition MSLane.cpp:3428
double myNettoVehicleLengthSumToRemove
The length of all vehicles that have left this lane in the current step (this lane,...
Definition MSLane.h:1570
void setFrictionCoefficient(double val)
Sets a new friction coefficient for the lane [to be later (used by TraCI and MSCalibrator)].
Definition MSLane.cpp:2790
static CollisionAction getCollisionAction()
Definition MSLane.h:1362
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:186
static const std::string STAGE_MOVEMENTS
Definition MSNet.h:841
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:326
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:353
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:1285
bool hasPersons() const
Returns whether persons are simulated.
Definition MSNet.h:401
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition MSNet.h:437
static const std::string STAGE_LANECHANGE
Definition MSNet.h:842
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:384
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition MSNet.cpp:1200
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:1324
MSEdgeControl & getEdgeControl()
Returns the edge control.
Definition MSNet.h:427
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:35
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
Returns the object's "vehicle" type.
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
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:835
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:969
double processNextStop(double currentVelocity)
Processes stops, returns the velocity needed to reach the stop.
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:1690
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:54
std::string myID
The name of the object.
Definition Named.h:125
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition Named.h:67
const std::string & getID() const
Returns the id.
Definition Named.h:74
A 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 & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
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:227
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:214
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:62
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) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition json.hpp:21884
#define M_PI
Definition odrSpiral.cpp:45