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