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