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