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