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