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