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