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