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