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