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