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