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->getEdge().isCrossing()) {
1927 collisionType = "crossing";
1928 } else if (foeLane->getEdge().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
2636bool
2638 return myEdge->isWalkingArea();
2639}
2640
2641
2642MSVehicle*
2644 if (myVehicles.size() == 0) {
2645 return nullptr;
2646 }
2647 return myVehicles.front();
2648}
2649
2650
2651MSVehicle*
2653 if (myVehicles.size() == 0) {
2654 return nullptr;
2655 }
2656 return myVehicles.back();
2657}
2658
2659
2660MSVehicle*
2662 // all vehicles in myVehicles should have positions smaller or equal to
2663 // those in myPartialVehicles (unless we're on a bidi-lane)
2664 if (myVehicles.size() > 0) {
2665 if (myBidiLane != nullptr && myPartialVehicles.size() > 0) {
2666 if (myVehicles.front()->getPositionOnLane() > myPartialVehicles.front()->getPositionOnLane(this)) {
2667 return myPartialVehicles.front();
2668 }
2669 }
2670 return myVehicles.front();
2671 }
2672 if (myPartialVehicles.size() > 0) {
2673 return myPartialVehicles.front();
2674 }
2675 return nullptr;
2676}
2677
2678
2679MSVehicle*
2681 MSVehicle* result = nullptr;
2682 if (myVehicles.size() > 0) {
2683 result = myVehicles.back();
2684 }
2685 if (myPartialVehicles.size() > 0
2686 && (result == nullptr || result->getPositionOnLane(this) < myPartialVehicles.back()->getPositionOnLane(this))) {
2687 result = myPartialVehicles.back();
2688 }
2689 return result;
2690}
2691
2692
2693std::vector<MSLink*>::const_iterator
2694MSLane::succLinkSec(const SUMOVehicle& veh, int nRouteSuccs,
2695 const MSLane& succLinkSource, const std::vector<MSLane*>& conts) {
2696 const MSEdge* nRouteEdge = veh.succEdge(nRouteSuccs);
2697 // check whether the vehicle tried to look beyond its route
2698 if (nRouteEdge == nullptr) {
2699 // return end (no succeeding link) if so
2700 return succLinkSource.myLinks.end();
2701 }
2702 // if we are on an internal lane there should only be one link and it must be allowed
2703 if (succLinkSource.isInternal()) {
2704 assert(succLinkSource.myLinks.size() == 1);
2705 // could have been disallowed dynamically with a rerouter or via TraCI
2706 // assert(succLinkSource.myLinks[0]->getLane()->allowsVehicleClass(veh.getVehicleType().getVehicleClass()));
2707 return succLinkSource.myLinks.begin();
2708 }
2709 // a link may be used if
2710 // 1) there is a destination lane ((*link)->getLane()!=0)
2711 // 2) the destination lane belongs to the next edge in route ((*link)->getLane()->myEdge == nRouteEdge)
2712 // 3) the destination lane allows the vehicle's class ((*link)->getLane()->allowsVehicleClass(veh.getVehicleClass()))
2713
2714 // there should be a link which leads to the next desired lane our route in "conts" (built in "getBestLanes")
2715 // "conts" stores the best continuations of our current lane
2716 // we should never return an arbitrary link since this may cause collisions
2717
2718 if (nRouteSuccs < (int)conts.size()) {
2719 // we go through the links in our list and return the matching one
2720 for (std::vector<MSLink*>::const_iterator link = succLinkSource.myLinks.begin(); link != succLinkSource.myLinks.end(); ++link) {
2721 if ((*link)->getLane() != nullptr && (*link)->getLane()->myEdge == nRouteEdge
2722 && (*link)->getLane()->allowsVehicleClass(veh.getVClass())
2723 && ((*link)->getViaLane() == nullptr || (*link)->getViaLane()->allowsVehicleClass(veh.getVClass()))) {
2724 // we should use the link if it connects us to the best lane
2725 if ((*link)->getLane() == conts[nRouteSuccs]) {
2726 return link;
2727 }
2728 }
2729 }
2730 } else {
2731 // the source lane is a dead end (no continuations exist)
2732 return succLinkSource.myLinks.end();
2733 }
2734 // the only case where this should happen is for a disconnected route (deliberately ignored)
2735#ifdef DEBUG_NO_CONNECTION
2736 // the "'" around the ids are missing intentionally in the message below because it slows messaging down, resulting in test timeouts
2737 WRITE_WARNING("Could not find connection between lane " + succLinkSource.getID() + " and lane " + conts[nRouteSuccs]->getID() +
2738 " for vehicle " + veh.getID() + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
2739#endif
2740 return succLinkSource.myLinks.end();
2741}
2742
2743
2744const MSLink*
2745MSLane::getLinkTo(const MSLane* const target) const {
2746 const bool internal = target->isInternal();
2747 for (const MSLink* const l : myLinks) {
2748 if ((internal && l->getViaLane() == target) || (!internal && l->getLane() == target)) {
2749 return l;
2750 }
2751 }
2752 return nullptr;
2753}
2754
2755
2756const MSLane*
2757MSLane::getInternalFollowingLane(const MSLane* const target) const {
2758 for (const MSLink* const l : myLinks) {
2759 if (l->getLane() == target) {
2760 return l->getViaLane();
2761 }
2762 }
2763 return nullptr;
2764}
2765
2766
2767const MSLink*
2769 if (!isInternal()) {
2770 return nullptr;
2771 }
2772 const MSLane* internal = this;
2773 const MSLane* lane = this->getCanonicalPredecessorLane();
2774 assert(lane != nullptr);
2775 while (lane->isInternal()) {
2776 internal = lane;
2777 lane = lane->getCanonicalPredecessorLane();
2778 assert(lane != nullptr);
2779 }
2780 return lane->getLinkTo(internal);
2781}
2782
2783
2784void
2785MSLane::setMaxSpeed(double val, bool byVSS, bool byTraCI, double jamThreshold) {
2786 myMaxSpeed = val;
2787 mySpeedByVSS = byVSS;
2788 mySpeedByTraCI = byTraCI;
2792 while (first != nullptr) {
2793 first->setSpeed(val, SIMSTEP, jamThreshold, myIndex);
2794 first = first->getNextSegment();
2795 }
2796 }
2797}
2798
2799
2800void
2805
2806
2807void
2809 myLength = val;
2811}
2812
2813
2814void
2816 //if (getID() == "disabled_lane") std::cout << SIMTIME << " swapAfterLaneChange lane=" << getID() << " myVehicles=" << toString(myVehicles) << " myTmpVehicles=" << toString(myTmpVehicles) << "\n";
2818 myTmpVehicles.clear();
2819 // this needs to be done after finishing lane-changing for all lanes on the
2820 // current edge (MSLaneChanger::updateLanes())
2822 if (MSGlobals::gSublane && getOpposite() != nullptr) {
2824 }
2825 if (myBidiLane != nullptr) {
2827 }
2828}
2829
2830
2831MSVehicle*
2832MSLane::removeVehicle(MSVehicle* remVehicle, MSMoveReminder::Notification notification, bool notify) {
2833 assert(remVehicle->getLane() == this);
2834 for (MSLane::VehCont::iterator it = myVehicles.begin(); it < myVehicles.end(); it++) {
2835 if (remVehicle == *it) {
2836 if (notify) {
2837 remVehicle->leaveLane(notification);
2838 }
2839 myVehicles.erase(it);
2842 break;
2843 }
2844 }
2845 return remVehicle;
2846}
2847
2848
2849MSLane*
2850MSLane::getParallelLane(int offset, bool includeOpposite) const {
2851 return myEdge->parallelLane(this, offset, includeOpposite);
2852}
2853
2854
2855void
2857 IncomingLaneInfo ili;
2858 ili.lane = lane;
2859 ili.viaLink = viaLink;
2860 ili.length = lane->getLength();
2861 myIncomingLanes.push_back(ili);
2862}
2863
2864
2865void
2866MSLane::addApproachingLane(MSLane* lane, bool warnMultiCon) {
2867 MSEdge* approachingEdge = &lane->getEdge();
2868 if (myApproachingLanes.find(approachingEdge) == myApproachingLanes.end()) {
2869 myApproachingLanes[approachingEdge] = std::vector<MSLane*>();
2870 } else if (!approachingEdge->isInternal() && warnMultiCon) {
2871 // whenever a normal edge connects twice, there is a corresponding
2872 // internal edge wich connects twice, one warning is sufficient
2873 WRITE_WARNINGF(TL("Lane '%' is approached multiple times from edge '%'. This may cause collisions."),
2874 getID(), approachingEdge->getID());
2875 }
2876 myApproachingLanes[approachingEdge].push_back(lane);
2877}
2878
2879
2880bool
2881MSLane::isApproachedFrom(MSEdge* const edge, MSLane* const lane) {
2882 std::map<MSEdge*, std::vector<MSLane*> >::const_iterator i = myApproachingLanes.find(edge);
2883 if (i == myApproachingLanes.end()) {
2884 return false;
2885 }
2886 const std::vector<MSLane*>& lanes = (*i).second;
2887 return std::find(lanes.begin(), lanes.end(), lane) != lanes.end();
2888}
2889
2890
2891double MSLane::getMissingRearGap(const MSVehicle* leader, double backOffset, double leaderSpeed) const {
2892 // this follows the same logic as getFollowerOnConsecutive. we do a tree
2893 // search and check for the vehicle with the largest missing rear gap within
2894 // relevant range
2895 double result = 0;
2896 const double leaderDecel = leader->getCarFollowModel().getMaxDecel();
2897 CLeaderDist followerInfo = getFollowersOnConsecutive(leader, backOffset, false)[0];
2898 const MSVehicle* v = followerInfo.first;
2899 if (v != nullptr) {
2900 result = v->getCarFollowModel().getSecureGap(v, leader, v->getSpeed(), leaderSpeed, leaderDecel) - followerInfo.second;
2901 }
2902 return result;
2903}
2904
2905
2906double
2909 const double maxSpeed = getSpeedLimit() * vc.getMaxSpeedFactor();
2910 // NOTE: For the euler update this is an upper bound on the actual braking distance (see ticket #860)
2911 // impose a hard bound due to visibility / common sense to avoid unnecessary computation if there are strange vehicles in the fleet
2912 const double minDecel = isRailway(myPermissions) ? vc.getMinDecelerationRail() : vc.getMinDeceleration();
2913 return MIN2(maxSpeed * maxSpeed * 0.5 / minDecel,
2914 myPermissions == SVC_SHIP ? 10000.0 : 1000.0);
2915}
2916
2917
2918std::pair<MSVehicle* const, double>
2919MSLane::getLeader(const MSVehicle* veh, const double vehPos, const std::vector<MSLane*>& bestLaneConts, double dist, bool checkTmpVehicles) const {
2920 // get the leading vehicle for (shadow) veh
2921 // XXX this only works as long as all lanes of an edge have equal length
2922#ifdef DEBUG_CONTEXT
2923 if (DEBUG_COND2(veh)) {
2924 std::cout << " getLeader lane=" << getID() << " ego=" << veh->getID() << " vehs=" << toString(myVehicles) << " tmpVehs=" << toString(myTmpVehicles) << "\n";
2925 }
2926#endif
2927 if (checkTmpVehicles) {
2928 for (VehCont::const_iterator last = myTmpVehicles.begin(); last != myTmpVehicles.end(); ++last) {
2929 // XXX refactor leaderInfo to use a const vehicle all the way through the call hierarchy
2930 MSVehicle* pred = (MSVehicle*)*last;
2931 if (pred == veh) {
2932 continue;
2933 }
2934#ifdef DEBUG_CONTEXT
2935 if (DEBUG_COND2(veh)) {
2936 std::cout << std::setprecision(gPrecision) << " getLeader lane=" << getID() << " ego=" << veh->getID() << " egoPos=" << vehPos << " pred=" << pred->getID() << " predPos=" << pred->getPositionOnLane() << "\n";
2937 }
2938#endif
2939 if (pred->getPositionOnLane() >= vehPos) {
2940 return std::pair<MSVehicle* const, double>(pred, pred->getBackPositionOnLane(this) - veh->getVehicleType().getMinGap() - vehPos);
2941 }
2942 }
2943 } else {
2944 for (AnyVehicleIterator last = anyVehiclesBegin(); last != anyVehiclesEnd(); ++last) {
2945 // XXX refactor leaderInfo to use a const vehicle all the way through the call hierarchy
2946 MSVehicle* pred = (MSVehicle*)*last;
2947 if (pred == veh) {
2948 continue;
2949 }
2950#ifdef DEBUG_CONTEXT
2951 if (DEBUG_COND2(veh)) {
2952 std::cout << " getLeader lane=" << getID() << " ego=" << veh->getID() << " egoPos=" << vehPos
2953 << " pred=" << pred->getID() << " predPos=" << pred->getPositionOnLane(this) << " predBack=" << pred->getBackPositionOnLane(this) << "\n";
2954 }
2955#endif
2956 if (pred->getPositionOnLane(this) >= vehPos) {
2958 && pred->getLaneChangeModel().isOpposite()
2960 && pred->getLaneChangeModel().getShadowLane() == this) {
2961 // skip non-overlapping shadow
2962 continue;
2963 }
2964 return std::pair<MSVehicle* const, double>(pred, pred->getBackPositionOnLane(this) - veh->getVehicleType().getMinGap() - vehPos);
2965 }
2966 }
2967 }
2968 // XXX from here on the code mirrors MSLaneChanger::getRealLeader
2969 if (bestLaneConts.size() > 0) {
2970 double seen = getLength() - vehPos;
2971 double speed = veh->getSpeed();
2972 if (dist < 0) {
2973 dist = veh->getCarFollowModel().brakeGap(speed) + veh->getVehicleType().getMinGap();
2974 }
2975#ifdef DEBUG_CONTEXT
2976 if (DEBUG_COND2(veh)) {
2977 std::cout << " getLeader lane=" << getID() << " seen=" << seen << " dist=" << dist << "\n";
2978 }
2979#endif
2980 if (seen > dist) {
2981 return std::pair<MSVehicle* const, double>(static_cast<MSVehicle*>(nullptr), -1);
2982 }
2983 return getLeaderOnConsecutive(dist, seen, speed, *veh, bestLaneConts);
2984 } else {
2985 return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
2986 }
2987}
2988
2989
2990std::pair<MSVehicle* const, double>
2991MSLane::getLeaderOnConsecutive(double dist, double seen, double speed, const MSVehicle& veh,
2992 const std::vector<MSLane*>& bestLaneConts, bool considerCrossingFoes) const {
2993#ifdef DEBUG_CONTEXT
2994 if (DEBUG_COND2(&veh)) {
2995 std::cout << " getLeaderOnConsecutive lane=" << getID() << " ego=" << veh.getID() << " seen=" << seen << " dist=" << dist << " conts=" << toString(bestLaneConts) << "\n";
2996 }
2997#endif
2998 if (seen > dist && !isInternal()) {
2999 return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
3000 }
3001 int view = 1;
3002 // loop over following lanes
3003 if (myPartialVehicles.size() > 0) {
3004 // XXX
3005 MSVehicle* pred = myPartialVehicles.front();
3006 const double gap = seen - (getLength() - pred->getBackPositionOnLane(this)) - veh.getVehicleType().getMinGap();
3007#ifdef DEBUG_CONTEXT
3008 if (DEBUG_COND2(&veh)) {
3009 std::cout << " predGap=" << gap << " partials=" << toString(myPartialVehicles) << "\n";
3010 }
3011#endif
3012 // make sure pred is really a leader and not doing continous lane-changing behind ego
3013 if (gap > 0) {
3014 return std::pair<MSVehicle* const, double>(pred, gap);
3015 }
3016 }
3017#ifdef DEBUG_CONTEXT
3018 if (DEBUG_COND2(&veh)) {
3019 gDebugFlag1 = true;
3020 }
3021#endif
3022 const MSLane* nextLane = this;
3023 do {
3024 nextLane->getVehiclesSecure(); // lock against running sim when called from GUI for time gap coloring
3025 // get the next link used
3026 std::vector<MSLink*>::const_iterator link = succLinkSec(veh, view, *nextLane, bestLaneConts);
3027 if (nextLane->isLinkEnd(link) && view < veh.getRoute().size() - veh.getRoutePosition()) {
3028 const MSEdge* nextEdge = *(veh.getCurrentRouteEdge() + view);
3029 if (nextEdge->getNumLanes() == 1) {
3030 // lanes are unambiguous on the next route edge, continue beyond bestLaneConts
3031 for (link = nextLane->getLinkCont().begin(); link < nextLane->getLinkCont().end(); link++) {
3032 if ((*link)->getLane() == nextEdge->getLanes().front()) {
3033 break;
3034 }
3035 }
3036 }
3037 }
3038 if (nextLane->isLinkEnd(link)) {
3039#ifdef DEBUG_CONTEXT
3040 if (DEBUG_COND2(&veh)) {
3041 std::cout << " cannot continue after nextLane=" << nextLane->getID() << "\n";
3042 }
3043#endif
3044 nextLane->releaseVehicles();
3045 break;
3046 }
3047 // check for link leaders
3048 const bool laneChanging = veh.getLane() != this;
3049 const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(&veh, seen);
3050 nextLane->releaseVehicles();
3051 if (linkLeaders.size() > 0) {
3052 std::pair<MSVehicle*, double> result;
3053 double shortestGap = std::numeric_limits<double>::max();
3054 for (auto ll : linkLeaders) {
3055 double gap = ll.vehAndGap.second;
3056 MSVehicle* lVeh = ll.vehAndGap.first;
3057 if (lVeh != nullptr) {
3058 // leader is a vehicle, not a pedestrian
3059 gap += lVeh->getCarFollowModel().brakeGap(lVeh->getSpeed(), lVeh->getCarFollowModel().getMaxDecel(), 0);
3060 }
3061#ifdef DEBUG_CONTEXT
3062 if (DEBUG_COND2(&veh)) {
3063 std::cout << " linkLeader candidate " << Named::getIDSecure(lVeh)
3064 << " isLeader=" << veh.isLeader(*link, lVeh, ll.vehAndGap.second)
3065 << " gap=" << ll.vehAndGap.second
3066 << " gap+brakeing=" << gap
3067 << "\n";
3068 }
3069#endif
3070 // skip vehicles which do not share the outgoing edge (to get only real leader vehicles in TraCI #13842)
3071 if (!considerCrossingFoes && !ll.sameTarget()) {
3072 continue;
3073 }
3074 // in the context of lane-changing, all candidates are leaders
3075 if (lVeh != nullptr && !laneChanging && !veh.isLeader(*link, lVeh, ll.vehAndGap.second)) {
3076 continue;
3077 }
3078 if (gap < shortestGap) {
3079 shortestGap = gap;
3080 if (ll.vehAndGap.second < 0 && !MSGlobals::gComputeLC) {
3081 // can always continue up to the stop line or crossing point
3082 // @todo: figure out whether this should also impact lane changing
3083 ll.vehAndGap.second = MAX2(seen - nextLane->getLength(), ll.distToCrossing);
3084 }
3085 result = ll.vehAndGap;
3086 }
3087 }
3088 if (shortestGap != std::numeric_limits<double>::max()) {
3089#ifdef DEBUG_CONTEXT
3090 if (DEBUG_COND2(&veh)) {
3091 std::cout << " found linkLeader after nextLane=" << nextLane->getID() << "\n";
3092 gDebugFlag1 = false;
3093 }
3094#endif
3095 return result;
3096 }
3097 }
3098 bool nextInternal = (*link)->getViaLane() != nullptr;
3099 nextLane = (*link)->getViaLaneOrLane();
3100 if (nextLane == nullptr) {
3101 break;
3102 }
3103 nextLane->getVehiclesSecure(); // lock against running sim when called from GUI for time gap coloring
3104 MSVehicle* leader = nextLane->getLastAnyVehicle();
3105 if (leader != nullptr) {
3106#ifdef DEBUG_CONTEXT
3107 if (DEBUG_COND2(&veh)) {
3108 std::cout << " found leader " << leader->getID() << " on nextLane=" << nextLane->getID() << "\n";
3109 }
3110#endif
3111 const double leaderDist = seen + leader->getBackPositionOnLane(nextLane) - veh.getVehicleType().getMinGap();
3112 nextLane->releaseVehicles();
3113 return std::make_pair(leader, leaderDist);
3114 }
3115 nextLane->releaseVehicles();
3116 if (nextLane->getVehicleMaxSpeed(&veh) < speed) {
3117 dist = veh.getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(&veh));
3118 }
3119 seen += nextLane->getLength();
3120 if (!nextInternal) {
3121 view++;
3122 }
3123 } while (seen <= dist || nextLane->isInternal());
3124#ifdef DEBUG_CONTEXT
3125 gDebugFlag1 = false;
3126#endif
3127 return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
3128}
3129
3130
3131std::pair<MSVehicle* const, double>
3132MSLane::getCriticalLeader(double dist, double seen, double speed, const MSVehicle& veh) const {
3133#ifdef DEBUG_CONTEXT
3134 if (DEBUG_COND2(&veh)) {
3135 std::cout << SIMTIME << " getCriticalLeader. lane=" << getID() << " veh=" << veh.getID() << "\n";
3136 }
3137#endif
3138 const std::vector<MSLane*>& bestLaneConts = veh.getBestLanesContinuation(this);
3139 std::pair<MSVehicle*, double> result = std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
3140 double safeSpeed = std::numeric_limits<double>::max();
3141 int view = 1;
3142 // loop over following lanes
3143 // @note: we don't check the partial occupator for this lane since it was
3144 // already checked in MSLaneChanger::getRealLeader()
3145 const MSLane* nextLane = this;
3146 SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / MAX2(speed, NUMERICAL_EPS));
3147 do {
3148 // get the next link used
3149 std::vector<MSLink*>::const_iterator link = succLinkSec(veh, view, *nextLane, bestLaneConts);
3150 if (nextLane->isLinkEnd(link) || !(*link)->opened(arrivalTime, speed, speed, veh.getVehicleType().getLength(),
3151 veh.getImpatience(), veh.getCarFollowModel().getMaxDecel(), 0, veh.getLateralPositionOnLane(), nullptr, false, &veh) || (*link)->haveRed()) {
3152 return result;
3153 }
3154 // check for link leaders
3155#ifdef DEBUG_CONTEXT
3156 if (DEBUG_COND2(&veh)) {
3157 gDebugFlag1 = true; // See MSLink::getLeaderInfo
3158 }
3159#endif
3160 const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(&veh, seen);
3161#ifdef DEBUG_CONTEXT
3162 if (DEBUG_COND2(&veh)) {
3163 gDebugFlag1 = false; // See MSLink::getLeaderInfo
3164 }
3165#endif
3166 for (MSLink::LinkLeaders::const_iterator it = linkLeaders.begin(); it != linkLeaders.end(); ++it) {
3167 const MSVehicle* leader = (*it).vehAndGap.first;
3168 if (leader != nullptr && leader != result.first) {
3169 // XXX ignoring pedestrians here!
3170 // XXX ignoring the fact that the link leader may alread by following us
3171 // XXX ignoring the fact that we may drive up to the crossing point
3172 double tmpSpeed = safeSpeed;
3173 veh.adaptToJunctionLeader((*it).vehAndGap, seen, nullptr, nextLane, tmpSpeed, tmpSpeed, (*it).distToCrossing);
3174#ifdef DEBUG_CONTEXT
3175 if (DEBUG_COND2(&veh)) {
3176 std::cout << " linkLeader=" << leader->getID() << " gap=" << result.second << " tmpSpeed=" << tmpSpeed << " safeSpeed=" << safeSpeed << "\n";
3177 }
3178#endif
3179 if (tmpSpeed < safeSpeed) {
3180 safeSpeed = tmpSpeed;
3181 result = (*it).vehAndGap;
3182 }
3183 }
3184 }
3185 bool nextInternal = (*link)->getViaLane() != nullptr;
3186 nextLane = (*link)->getViaLaneOrLane();
3187 if (nextLane == nullptr) {
3188 break;
3189 }
3190 MSVehicle* leader = nextLane->getLastAnyVehicle();
3191 if (leader != nullptr && leader != result.first) {
3192 const double gap = seen + leader->getBackPositionOnLane(nextLane) - veh.getVehicleType().getMinGap();
3193 const double tmpSpeed = veh.getCarFollowModel().insertionFollowSpeed(&veh, speed, gap, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel(), leader);
3194 if (tmpSpeed < safeSpeed) {
3195 safeSpeed = tmpSpeed;
3196 result = std::make_pair(leader, gap);
3197 }
3198 }
3199 if (nextLane->getVehicleMaxSpeed(&veh) < speed) {
3200 dist = veh.getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(&veh));
3201 }
3202 seen += nextLane->getLength();
3203 if (seen <= dist) {
3204 // delaying the update of arrivalTime and making it conditional to avoid possible integer overflows
3205 arrivalTime += TIME2STEPS(nextLane->getLength() / MAX2(speed, NUMERICAL_EPS));
3206 }
3207 if (!nextInternal) {
3208 view++;
3209 }
3210 } while (seen <= dist || nextLane->isInternal());
3211 return result;
3212}
3213
3214
3215MSLane*
3217 if (myLogicalPredecessorLane == nullptr) {
3219 // get only those edges which connect to this lane
3220 for (MSEdgeVector::iterator i = pred.begin(); i != pred.end();) {
3221 std::vector<IncomingLaneInfo>::const_iterator j = find_if(myIncomingLanes.begin(), myIncomingLanes.end(), edge_finder(*i));
3222 if (j == myIncomingLanes.end()) {
3223 i = pred.erase(i);
3224 } else {
3225 ++i;
3226 }
3227 }
3228 // get the lane with the "straightest" connection
3229 if (pred.size() != 0) {
3230 std::sort(pred.begin(), pred.end(), by_connections_to_sorter(&getEdge()));
3231 MSEdge* best = *pred.begin();
3232 std::vector<IncomingLaneInfo>::const_iterator j = find_if(myIncomingLanes.begin(), myIncomingLanes.end(), edge_finder(best));
3233 myLogicalPredecessorLane = j->lane;
3234 }
3235 }
3237}
3238
3239
3240const MSLane*
3242 if (isInternal()) {
3244 } else {
3245 return this;
3246 }
3247}
3248
3249
3250const MSLane*
3252 if (isInternal()) {
3254 } else {
3255 return this;
3256 }
3257}
3258
3259
3260MSLane*
3262 for (const IncomingLaneInfo& cand : myIncomingLanes) {
3263 if (&(cand.lane->getEdge()) == &fromEdge) {
3264 return cand.lane;
3265 }
3266 }
3267 return nullptr;
3268}
3269
3270
3271MSLane*
3273 if (myCanonicalPredecessorLane != nullptr) {
3275 }
3276 if (myIncomingLanes.empty()) {
3277 return nullptr;
3278 }
3279 // myCanonicalPredecessorLane has not yet been determined and there exist incoming lanes
3280 // get the lane with the priorized (or if this does not apply the "straightest") connection
3281 const auto bestLane = std::min_element(myIncomingLanes.begin(), myIncomingLanes.end(), incoming_lane_priority_sorter(this));
3282 {
3283#ifdef HAVE_FOX
3284 ScopedLocker<> lock(myLeaderInfoMutex, MSGlobals::gNumSimThreads > 1);
3285#endif
3286 myCanonicalPredecessorLane = bestLane->lane;
3287 }
3288#ifdef DEBUG_LANE_SORTER
3289 std::cout << "\nBest predecessor lane for lane '" << myID << "': '" << myCanonicalPredecessorLane->getID() << "'" << std::endl;
3290#endif
3292}
3293
3294
3295MSLane*
3297 if (myCanonicalSuccessorLane != nullptr) {
3299 }
3300 if (myLinks.empty()) {
3301 return nullptr;
3302 }
3303 // myCanonicalSuccessorLane has not yet been determined and there exist outgoing links
3304 std::vector<MSLink*> candidateLinks = myLinks;
3305 // get the lane with the priorized (or if this does not apply the "straightest") connection
3306 std::sort(candidateLinks.begin(), candidateLinks.end(), outgoing_lane_priority_sorter(this));
3307 MSLane* best = (*candidateLinks.begin())->getViaLaneOrLane();
3308#ifdef DEBUG_LANE_SORTER
3309 std::cout << "\nBest successor lane for lane '" << myID << "': '" << best->getID() << "'" << std::endl;
3310#endif
3313}
3314
3315
3318 const MSLane* const pred = getLogicalPredecessorLane();
3319 if (pred == nullptr) {
3320 return LINKSTATE_DEADEND;
3321 } else {
3322 return pred->getLinkTo(this)->getState();
3323 }
3324}
3325
3326
3327const std::vector<std::pair<const MSLane*, const MSEdge*> >
3329 std::vector<std::pair<const MSLane*, const MSEdge*> > result;
3330 for (const MSLink* link : myLinks) {
3331 assert(link->getLane() != nullptr);
3332 result.push_back(std::make_pair(link->getLane(), link->getViaLane() == nullptr ? nullptr : &link->getViaLane()->getEdge()));
3333 }
3334 return result;
3335}
3336
3337std::vector<const MSLane*>
3339 std::vector<const MSLane*> result = {};
3340 for (std::map<MSEdge*, std::vector<MSLane*> >::const_iterator it = myApproachingLanes.begin(); it != myApproachingLanes.end(); ++it) {
3341 for (std::vector<MSLane*>::const_iterator it_lane = (*it).second.begin(); it_lane != (*it).second.end(); ++it_lane) {
3342 if (!((*it_lane)->isInternal())) {
3343 result.push_back(*it_lane);
3344 }
3345 }
3346 }
3347 return result;
3348}
3349
3350
3351void
3356
3357
3358void
3363
3364
3365int
3367 for (std::vector<MSLink*>::const_iterator i = myLinks.begin(); i != myLinks.end(); ++i) {
3368 if ((*i)->getLane()->getEdge().isCrossing()) {
3369 return (int)(i - myLinks.begin());
3370 }
3371 }
3372 return -1;
3373}
3374
3375// ------------ Current state retrieval
3376double
3378 double sum = 0;
3379 if (myPartialVehicles.size() > 0) {
3380 const MSLane* bidi = getBidiLane();
3381 for (MSVehicle* cand : myPartialVehicles) {
3382 if (MSGlobals::gSublane && cand->getLaneChangeModel().getShadowLane() == this) {
3383 continue;
3384 }
3385 if (cand->getLane() == bidi) {
3386 sum += (brutto ? cand->getVehicleType().getLengthWithGap() : cand->getVehicleType().getLength());
3387 } else {
3388 sum += myLength - cand->getBackPositionOnLane(this);
3389 }
3390 }
3391 }
3392 return sum;
3393}
3394
3395double
3398 double fractions = getFractionalVehicleLength(true);
3399 if (myVehicles.size() != 0) {
3400 MSVehicle* lastVeh = myVehicles.front();
3401 if (lastVeh->getPositionOnLane() < lastVeh->getVehicleType().getLength()) {
3402 fractions -= (lastVeh->getVehicleType().getLength() - lastVeh->getPositionOnLane());
3403 }
3404 }
3406 return MIN2(1., (myBruttoVehicleLengthSum + fractions) / myLength);
3407}
3408
3409
3410double
3413 double fractions = getFractionalVehicleLength(false);
3414 if (myVehicles.size() != 0) {
3415 MSVehicle* lastVeh = myVehicles.front();
3416 if (lastVeh->getPositionOnLane() < lastVeh->getVehicleType().getLength()) {
3417 fractions -= (lastVeh->getVehicleType().getLength() - lastVeh->getPositionOnLane());
3418 }
3419 }
3421 return (myNettoVehicleLengthSum + fractions) / myLength;
3422}
3423
3424
3425double
3427 if (myVehicles.size() == 0) {
3428 return 0;
3429 }
3430 double wtime = 0;
3431 for (VehCont::const_iterator i = myVehicles.begin(); i != myVehicles.end(); ++i) {
3432 wtime += (*i)->getWaitingSeconds();
3433 }
3434 return wtime;
3435}
3436
3437
3438double
3440 if (myVehicles.size() == 0) {
3441 return myMaxSpeed;
3442 }
3443 double v = 0;
3444 int numVehs = 0;
3445 for (const MSVehicle* const veh : getVehiclesSecure()) {
3446 if (!veh->isStopped() || !myEdge->hasLaneChanger()) {
3447 v += veh->getSpeed();
3448 numVehs++;
3449 }
3450 }
3452 if (numVehs == 0) {
3453 return myMaxSpeed;
3454 }
3455 return v / numVehs;
3456}
3457
3458
3459double
3461 // @note: redundant code with getMeanSpeed to avoid extra checks in a function that is called very often
3462 if (myVehicles.size() == 0) {
3463 return myMaxSpeed;
3464 }
3465 double v = 0;
3466 int numBikes = 0;
3467 for (MSVehicle* veh : getVehiclesSecure()) {
3468 if (veh->getVClass() == SVC_BICYCLE) {
3469 v += veh->getSpeed();
3470 numBikes++;
3471 }
3472 }
3473 double ret;
3474 if (numBikes > 0) {
3475 ret = v / (double) myVehicles.size();
3476 } else {
3477 ret = myMaxSpeed;
3478 }
3480 return ret;
3481}
3482
3483
3484double
3486 double ret = 0;
3487 const MSLane::VehCont& vehs = getVehiclesSecure();
3488 if (vehs.size() == 0) {
3490 return 0;
3491 }
3492 for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
3493 double sv = (*i)->getHarmonoise_NoiseEmissions();
3494 ret += (double) pow(10., (sv / 10.));
3495 }
3497 return HelpersHarmonoise::sum(ret);
3498}
3499
3500
3501int
3503 const double pos1 = v1->getBackPositionOnLane(myLane);
3504 const double pos2 = v2->getBackPositionOnLane(myLane);
3505 if (pos1 != pos2) {
3506 return pos1 > pos2;
3507 } else {
3508 return v1->getNumericalID() > v2->getNumericalID();
3509 }
3510}
3511
3512
3513int
3515 const double pos1 = v1->getBackPositionOnLane(myLane);
3516 const double pos2 = v2->getBackPositionOnLane(myLane);
3517 if (pos1 != pos2) {
3518 return pos1 < pos2;
3519 } else {
3521 }
3522}
3523
3524
3526 myEdge(e),
3527 myLaneDir(e->getLanes()[0]->getShape().angleAt2D(0)) {
3528}
3529
3530
3531int
3532MSLane::by_connections_to_sorter::operator()(const MSEdge* const e1, const MSEdge* const e2) const {
3533// std::cout << "\nby_connections_to_sorter()";
3534
3535 const std::vector<MSLane*>* ae1 = e1->allowedLanes(*myEdge);
3536 const std::vector<MSLane*>* ae2 = e2->allowedLanes(*myEdge);
3537 double s1 = 0;
3538 if (ae1 != nullptr && ae1->size() != 0) {
3539// std::cout << "\nsize 1 = " << ae1->size()
3540// << " anglediff 1 = " << fabs(GeomHelper::angleDiff((*ae1)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.
3541// << "\nallowed lanes: ";
3542// for (std::vector<MSLane*>::const_iterator j = ae1->begin(); j != ae1->end(); ++j){
3543// std::cout << "\n" << (*j)->getID();
3544// }
3545 s1 = (double) ae1->size() + fabs(GeomHelper::angleDiff((*ae1)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.;
3546 }
3547 double s2 = 0;
3548 if (ae2 != nullptr && ae2->size() != 0) {
3549// std::cout << "\nsize 2 = " << ae2->size()
3550// << " anglediff 2 = " << fabs(GeomHelper::angleDiff((*ae2)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.
3551// << "\nallowed lanes: ";
3552// for (std::vector<MSLane*>::const_iterator j = ae2->begin(); j != ae2->end(); ++j){
3553// std::cout << "\n" << (*j)->getID();
3554// }
3555 s2 = (double) ae2->size() + fabs(GeomHelper::angleDiff((*ae2)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.;
3556 }
3557
3558// std::cout << "\ne1 = " << e1->getID() << " e2 = " << e2->getID()
3559// << "\ns1 = " << s1 << " s2 = " << s2
3560// << std::endl;
3561
3562 return s1 < s2;
3563}
3564
3565
3567 myLane(targetLane),
3568 myLaneDir(targetLane->getShape().angleAt2D(0)) {}
3569
3570int
3572 const MSLane* noninternal1 = laneInfo1.lane;
3573 while (noninternal1->isInternal()) {
3574 assert(noninternal1->getIncomingLanes().size() == 1);
3575 noninternal1 = noninternal1->getIncomingLanes()[0].lane;
3576 }
3577 MSLane* noninternal2 = laneInfo2.lane;
3578 while (noninternal2->isInternal()) {
3579 assert(noninternal2->getIncomingLanes().size() == 1);
3580 noninternal2 = noninternal2->getIncomingLanes()[0].lane;
3581 }
3582
3583 const MSLink* link1 = noninternal1->getLinkTo(myLane);
3584 const MSLink* link2 = noninternal2->getLinkTo(myLane);
3585
3586#ifdef DEBUG_LANE_SORTER
3587 std::cout << "\nincoming_lane_priority sorter()\n"
3588 << "noninternal predecessor for lane '" << laneInfo1.lane->getID()
3589 << "': '" << noninternal1->getID() << "'\n"
3590 << "noninternal predecessor for lane '" << laneInfo2.lane->getID()
3591 << "': '" << noninternal2->getID() << "'\n";
3592#endif
3593
3594 assert(laneInfo1.lane->isInternal() || link1 == laneInfo1.viaLink);
3595 assert(link1 != 0);
3596 assert(link2 != 0);
3597
3598 // check priority between links
3599 bool priorized1 = true;
3600 bool priorized2 = true;
3601
3602#ifdef DEBUG_LANE_SORTER
3603 std::cout << "FoeLinks of '" << noninternal1->getID() << "'" << std::endl;
3604#endif
3605 for (const MSLink* const foeLink : link1->getFoeLinks()) {
3606#ifdef DEBUG_LANE_SORTER
3607 std::cout << foeLink->getLaneBefore()->getID() << std::endl;
3608#endif
3609 if (foeLink == link2) {
3610 priorized1 = false;
3611 break;
3612 }
3613 }
3614
3615#ifdef DEBUG_LANE_SORTER
3616 std::cout << "FoeLinks of '" << noninternal2->getID() << "'" << std::endl;
3617#endif
3618 for (const MSLink* const foeLink : link2->getFoeLinks()) {
3619#ifdef DEBUG_LANE_SORTER
3620 std::cout << foeLink->getLaneBefore()->getID() << std::endl;
3621#endif
3622 // either link1 is priorized, or it should not appear in link2's foes
3623 if (foeLink == link1) {
3624 priorized2 = false;
3625 break;
3626 }
3627 }
3628 // if one link is subordinate, the other must be priorized (except for
3629 // traffic lights where mutual response is permitted to handle stuck-on-red
3630 // situation)
3631 if (priorized1 != priorized2) {
3632 return priorized1;
3633 }
3634
3635 // both are priorized, compare angle difference
3636 double d1 = fabs(GeomHelper::angleDiff(noninternal1->getShape().angleAt2D(0), myLaneDir));
3637 double d2 = fabs(GeomHelper::angleDiff(noninternal2->getShape().angleAt2D(0), myLaneDir));
3638
3639 return d2 > d1;
3640}
3641
3642
3643
3645 myLaneDir(sourceLane->getShape().angleAt2D(0)) {}
3646
3647int
3649 const MSLane* target1 = link1->getLane();
3650 const MSLane* target2 = link2->getLane();
3651 if (target2 == nullptr) {
3652 return true;
3653 }
3654 if (target1 == nullptr) {
3655 return false;
3656 }
3657
3658#ifdef DEBUG_LANE_SORTER
3659 std::cout << "\noutgoing_lane_priority sorter()\n"
3660 << "noninternal successors for lane '" << myLane->getID()
3661 << "': '" << target1->getID() << "' and "
3662 << "'" << target2->getID() << "'\n";
3663#endif
3664
3665 // priority of targets
3666 int priority1 = target1->getEdge().getPriority();
3667 int priority2 = target2->getEdge().getPriority();
3668
3669 if (priority1 != priority2) {
3670 return priority1 > priority2;
3671 }
3672
3673 // if priority of targets coincides, use angle difference
3674
3675 // both are priorized, compare angle difference
3676 double d1 = fabs(GeomHelper::angleDiff(target1->getShape().angleAt2D(0), myLaneDir));
3677 double d2 = fabs(GeomHelper::angleDiff(target2->getShape().angleAt2D(0), myLaneDir));
3678
3679 return d2 > d1;
3680}
3681
3682void
3686
3687
3688void
3692
3693bool
3695 for (const MSLink* link : myLinks) {
3696 if (link->getApproaching().size() > 0) {
3697 return true;
3698 }
3699 }
3700 return false;
3701}
3702
3703void
3705 const bool toRailJunction = myLinks.size() > 0 && (
3708 const bool hasVehicles = myVehicles.size() > 0;
3709 if (hasVehicles || (toRailJunction && hasApproaching())) {
3712 if (hasVehicles) {
3715 out.closeTag();
3716 }
3717 if (toRailJunction) {
3718 for (const MSLink* link : myLinks) {
3719 if (link->getApproaching().size() > 0) {
3721 out.writeAttr(SUMO_ATTR_TO, link->getViaLaneOrLane()->getID());
3722 for (auto item : link->getApproaching()) {
3724 out.writeAttr(SUMO_ATTR_ID, item.first->getID());
3725 out.writeAttr(SUMO_ATTR_ARRIVALTIME, item.second.arrivalTime);
3726 out.writeAttr(SUMO_ATTR_ARRIVALSPEED, item.second.arrivalSpeed);
3727 out.writeAttr(SUMO_ATTR_DEPARTSPEED, item.second.leaveSpeed);
3728 out.writeAttr(SUMO_ATTR_REQUEST, item.second.willPass);
3729 out.writeAttr(SUMO_ATTR_ARRIVALSPEEDBRAKING, item.second.arrivalSpeedBraking);
3730 out.writeAttr(SUMO_ATTR_WAITINGTIME, item.second.waitingTime);
3731 out.writeAttr(SUMO_ATTR_DISTANCE, item.second.dist);
3732 if (item.second.latOffset != 0) {
3733 out.writeAttr(SUMO_ATTR_POSITION_LAT, item.second.latOffset);
3734 }
3735 out.closeTag();
3736 }
3737 out.closeTag();
3738 }
3739 }
3740 }
3741 out.closeTag();
3742 }
3743}
3744
3745void
3747 myVehicles.clear();
3748 myParkingVehicles.clear();
3749 myPartialVehicles.clear();
3750 myManeuverReservations.clear();
3757 for (MSLink* link : myLinks) {
3758 link->clearState();
3759 }
3760}
3761
3762void
3763MSLane::loadState(const std::vector<SUMOVehicle*>& vehs) {
3764 for (SUMOVehicle* veh : vehs) {
3765 MSVehicle* v = dynamic_cast<MSVehicle*>(veh);
3766 v->updateBestLanes(false, this);
3767 // incorporateVehicle resets the lastActionTime (which has just been loaded from state) so we must restore it
3768 const SUMOTime lastActionTime = v->getLastActionTime();
3771 v->resetActionOffset(lastActionTime - MSNet::getInstance()->getCurrentTimeStep());
3772 v->processNextStop(v->getSpeed());
3773 }
3774}
3775
3776
3777double
3779 if (!myLaneStopOffset.isDefined()) {
3780 return 0;
3781 }
3782 if ((myLaneStopOffset.getPermissions() & veh->getVClass()) != 0) {
3783 return myLaneStopOffset.getOffset();
3784 } else {
3785 return 0;
3786 }
3787}
3788
3789
3790const StopOffset&
3794
3795
3796void
3798 myLaneStopOffset = stopOffset;
3799}
3800
3801
3803MSLane::getFollowersOnConsecutive(const MSVehicle* ego, double backOffset,
3804 bool allSublanes, double searchDist, MinorLinkMode mLinkMode) const {
3805 assert(ego != 0);
3806 // get the follower vehicle on the lane to change to
3807 const double egoPos = backOffset + ego->getVehicleType().getLength();
3808 const double egoLatDist = ego->getLane()->getRightSideOnEdge() - getRightSideOnEdge();
3809 const bool getOppositeLeaders = ((ego->getLaneChangeModel().isOpposite() && ego->getLane() == this)
3810 || (!ego->getLaneChangeModel().isOpposite() && &ego->getLane()->getEdge() != &getEdge()));
3811#ifdef DEBUG_CONTEXT
3812 if (DEBUG_COND2(ego)) {
3813 std::cout << SIMTIME << " getFollowers lane=" << getID() << " ego=" << ego->getID()
3814 << " backOffset=" << backOffset << " pos=" << egoPos
3815 << " allSub=" << allSublanes << " searchDist=" << searchDist << " ignoreMinor=" << mLinkMode
3816 << " egoLatDist=" << egoLatDist
3817 << " getOppositeLeaders=" << getOppositeLeaders
3818 << "\n";
3819 }
3820#endif
3821 MSCriticalFollowerDistanceInfo result(myWidth, allSublanes ? nullptr : ego, allSublanes ? 0 : egoLatDist, getOppositeLeaders);
3822 if (MSGlobals::gLateralResolution > 0 && egoLatDist == 0) {
3823 // check whether ego is outside lane bounds far enough so that another vehicle might
3824 // be between itself and the first "actual" sublane
3825 // shift the offset so that we "see" this vehicle
3830 }
3831#ifdef DEBUG_CONTEXT
3832 if (DEBUG_COND2(ego)) {
3833 std::cout << SIMTIME << " getFollowers lane=" << getID() << " ego=" << ego->getID()
3834 << " egoPosLat=" << ego->getLateralPositionOnLane()
3835 << " egoLatDist=" << ego->getLane()->getRightSideOnEdge() - getRightSideOnEdge()
3836 << " extraOffset=" << result.getSublaneOffset()
3837 << "\n";
3838 }
3839#endif
3840 }
3842 for (AnyVehicleIterator last = anyVehiclesBegin(); last != anyVehiclesEnd(); ++last) {
3843 const MSVehicle* veh = *last;
3844#ifdef DEBUG_CONTEXT
3845 if (DEBUG_COND2(ego)) {
3846 std::cout << " veh=" << veh->getID() << " lane=" << veh->getLane()->getID() << " pos=" << veh->getPositionOnLane(this) << "\n";
3847 }
3848#endif
3849 if (veh != ego && veh->getPositionOnLane(this) < egoPos) {
3850 //const double latOffset = veh->getLane()->getRightSideOnEdge() - getRightSideOnEdge();
3851 const double latOffset = veh->getLatOffset(this);
3852 double dist = backOffset - veh->getPositionOnLane(this) - veh->getVehicleType().getMinGap();
3853 if (veh->isBidiOn(this)) {
3854 dist -= veh->getLength();
3855 }
3856 result.addFollower(veh, ego, dist, latOffset);
3857#ifdef DEBUG_CONTEXT
3858 if (DEBUG_COND2(ego)) {
3859 std::cout << " (1) added veh=" << veh->getID() << " latOffset=" << latOffset << " result=" << result.toString() << "\n";
3860 }
3861#endif
3862 }
3863 }
3864#ifdef DEBUG_CONTEXT
3865 if (DEBUG_COND2(ego)) {
3866 std::cout << " result.numFreeSublanes=" << result.numFreeSublanes() << "\n";
3867 }
3868#endif
3869 if (result.numFreeSublanes() > 0) {
3870 // do a tree search among all follower lanes and check for the most
3871 // important vehicle (the one requiring the largest reargap)
3872 // to get a safe bound on the necessary search depth, we need to consider the maximum speed and minimum
3873 // deceleration of potential follower vehicles
3874 if (searchDist == -1) {
3875 searchDist = getMaximumBrakeDist() - backOffset;
3876#ifdef DEBUG_CONTEXT
3877 if (DEBUG_COND2(ego)) {
3878 std::cout << " computed searchDist=" << searchDist << "\n";
3879 }
3880#endif
3881 }
3882 std::set<const MSEdge*> egoFurther;
3883 for (MSLane* further : ego->getFurtherLanes()) {
3884 egoFurther.insert(&further->getEdge());
3885 }
3886 if (ego->getPositionOnLane() < ego->getVehicleType().getLength() && egoFurther.size() == 0
3887 && ego->getLane()->getLogicalPredecessorLane() != nullptr) {
3888 // on insertion
3889 egoFurther.insert(&ego->getLane()->getLogicalPredecessorLane()->getEdge());
3890 }
3891
3892 // avoid loops
3893 std::set<const MSLane*> visited(myEdge->getLanes().begin(), myEdge->getLanes().end());
3894 if (myEdge->getBidiEdge() != nullptr) {
3895 visited.insert(myEdge->getBidiEdge()->getLanes().begin(), myEdge->getBidiEdge()->getLanes().end());
3896 }
3897 std::vector<MSLane::IncomingLaneInfo> newFound;
3898 std::vector<MSLane::IncomingLaneInfo> toExamine = myIncomingLanes;
3899 while (toExamine.size() != 0) {
3900 for (std::vector<MSLane::IncomingLaneInfo>::iterator it = toExamine.begin(); it != toExamine.end(); ++it) {
3901 MSLane* next = (*it).lane;
3902 searchDist = MAX2(searchDist, next->getMaximumBrakeDist() - backOffset);
3903 MSLeaderInfo first = next->getFirstVehicleInformation(nullptr, 0, false, std::numeric_limits<double>::max(), false);
3904 MSLeaderInfo firstFront = next->getFirstVehicleInformation(nullptr, 0, true);
3905#ifdef DEBUG_CONTEXT
3906 if (DEBUG_COND2(ego)) {
3907 std::cout << " next=" << next->getID() << " seen=" << (*it).length << " first=" << first.toString() << " firstFront=" << firstFront.toString() << " backOffset=" << backOffset << "\n";
3908 gDebugFlag1 = true; // for calling getLeaderInfo
3909 }
3910#endif
3911 if (backOffset + (*it).length - next->getLength() < 0
3912 && egoFurther.count(&next->getEdge()) != 0
3913 ) {
3914 // check for junction foes that would interfere with lane changing
3915 // @note: we are passing the back of ego as its front position so
3916 // we need to add this back to the returned gap
3917 const MSLink::LinkLeaders linkLeaders = (*it).viaLink->getLeaderInfo(ego, -backOffset);
3918 for (const auto& ll : linkLeaders) {
3919 if (ll.vehAndGap.first != nullptr) {
3920 const bool bidiFoe = (*it).viaLink->getLane() == ll.vehAndGap.first->getLane()->getNormalPredecessorLane()->getBidiLane();
3921 const bool egoIsLeader = !bidiFoe && ll.vehAndGap.first->isLeader((*it).viaLink, ego, ll.vehAndGap.second);
3922 // if ego is leader the returned gap still assumes that ego follows the leader
3923 // if the foe vehicle follows ego we need to deduce that gap
3924 const double gap = (egoIsLeader
3925 ? -ll.vehAndGap.second - ll.vehAndGap.first->getVehicleType().getLengthWithGap() - ego->getVehicleType().getMinGap()
3926 : ll.vehAndGap.second + ego->getVehicleType().getLength());
3927 result.addFollower(ll.vehAndGap.first, ego, gap);
3928#ifdef DEBUG_CONTEXT
3929 if (DEBUG_COND2(ego)) {
3930 std::cout << SIMTIME << " ego=" << ego->getID() << " link=" << (*it).viaLink->getViaLaneOrLane()->getID()
3931 << " (3) added veh=" << Named::getIDSecure(ll.vehAndGap.first)
3932 << " gap=" << ll.vehAndGap.second << " dtC=" << ll.distToCrossing
3933 << " bidiFoe=" << bidiFoe
3934 << " egoIsLeader=" << egoIsLeader << " gap2=" << gap
3935 << "\n";
3936 }
3937#endif
3938 }
3939 }
3940 }
3941#ifdef DEBUG_CONTEXT
3942 if (DEBUG_COND2(ego)) {
3943 gDebugFlag1 = false;
3944 }
3945#endif
3946
3947 for (int i = 0; i < first.numSublanes(); ++i) {
3948 const MSVehicle* v = first[i] == ego ? firstFront[i] : first[i];
3949 double agap = 0;
3950
3951 if (v != nullptr && v != ego) {
3952 if (!v->isFrontOnLane(next)) {
3953 // the front of v is already on divergent trajectory from the ego vehicle
3954 // for which this method is called (in the context of MSLaneChanger).
3955 // Therefore, technically v is not a follower but only an obstruction and
3956 // the gap is not between the front of v and the back of ego
3957 // but rather between the flank of v and the back of ego.
3958 agap = (*it).length - next->getLength() + backOffset;
3960 // ego should have left the intersection still occupied by v
3961 agap -= v->getVehicleType().getMinGap();
3962 }
3963#ifdef DEBUG_CONTEXT
3964 if (DEBUG_COND2(ego)) {
3965 std::cout << " agap1=" << agap << "\n";
3966 }
3967#endif
3968 const bool differentEdge = &v->getLane()->getEdge() != &ego->getLane()->getEdge();
3969 if (agap > 0 && differentEdge) {
3970 // Only if ego overlaps we treat v as if it were a real follower
3971 // Otherwise we ignore it and look for another follower
3972 if (!getOppositeLeaders) {
3973 // even if the vehicle is not a real
3974 // follower, it still forms a real
3975 // obstruction in opposite direction driving
3976 v = firstFront[i];
3977 if (v != nullptr && v != ego) {
3978 agap = (*it).length - v->getPositionOnLane() + backOffset - v->getVehicleType().getMinGap();
3979 } else {
3980 v = nullptr;
3981 }
3982 }
3983 } else if (differentEdge && result.hasVehicle(v)) {
3984 // ignore this vehicle as it was already seen on another lane
3985 agap = 0;
3986 }
3987 } else {
3988 if (next->getBidiLane() != nullptr && v->isBidiOn(next)) {
3989 agap = v->getPositionOnLane() + backOffset - v->getVehicleType().getLengthWithGap();
3990 } else {
3991 agap = (*it).length - v->getPositionOnLane() + backOffset - v->getVehicleType().getMinGap();
3992 }
3993 if (!(*it).viaLink->havePriority() && egoFurther.count(&(*it).lane->getEdge()) == 0
3994 && ego->isOnRoad() // during insertion, this can lead to collisions because ego's further lanes are not set (see #3053)
3995 && !ego->getLaneChangeModel().isOpposite()
3997 ) {
3998 // if v is stopped on a minor side road it should not block lane changing
3999 agap = MAX2(agap, 0.0);
4000 }
4001 }
4002 result.addFollower(v, ego, agap, 0, i);
4003#ifdef DEBUG_CONTEXT
4004 if (DEBUG_COND2(ego)) {
4005 std::cout << " (2) added veh=" << Named::getIDSecure(v) << " agap=" << agap << " next=" << next->getID() << " result=" << result.toString() << "\n";
4006 }
4007#endif
4008 }
4009 }
4010 if ((*it).length < searchDist) {
4011 const std::vector<MSLane::IncomingLaneInfo>& followers = next->getIncomingLanes();
4012 for (std::vector<MSLane::IncomingLaneInfo>::const_iterator j = followers.begin(); j != followers.end(); ++j) {
4013 if (visited.find((*j).lane) == visited.end() && (((*j).viaLink->havePriority() && !(*j).viaLink->isTurnaround())
4014 || mLinkMode == MinorLinkMode::FOLLOW_ALWAYS
4015 || (mLinkMode == MinorLinkMode::FOLLOW_ONCOMING && (*j).viaLink->getDirection() == LinkDirection::STRAIGHT))) {
4016 visited.insert((*j).lane);
4018 ili.lane = (*j).lane;
4019 ili.length = (*j).length + (*it).length;
4020 ili.viaLink = (*j).viaLink;
4021 newFound.push_back(ili);
4022 }
4023 }
4024 }
4025 }
4026 toExamine.clear();
4027 swap(newFound, toExamine);
4028 }
4029 //return result;
4030
4031 }
4032 return result;
4033}
4034
4035
4036void
4037MSLane::getLeadersOnConsecutive(double dist, double seen, double speed, const MSVehicle* ego,
4038 const std::vector<MSLane*>& bestLaneConts, MSLeaderDistanceInfo& result,
4039 bool oppositeDirection) const {
4040 if (seen > dist && !(isInternal() && MSGlobals::gComputeLC)) {
4041 return;
4042 }
4043 // check partial vehicles (they might be on a different route and thus not
4044 // found when iterating along bestLaneConts)
4045 for (VehCont::const_iterator it = myPartialVehicles.begin(); it != myPartialVehicles.end(); ++it) {
4046 MSVehicle* veh = *it;
4047 if (!veh->isFrontOnLane(this)) {
4048 result.addLeader(veh, seen, veh->getLatOffset(this));
4049 } else {
4050 break;
4051 }
4052 }
4053#ifdef DEBUG_CONTEXT
4054 if (DEBUG_COND2(ego)) {
4055 gDebugFlag1 = true;
4056 }
4057#endif
4058 const MSLane* nextLane = this;
4059 int view = 1;
4060 // loop over following lanes
4061 while ((seen < dist || nextLane->isInternal()) && result.numFreeSublanes() > 0) {
4062 // get the next link used
4063 bool nextInternal = false;
4064 if (oppositeDirection) {
4065 if (view >= (int)bestLaneConts.size()) {
4066 break;
4067 }
4068 nextLane = bestLaneConts[view];
4069 } else {
4070 std::vector<MSLink*>::const_iterator link = succLinkSec(*ego, view, *nextLane, bestLaneConts);
4071 if (nextLane->isLinkEnd(link)) {
4072 break;
4073 }
4074 // check for link leaders
4075 const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(ego, seen);
4076 if (linkLeaders.size() > 0) {
4077 const MSLink::LinkLeader ll = linkLeaders[0];
4078 MSVehicle* veh = ll.vehAndGap.first;
4079 // in the context of lane changing all junction leader candidates must be respected
4080 if (veh != 0 && (ego->isLeader(*link, veh, ll.vehAndGap.second)
4083 < veh->getCarFollowModel().brakeGap(veh->getSpeed())))) {
4084#ifdef DEBUG_CONTEXT
4085 if (DEBUG_COND2(ego)) {
4086 std::cout << " linkleader=" << veh->getID() << " gap=" << ll.vehAndGap.second << " leaderOffset=" << ll.latOffset << " flags=" << ll.llFlags << "\n";
4087 }
4088#endif
4089 if (ll.sameTarget() || ll.sameSource()) {
4090 result.addLeader(veh, ll.vehAndGap.second, ll.latOffset);
4091 } else {
4092 // add link leader to all sublanes and return
4093 for (int i = 0; i < result.numSublanes(); ++i) {
4094 result.addLeader(veh, ll.vehAndGap.second, 0, i);
4095 }
4096 }
4097#ifdef DEBUG_CONTEXT
4098 gDebugFlag1 = false;
4099#endif
4100 return;
4101 } // XXX else, deal with pedestrians
4102 }
4103 nextInternal = (*link)->getViaLane() != nullptr;
4104 nextLane = (*link)->getViaLaneOrLane();
4105 if (nextLane == nullptr) {
4106 break;
4107 }
4108 }
4109
4110 MSLeaderInfo leaders = nextLane->getLastVehicleInformation(nullptr, 0, 0, false);
4111#ifdef DEBUG_CONTEXT
4112 if (DEBUG_COND2(ego)) {
4113 std::cout << SIMTIME << " getLeadersOnConsecutive lane=" << getID() << " nextLane=" << nextLane->getID() << " leaders=" << leaders.toString() << "\n";
4114 }
4115#endif
4116 // @todo check alignment issues if the lane width changes
4117 const int iMax = MIN2(leaders.numSublanes(), result.numSublanes());
4118 for (int i = 0; i < iMax; ++i) {
4119 const MSVehicle* veh = leaders[i];
4120 if (veh != nullptr) {
4121#ifdef DEBUG_CONTEXT
4122 if (DEBUG_COND2(ego)) std::cout << " lead=" << veh->getID()
4123 << " seen=" << seen
4124 << " minGap=" << ego->getVehicleType().getMinGap()
4125 << " backPos=" << veh->getBackPositionOnLane(nextLane)
4126 << " gap=" << seen - ego->getVehicleType().getMinGap() + veh->getBackPositionOnLane(nextLane)
4127 << "\n";
4128#endif
4129 result.addLeader(veh, seen - ego->getVehicleType().getMinGap() + veh->getBackPositionOnLane(nextLane), 0, i);
4130 }
4131 }
4132
4133 if (nextLane->getVehicleMaxSpeed(ego) < speed) {
4134 dist = ego->getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(ego));
4135 }
4136 seen += nextLane->getLength();
4137 if (!nextInternal) {
4138 view++;
4139 }
4140 }
4141#ifdef DEBUG_CONTEXT
4142 gDebugFlag1 = false;
4143#endif
4144}
4145
4146
4147void
4148MSLane::addLeaders(const MSVehicle* vehicle, double vehPos, MSLeaderDistanceInfo& result, bool opposite) {
4149 // if there are vehicles on the target lane with the same position as ego,
4150 // they may not have been added to 'ahead' yet
4151#ifdef DEBUG_SURROUNDING
4152 if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4153 std::cout << " addLeaders lane=" << getID() << " veh=" << vehicle->getID() << " vehPos=" << vehPos << " opposite=" << opposite << "\n";
4154 }
4155#endif
4156 const MSLeaderInfo& aheadSamePos = getLastVehicleInformation(nullptr, 0, vehPos, false);
4157 for (int i = 0; i < aheadSamePos.numSublanes(); ++i) {
4158 const MSVehicle* veh = aheadSamePos[i];
4159 if (veh != nullptr && veh != vehicle) {
4160 const double gap = veh->getBackPositionOnLane(this) - vehPos - vehicle->getVehicleType().getMinGap();
4161#ifdef DEBUG_SURROUNDING
4162 if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4163 std::cout << " further lead=" << veh->getID() << " leadBack=" << veh->getBackPositionOnLane(this) << " gap=" << gap << "\n";
4164 }
4165#endif
4166 result.addLeader(veh, gap, 0, i);
4167 }
4168 }
4169
4170 if (result.numFreeSublanes() > 0) {
4171 double seen = vehicle->getLane()->getLength() - vehPos;
4172 double speed = vehicle->getSpeed();
4173 // leader vehicle could be link leader on the next junction
4174 double dist = MAX2(vehicle->getCarFollowModel().brakeGap(speed), 10.0) + vehicle->getVehicleType().getMinGap();
4175 if (getBidiLane() != nullptr) {
4176 dist = MAX2(dist, myMaxSpeed * 20);
4177 }
4178 // check for link leaders when on internal
4179 if (seen > dist && !(isInternal() && MSGlobals::gComputeLC)) {
4180#ifdef DEBUG_SURROUNDING
4181 if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4182 std::cout << " aborting forward search. dist=" << dist << " seen=" << seen << "\n";
4183 }
4184#endif
4185 return;
4186 }
4187#ifdef DEBUG_SURROUNDING
4188 if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4189 std::cout << " add consecutive before=" << result.toString() << " seen=" << seen << " dist=" << dist;
4190 }
4191#endif
4192 if (opposite) {
4193 const std::vector<MSLane*> bestLaneConts = vehicle->getUpstreamOppositeLanes();
4194#ifdef DEBUG_SURROUNDING
4195 if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4196 std::cout << " upstreamOpposite=" << toString(bestLaneConts);
4197 }
4198#endif
4199 getLeadersOnConsecutive(dist, seen, speed, vehicle, bestLaneConts, result, opposite);
4200 } else {
4201 const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation(this);
4202 getLeadersOnConsecutive(dist, seen, speed, vehicle, bestLaneConts, result);
4203 }
4204#ifdef DEBUG_SURROUNDING
4205 if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4206 std::cout << " after=" << result.toString() << "\n";
4207 }
4208#endif
4209 }
4210}
4211
4212
4213MSVehicle*
4215 for (VehCont::const_reverse_iterator i = myPartialVehicles.rbegin(); i != myPartialVehicles.rend(); ++i) {
4216 MSVehicle* veh = *i;
4217 if (veh->isFrontOnLane(this)
4218 && veh != ego
4219 && veh->getPositionOnLane() <= ego->getPositionOnLane()) {
4220#ifdef DEBUG_CONTEXT
4221 if (DEBUG_COND2(ego)) {
4222 std::cout << SIMTIME << " getPartialBehind lane=" << getID() << " ego=" << ego->getID() << " found=" << veh->getID() << "\n";
4223 }
4224#endif
4225 return veh;
4226 }
4227 }
4228#ifdef DEBUG_CONTEXT
4229 if (DEBUG_COND2(ego)) {
4230 std::cout << SIMTIME << " getPartialBehind lane=" << getID() << " ego=" << ego->getID() << " nothing found. partials=" << toString(myPartialVehicles) << "\n";
4231 }
4232#endif
4233 return nullptr;
4234}
4235
4238 MSLeaderInfo result(myWidth);
4239 for (VehCont::const_iterator it = myPartialVehicles.begin(); it != myPartialVehicles.end(); ++it) {
4240 MSVehicle* veh = *it;
4241 if (!veh->isFrontOnLane(this)) {
4242 result.addLeader(veh, false, veh->getLatOffset(this));
4243 } else {
4244 break;
4245 }
4246 }
4247 return result;
4248}
4249
4250
4251std::set<MSVehicle*>
4252MSLane::getSurroundingVehicles(double startPos, double downstreamDist, double upstreamDist, std::shared_ptr<LaneCoverageInfo> checkedLanes) const {
4253 assert(checkedLanes != nullptr);
4254 if (checkedLanes->find(this) != checkedLanes->end()) {
4255#ifdef DEBUG_SURROUNDING
4256 std::cout << "Skipping previously scanned lane: " << getID() << std::endl;
4257#endif
4258 return std::set<MSVehicle*>();
4259 } else {
4260 // Add this lane's coverage to the lane coverage info
4261 (*checkedLanes)[this] = std::make_pair(MAX2(0.0, startPos - upstreamDist), MIN2(startPos + downstreamDist, getLength()));
4262 }
4263#ifdef DEBUG_SURROUNDING
4264 std::cout << "Scanning on lane " << myID << "(downstr. " << downstreamDist << ", upstr. " << upstreamDist << ", startPos " << startPos << "): " << std::endl;
4265#endif
4266 std::set<MSVehicle*> foundVehicles = getVehiclesInRange(MAX2(0., startPos - upstreamDist), MIN2(myLength, startPos + downstreamDist));
4267 if (startPos < upstreamDist) {
4268 // scan incoming lanes
4269 for (const IncomingLaneInfo& incomingInfo : getIncomingLanes()) {
4270 MSLane* incoming = incomingInfo.lane;
4271#ifdef DEBUG_SURROUNDING
4272 std::cout << "Checking on incoming: " << incoming->getID() << std::endl;
4273 if (checkedLanes->find(incoming) != checkedLanes->end()) {
4274 std::cout << "Skipping previous: " << incoming->getID() << std::endl;
4275 }
4276#endif
4277 std::set<MSVehicle*> newVehs = incoming->getSurroundingVehicles(incoming->getLength(), 0.0, upstreamDist - startPos, checkedLanes);
4278 foundVehicles.insert(newVehs.begin(), newVehs.end());
4279 }
4280 }
4281
4282 if (getLength() < startPos + downstreamDist) {
4283 // scan successive lanes
4284 const std::vector<MSLink*>& lc = getLinkCont();
4285 for (MSLink* l : lc) {
4286#ifdef DEBUG_SURROUNDING
4287 std::cout << "Checking on outgoing: " << l->getViaLaneOrLane()->getID() << std::endl;
4288#endif
4289 std::set<MSVehicle*> newVehs = l->getViaLaneOrLane()->getSurroundingVehicles(0.0, downstreamDist - (myLength - startPos), upstreamDist, checkedLanes);
4290 foundVehicles.insert(newVehs.begin(), newVehs.end());
4291 }
4292 }
4293#ifdef DEBUG_SURROUNDING
4294 std::cout << "On lane (2) " << myID << ": \nFound vehicles: " << std::endl;
4295 for (MSVehicle* v : foundVehicles) {
4296 std::cout << v->getID() << " pos = " << v->getPositionOnLane() << std::endl;
4297 }
4298#endif
4299 return foundVehicles;
4300}
4301
4302
4303std::set<MSVehicle*>
4304MSLane::getVehiclesInRange(const double a, const double b) const {
4305 std::set<MSVehicle*> res;
4306 const VehCont& vehs = getVehiclesSecure();
4307
4308 if (!vehs.empty()) {
4309 for (MSVehicle* const veh : vehs) {
4310 if (veh->getPositionOnLane() >= a) {
4311 if (veh->getBackPositionOnLane() > b) {
4312 break;
4313 }
4314 res.insert(veh);
4315 }
4316 }
4317 }
4319 return res;
4320}
4321
4322
4323std::vector<const MSJunction*>
4324MSLane::getUpcomingJunctions(double pos, double range, const std::vector<MSLane*>& contLanes) const {
4325 // set of upcoming junctions and the corresponding conflict links
4326 std::vector<const MSJunction*> junctions;
4327 for (auto l : getUpcomingLinks(pos, range, contLanes)) {
4328 junctions.insert(junctions.end(), l->getJunction());
4329 }
4330 return junctions;
4331}
4332
4333
4334std::vector<const MSLink*>
4335MSLane::getUpcomingLinks(double pos, double range, const std::vector<MSLane*>& contLanes) const {
4336#ifdef DEBUG_SURROUNDING
4337 std::cout << "getUpcoming links on lane '" << getID() << "' with pos=" << pos
4338 << " range=" << range << std::endl;
4339#endif
4340 // set of upcoming junctions and the corresponding conflict links
4341 std::vector<const MSLink*> links;
4342
4343 // Currently scanned lane
4344 const MSLane* lane = this;
4345
4346 // continuation lanes for the vehicle
4347 std::vector<MSLane*>::const_iterator contLanesIt = contLanes.begin();
4348 // scanned distance so far
4349 double dist = 0.0;
4350 // link to be crossed by the vehicle
4351 const MSLink* link = nullptr;
4352 if (lane->isInternal()) {
4353 assert(*contLanesIt == nullptr); // is called with vehicle's bestLane structure
4354 link = lane->getEntryLink();
4355 links.insert(links.end(), link);
4356 dist += link->getInternalLengthsAfter();
4357 // next non-internal lane behind junction
4358 lane = link->getLane();
4359 pos = 0.0;
4360 assert(*(contLanesIt + 1) == lane);
4361 }
4362 while (++contLanesIt != contLanes.end()) {
4363 assert(!lane->isInternal());
4364 dist += lane->getLength() - pos;
4365 pos = 0.;
4366#ifdef DEBUG_SURROUNDING
4367 std::cout << "Distance until end of lane '" << lane->getID() << "' is " << dist << "." << std::endl;
4368#endif
4369 if (dist > range) {
4370 break;
4371 }
4372 link = lane->getLinkTo(*contLanesIt);
4373 if (link != nullptr) {
4374 links.insert(links.end(), link);
4375 }
4376 lane = *contLanesIt;
4377 }
4378 return links;
4379}
4380
4381
4382MSLane*
4384 return myOpposite;
4385}
4386
4387
4388MSLane*
4390 return myEdge->getLanes().back()->getOpposite();
4391}
4392
4393
4394double
4395MSLane::getOppositePos(double pos) const {
4396 return MAX2(0., myLength - pos);
4397}
4398
4399std::pair<MSVehicle* const, double>
4400MSLane::getFollower(const MSVehicle* ego, double egoPos, double dist, MinorLinkMode mLinkMode) const {
4401 for (AnyVehicleIterator first = anyVehiclesUpstreamBegin(); first != anyVehiclesUpstreamEnd(); ++first) {
4402 // XXX refactor leaderInfo to use a const vehicle all the way through the call hierarchy
4403 MSVehicle* pred = (MSVehicle*)*first;
4404#ifdef DEBUG_CONTEXT
4405 if (DEBUG_COND2(ego)) {
4406 std::cout << " getFollower lane=" << getID() << " egoPos=" << egoPos << " pred=" << pred->getID() << " predPos=" << pred->getPositionOnLane(this) << "\n";
4407 }
4408#endif
4409 if (pred != ego && pred->getPositionOnLane(this) < egoPos) {
4410 return std::pair<MSVehicle* const, double>(pred, egoPos - pred->getPositionOnLane(this) - ego->getVehicleType().getLength() - pred->getVehicleType().getMinGap());
4411 }
4412 }
4413 const double backOffset = egoPos - ego->getVehicleType().getLength();
4414 if (dist > 0 && backOffset > dist) {
4415 return std::make_pair(nullptr, -1);
4416 }
4417 const MSLeaderDistanceInfo followers = getFollowersOnConsecutive(ego, backOffset, true, dist, mLinkMode);
4418 CLeaderDist result = followers.getClosest();
4419 return std::make_pair(const_cast<MSVehicle*>(result.first), result.second);
4420}
4421
4422std::pair<MSVehicle* const, double>
4423MSLane::getOppositeLeader(const MSVehicle* ego, double dist, bool oppositeDir, MinorLinkMode mLinkMode) const {
4424#ifdef DEBUG_OPPOSITE
4425 if (DEBUG_COND2(ego)) std::cout << SIMTIME << " getOppositeLeader lane=" << getID()
4426 << " ego=" << ego->getID()
4427 << " pos=" << ego->getPositionOnLane()
4428 << " posOnOpposite=" << getOppositePos(ego->getPositionOnLane())
4429 << " dist=" << dist
4430 << " oppositeDir=" << oppositeDir
4431 << "\n";
4432#endif
4433 if (!oppositeDir) {
4434 return getLeader(ego, getOppositePos(ego->getPositionOnLane()), ego->getBestLanesContinuation(this));
4435 } else {
4436 const double egoLength = ego->getVehicleType().getLength();
4437 const double egoPos = ego->getLaneChangeModel().isOpposite() ? ego->getPositionOnLane() : getOppositePos(ego->getPositionOnLane());
4438 std::pair<MSVehicle* const, double> result = getFollower(ego, egoPos + egoLength, dist, mLinkMode);
4439 if (result.first != nullptr) {
4440 result.second -= ego->getVehicleType().getMinGap();
4441 if (result.first->getLaneChangeModel().isOpposite()) {
4442 result.second -= result.first->getVehicleType().getLength();
4443 }
4444 }
4445 return result;
4446 }
4447}
4448
4449
4450std::pair<MSVehicle* const, double>
4452#ifdef DEBUG_OPPOSITE
4453 if (DEBUG_COND2(ego)) std::cout << SIMTIME << " getOppositeFollower lane=" << getID()
4454 << " ego=" << ego->getID()
4455 << " backPos=" << ego->getBackPositionOnLane()
4456 << " posOnOpposite=" << getOppositePos(ego->getBackPositionOnLane())
4457 << "\n";
4458#endif
4459 if (ego->getLaneChangeModel().isOpposite()) {
4460 std::pair<MSVehicle* const, double> result = getFollower(ego, getOppositePos(ego->getPositionOnLane()), -1, MinorLinkMode::FOLLOW_NEVER);
4461 return result;
4462 } else {
4463 double vehPos = getOppositePos(ego->getPositionOnLane() - ego->getVehicleType().getLength());
4464 std::pair<MSVehicle*, double> result = getLeader(ego, vehPos, std::vector<MSLane*>());
4465 double dist = getMaximumBrakeDist() + getOppositePos(ego->getPositionOnLane() - getLength());
4466 MSLane* next = const_cast<MSLane*>(this);
4467 while (result.first == nullptr && dist > 0) {
4468 // cannot call getLeadersOnConsecutive because succLinkSec doesn't
4469 // uses the vehicle's route and doesn't work on the opposite side
4470 vehPos -= next->getLength();
4471 next = next->getCanonicalSuccessorLane();
4472 if (next == nullptr) {
4473 break;
4474 }
4475 dist -= next->getLength();
4476 result = next->getLeader(ego, vehPos, std::vector<MSLane*>());
4477 }
4478 if (result.first != nullptr) {
4479 if (result.first->getLaneChangeModel().isOpposite()) {
4480 result.second -= result.first->getVehicleType().getLength();
4481 } else {
4482 if (result.second > POSITION_EPS) {
4483 // follower can be safely ignored since it is going the other way
4484 return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
4485 }
4486 }
4487 }
4488 return result;
4489 }
4490}
4491
4492void
4493MSLane::initCollisionAction(const OptionsCont& oc, const std::string& option, CollisionAction& myAction) {
4494 const std::string action = oc.getString(option);
4495 if (action == "none") {
4496 myAction = COLLISION_ACTION_NONE;
4497 } else if (action == "warn") {
4498 myAction = COLLISION_ACTION_WARN;
4499 } else if (action == "teleport") {
4500 myAction = COLLISION_ACTION_TELEPORT;
4501 } else if (action == "remove") {
4502 myAction = COLLISION_ACTION_REMOVE;
4503 } else {
4504 WRITE_ERROR(TLF("Invalid % '%'.", option, action));
4505 }
4506}
4507
4508void
4510 initCollisionAction(oc, "collision.action", myCollisionAction);
4511 initCollisionAction(oc, "intermodal-collision.action", myIntermodalCollisionAction);
4512 myCheckJunctionCollisions = oc.getBool("collision.check-junctions");
4513 myCheckJunctionCollisionMinGap = oc.getFloat("collision.check-junctions.mingap");
4514 myCollisionStopTime = string2time(oc.getString("collision.stoptime"));
4515 myIntermodalCollisionStopTime = string2time(oc.getString("intermodal-collision.stoptime"));
4516 myCollisionMinGapFactor = oc.getFloat("collision.mingap-factor");
4517 myExtrapolateSubstepDepart = oc.getBool("extrapolate-departpos");
4518}
4519
4520
4521void
4522MSLane::setPermissions(SVCPermissions permissions, long long transientID) {
4523 if (transientID == CHANGE_PERMISSIONS_PERMANENT) {
4524 myPermissions = permissions;
4525 myOriginalPermissions = permissions;
4526 } else {
4527 myPermissionChanges[transientID] = permissions;
4529 }
4530}
4531
4532
4533void
4534MSLane::resetPermissions(long long transientID) {
4535 myPermissionChanges.erase(transientID);
4536 if (myPermissionChanges.empty()) {
4538 } else {
4539 // combine all permission changes
4541 for (const auto& item : myPermissionChanges) {
4542 myPermissions &= item.second;
4543 }
4544 }
4545}
4546
4547
4548bool
4550 return !myPermissionChanges.empty();
4551}
4552
4553
4554void
4556 myChangeLeft = permissions;
4557}
4558
4559
4560void
4562 myChangeRight = permissions;
4563}
4564
4565
4566bool
4568 MSNet* const net = MSNet::getInstance();
4569 return net->hasPersons() && net->getPersonControl().getMovementModel()->hasPedestrians(this);
4570}
4571
4572
4574MSLane::nextBlocking(double minPos, double minRight, double maxLeft, double stopTime, bool bidi) const {
4575 return MSNet::getInstance()->getPersonControl().getMovementModel()->nextBlocking(this, minPos, minRight, maxLeft, stopTime, bidi);
4576}
4577
4578
4579bool
4580MSLane::checkForPedestrians(const MSVehicle* aVehicle, double& speed, double& dist, double pos, bool patchSpeed) const {
4581 if (getEdge().getPersons().size() > 0 && hasPedestrians()) {
4582#ifdef DEBUG_INSERTION
4583 if (DEBUG_COND2(aVehicle)) {
4584 std::cout << SIMTIME << " check for pedestrians on lane=" << getID() << " pos=" << pos << "\n";
4585 }
4586#endif
4587 PersonDist leader = nextBlocking(pos - aVehicle->getVehicleType().getLength(),
4588 aVehicle->getRightSideOnLane(), aVehicle->getRightSideOnLane() + aVehicle->getVehicleType().getWidth(), ceil(speed / aVehicle->getCarFollowModel().getMaxDecel()));
4589 if (leader.first != 0) {
4590 const double gap = leader.second - aVehicle->getVehicleType().getLengthWithGap();
4591 const double stopSpeed = aVehicle->getCarFollowModel().stopSpeed(aVehicle, speed, gap, MSCFModel::CalcReason::FUTURE);
4592 if ((gap < 0 && (aVehicle->getInsertionChecks() & ((int)InsertionCheck::COLLISION | (int)InsertionCheck::PEDESTRIAN)) != 0)
4593 || checkFailure(aVehicle, speed, dist, stopSpeed, patchSpeed, "", InsertionCheck::PEDESTRIAN)) {
4594 // we may not drive with the given velocity - we crash into the pedestrian
4595#ifdef DEBUG_INSERTION
4596 if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
4597 << " isInsertionSuccess lane=" << getID()
4598 << " veh=" << aVehicle->getID()
4599 << " pos=" << pos
4600 << " posLat=" << aVehicle->getLateralPositionOnLane()
4601 << " patchSpeed=" << patchSpeed
4602 << " speed=" << speed
4603 << " stopSpeed=" << stopSpeed
4604 << " pedestrianLeader=" << leader.first->getID()
4605 << " failed (@796)!\n";
4606#endif
4607 return false;
4608 }
4609 }
4610 }
4611 double backLength = aVehicle->getLength() - pos;
4612 if (backLength > 0 && MSNet::getInstance()->hasPersons()) {
4613 // look upstream for pedestrian crossings
4614 const MSLane* prev = getLogicalPredecessorLane();
4615 const MSLane* cur = this;
4616 while (backLength > 0 && prev != nullptr) {
4617 const MSLink* link = prev->getLinkTo(cur);
4618 if (link->hasFoeCrossing()) {
4619 for (const MSLane* foe : link->getFoeLanes()) {
4620 if (foe->isCrossing() && (foe->hasPedestrians() ||
4621 (foe->getIncomingLanes()[0].viaLink->getApproachingPersons() != nullptr
4622 && foe->getIncomingLanes()[0].viaLink->getApproachingPersons()->size() > 0))) {
4623#ifdef DEBUG_INSERTION
4624 if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
4625 << " isInsertionSuccess lane=" << getID()
4626 << " veh=" << aVehicle->getID()
4627 << " pos=" << pos
4628 << " backCrossing=" << foe->getID()
4629 << " peds=" << joinNamedToString(foe->getEdge().getPersons(), " ")
4630 << " approaching=" << foe->getIncomingLanes()[0].viaLink->getApproachingPersons()->size()
4631 << " failed (@4550)!\n";
4632#endif
4633 return false;
4634 }
4635 }
4636 }
4637 backLength -= prev->getLength();
4638 cur = prev;
4639 prev = prev->getLogicalPredecessorLane();
4640 }
4641 }
4642 return true;
4643}
4644
4645
4646void
4648 myRNGs.clear();
4649 const int numRNGs = oc.getInt("thread-rngs");
4650 const bool random = oc.getBool("random");
4651 int seed = oc.getInt("seed");
4652 myRNGs.reserve(numRNGs); // this is needed for stable pointers on debugging
4653 for (int i = 0; i < numRNGs; i++) {
4654 myRNGs.push_back(SumoRNG("lanes_" + toString(i)));
4655 RandHelper::initRand(&myRNGs.back(), random, seed++);
4656 }
4657}
4658
4659void
4661 for (int i = 0; i < getNumRNGs(); i++) {
4663 out.writeAttr(SUMO_ATTR_INDEX, i);
4665 out.closeTag();
4666 }
4667}
4668
4669void
4670MSLane::loadRNGState(int index, const std::string& state) {
4671 if (index >= getNumRNGs()) {
4672 throw ProcessError(TLF("State was saved with more than % threads. Change the number of threads or do not load RNG state", toString(getNumRNGs())));
4673 }
4674 RandHelper::loadState(state, &myRNGs[index]);
4675}
4676
4677
4678MSLane*
4680 return myBidiLane;
4681}
4682
4683
4684bool
4687 myLinks.front()->getFoeLanes().size() > 0
4688 || myLinks.front()->getWalkingAreaFoe() != nullptr
4689 || myLinks.front()->getWalkingAreaFoeExit() != nullptr);
4690}
4691
4692
4693double
4694MSLane::getSpaceTillLastStanding(const MSVehicle* ego, bool& foundStopped) const {
4696 double lengths = 0;
4697 for (const MSVehicle* last : myVehicles) {
4698 if (last->getSpeed() < SUMO_const_haltingSpeed && !last->getLane()->getEdge().isRoundabout()
4699 && last != ego
4700 // @todo recheck
4701 && last->isFrontOnLane(this)) {
4702 foundStopped = true;
4703 const double lastBrakeGap = last->getCarFollowModel().brakeGap(last->getSpeed());
4704 const double ret = last->getBackPositionOnLane() + lastBrakeGap - lengths;
4705 return ret;
4706 }
4707 if (MSGlobals::gSublane && ego->getVehicleType().getWidth() + last->getVehicleType().getWidth() < getWidth()) {
4708 lengths += last->getVehicleType().getLengthWithGap() * (last->getVehicleType().getWidth() + last->getVehicleType().getMinGapLat()) / getWidth();
4709 } else {
4710 lengths += last->getVehicleType().getLengthWithGap();
4711 }
4712 }
4713 return getLength() - lengths;
4714}
4715
4716
4717bool
4718MSLane::allowsVehicleClass(SUMOVehicleClass vclass, int routingMode) const {
4719 return (((routingMode & libsumo::ROUTING_MODE_IGNORE_TRANSIENT_PERMISSIONS) ? myOriginalPermissions : myPermissions) & vclass) == vclass;
4720}
4721
4722
4723const MSJunction*
4725 return myEdge->getFromJunction();
4726}
4727
4728
4729const MSJunction*
4731 return myEdge->getToJunction();
4732}
4733
4734/****************************************************************************/
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:1811
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_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:902
bool isCrossing() const
return whether this edge is a pedestrian crossing
Definition MSEdge.h:273
int getPriority() const
Returns the priority of the edge.
Definition MSEdge.h:336
const std::set< MSTransportable *, ComparatorNumericalIdLess > & getPersons() const
Returns this edge's persons set.
Definition MSEdge.h:204
bool isWalkingArea() const
return whether this edge is walking area
Definition MSEdge.h:287
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition MSEdge.h:168
const MSEdge * getNormalSuccessor() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
Definition MSEdge.cpp:957
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:482
const MSEdge * getBidiEdge() const
return opposite superposable/congruent edge, if it exist and 0 else
Definition MSEdge.h:282
bool isNormal() const
return whether this edge is an internal edge
Definition MSEdge.h:263
std::vector< MSTransportable * > getSortedPersons(SUMOTime timestep, bool includeRiding=false) const
Returns this edge's persons sorted by pos.
Definition MSEdge.cpp:1216
void recalcCache()
Recalculates the cached values.
Definition MSEdge.cpp:122
bool hasLaneChanger() const
Definition MSEdge.h:746
const MSJunction * getToJunction() const
Definition MSEdge.h:426
const MSJunction * getFromJunction() const
Definition MSEdge.h:422
int getNumLanes() const
Definition MSEdge.h:172
bool isInternal() const
return whether this edge is an internal edge
Definition MSEdge.h:268
bool isVaporizing() const
Returns whether vehicles on this edge shall be vaporized.
Definition MSEdge.h:442
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:465
const std::string & getEdgeType() const
Returns the type of the edge.
Definition MSEdge.h:319
void markDelayed() const
Definition MSEdge.h:737
const MSEdgeVector & getPredecessors() const
Definition MSEdge.h:417
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:1696
by_connections_to_sorter(const MSEdge *const e)
constructor
Definition MSLane.cpp:3525
int operator()(const MSEdge *const e1, const MSEdge *const e2) const
comparing operator
Definition MSLane.cpp:3532
Sorts lanes (IncomingLaneInfos) by their priority or, if this doesn't apply, wrt. the angle differenc...
Definition MSLane.h:1715
incoming_lane_priority_sorter(const MSLane *targetLane)
constructor
Definition MSLane.cpp:3566
int operator()(const IncomingLaneInfo &lane1, const IncomingLaneInfo &lane2) const
comparing operator
Definition MSLane.cpp:3571
Sorts lanes (their origin link) by the priority of their noninternal target edges or,...
Definition MSLane.h:1733
outgoing_lane_priority_sorter(const MSLane *sourceLane)
constructor
Definition MSLane.cpp:3644
int operator()(const MSLink *link1, const MSLink *link2) const
comparing operator
Definition MSLane.cpp:3648
int operator()(MSVehicle *v1, MSVehicle *v2) const
Comparing operator.
Definition MSLane.cpp:3514
Sorts vehicles by their position (descending)
Definition MSLane.h:1650
int operator()(MSVehicle *v1, MSVehicle *v2) const
Comparing operator.
Definition MSLane.cpp:3502
Representation of a lane in the micro simulation.
Definition MSLane.h:84
void addApproachingLane(MSLane *lane, bool warnMultiCon)
Definition MSLane.cpp:2866
void loadState(const std::vector< SUMOVehicle * > &vehs)
Loads the state of this segment with the given parameters.
Definition MSLane.cpp:3763
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:1641
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:1497
SVCPermissions myPermissions
The vClass permissions for this lane.
Definition MSLane.h:1538
MSLane * myLogicalPredecessorLane
Definition MSLane.h:1554
static void initCollisionAction(const OptionsCont &oc, const std::string &option, CollisionAction &myAction)
Definition MSLane.cpp:4493
std::set< const MSBaseVehicle * > myParkingVehicles
Definition MSLane.h:1510
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:4580
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:4400
static double myDefaultDepartSpeed
Definition MSLane.h:1645
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:4574
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:2850
double myRightSideOnEdge
the combined width of all lanes with lower index on myEdge
Definition MSLane.h:1604
const StopOffset & getLaneStopOffsets() const
Returns vehicle class specific stopOffsets.
Definition MSLane.cpp:3791
virtual void removeParking(MSBaseVehicle *veh)
remove parking vehicle. This must be syncrhonized when running with GUI
Definition MSLane.cpp:3689
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:1513
bool isApproachedFrom(MSEdge *const edge)
Definition MSLane.h:963
double getNettoOccupancy() const
Returns the netto (excluding minGaps) occupancy of this lane during the last step (including minGaps)
Definition MSLane.cpp:3411
virtual MSVehicle * removeVehicle(MSVehicle *remVehicle, MSMoveReminder::Notification notification, bool notify=true)
Definition MSLane.cpp:2832
int getCrossingIndex() const
return the index of the link to the next crossing if this is walkingArea, else -1
Definition MSLane.cpp:3366
PositionVector myShape
The shape of the lane.
Definition MSLane.h:1458
PositionVector * myOutlineShape
the outline of the lane (optional)
Definition MSLane.h:1461
std::map< long long, SVCPermissions > myPermissionChanges
Definition MSLane.h:1618
const std::map< SUMOVehicleClass, double > * myRestrictions
The vClass speed restrictions for this lane.
Definition MSLane.h:1548
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:1633
bool hasApproaching() const
Definition MSLane.cpp:3694
void addParking(MSBaseVehicle *veh)
add parking vehicle. This should only used during state loading
Definition MSLane.cpp:3683
VehCont myTmpVehicles
Container for lane-changing vehicles. After completion of lane-change- process, the containers will b...
Definition MSLane.h:1493
static DepartSpeedDefinition myDefaultDepartSpeedDefinition
Definition MSLane.h:1644
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:1587
const MSLane * getNormalSuccessorLane() const
get normal lane following this internal lane, for normal lanes, the lane itself is returned
Definition MSLane.cpp:3251
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:1640
static CollisionAction myCollisionAction
the action to take on collisions
Definition MSLane.h:1636
MSLane * myCanonicalSuccessorLane
Main successor lane,.
Definition MSLane.h:1560
SVCPermissions myChangeLeft
The vClass permissions for changing from this lane.
Definition MSLane.h:1541
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:4037
std::vector< IncomingLaneInfo > myIncomingLanes
All direct predecessor lanes.
Definition MSLane.h:1551
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:4549
void sortPartialVehicles()
sorts myPartialVehicles
Definition MSLane.cpp:2593
double myFrictionCoefficient
Lane-wide friction coefficient [0..1].
Definition MSLane.h:1529
MSVehicle * getFirstAnyVehicle() const
returns the first vehicle that is fully or partially on this lane
Definition MSLane.cpp:2680
const MSLink * getEntryLink() const
Returns the entry link if this is an internal lane, else nullptr.
Definition MSLane.cpp:2768
int getVehicleNumberWithPartials() const
Returns the number of vehicles on this lane (including partial occupators)
Definition MSLane.h:464
static bool myCheckJunctionCollisions
Definition MSLane.h:1638
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:1545
MSEdge *const myEdge
The lane's edge, for routing only.
Definition MSLane.h:1524
double myNettoVehicleLengthSum
The current length of all vehicles on this lane, excluding their minGaps.
Definition MSLane.h:1566
static std::vector< MSLink * >::const_iterator succLinkSec(const SUMOVehicle &veh, int nRouteSuccs, const MSLane &succLinkSource, const std::vector< MSLane * > &conts)
Definition MSLane.cpp:2694
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:2891
double myMaxSpeed
Lane-wide speed limit [m/s].
Definition MSLane.h:1527
void saveState(OutputDevice &out)
Saves the state of this lane into the given stream.
Definition MSLane.cpp:3704
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:2745
int myRightmostSublane
the index of the rightmost sublane of this lane on myEdge
Definition MSLane.h:1606
void setChangeRight(SVCPermissions permissions)
Sets the permissions for changing to the right neighbour lane.
Definition MSLane.cpp:4561
const bool myIsRampAccel
whether this lane is an acceleration lane
Definition MSLane.h:1598
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:4660
SUMOTime myFollowerInfoTime
time step for which myFollowerInfo was last updated
Definition MSLane.h:1592
MSLeaderInfo myLeaderInfo
leaders on all sublanes as seen by approaching vehicles (cached)
Definition MSLane.h:1585
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:3778
static void initCollisionOptions(const OptionsCont &oc)
Definition MSLane.cpp:4509
int myNumericalID
Unique numerical ID (set on reading by netload)
Definition MSLane.h:1455
VehCont myVehicles
The lane's vehicles. This container holds all vehicles that have their front (longitudinally) and the...
Definition MSLane.h:1477
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:4237
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:1627
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:1615
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:4324
void addIncomingLane(MSLane *lane, MSLink *viaLink)
Definition MSLane.cpp:2856
bool isWalkingArea() const
Definition MSLane.cpp:2637
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:4304
void enteredByLaneChange(MSVehicle *v)
Definition MSLane.cpp:3359
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:4423
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:3317
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:957
static const long CHANGE_PERMISSIONS_PERMANENT
Definition MSLane.h:1381
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:3272
void resetPermissions(long long transientID)
Definition MSLane.cpp:4534
MSVehicle * getLastFullVehicle() const
returns the last vehicle for which this lane is responsible or 0
Definition MSLane.cpp:2643
static void loadRNGState(int index, const std::string &state)
load random number generator state for the given rng index
Definition MSLane.cpp:4670
const std::string myLaneType
the type of this lane
Definition MSLane.h:1601
int myRNGIndex
Definition MSLane.h:1621
VehCont myManeuverReservations
The vehicles which registered maneuvering into the lane within their current action step....
Definition MSLane.h:1505
const MSJunction * getToJunction() const
Definition MSLane.cpp:4730
void addLeaders(const MSVehicle *vehicle, double vehPos, MSLeaderDistanceInfo &result, bool oppositeDirection=false)
get leaders for ego on the given lane
Definition MSLane.cpp:4148
static double myCheckJunctionCollisionMinGap
Definition MSLane.h:1639
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:1563
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:4555
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:4335
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:4724
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:2907
static CollisionAction myIntermodalCollisionAction
Definition MSLane.h:1637
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:2757
static std::vector< SumoRNG > myRNGs
Definition MSLane.h:1629
virtual void swapAfterLaneChange(SUMOTime t)
moves myTmpVehicles int myVehicles after a lane change procedure
Definition MSLane.cpp:2815
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:3132
StopOffset myLaneStopOffset
Definition MSLane.h:1521
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:4647
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:2991
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:4252
bool myRecalculateBruttoSum
Flag to recalculate the occupancy (including minGaps) after a change in minGap.
Definition MSLane.h:1575
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:3746
MSLane * myCanonicalPredecessorLane
Similar to LogicalPredecessorLane,.
Definition MSLane.h:1557
bool myNeedsCollisionCheck
whether a collision check is currently needed
Definition MSLane.h:1609
bool isLinkEnd(std::vector< MSLink * >::const_iterator &i) const
Definition MSLane.h:860
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition MSLane.h:932
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:1202
void checkBufferType()
Definition MSLane.cpp:321
std::pair< MSVehicle *const, double > getOppositeFollower(const MSVehicle *ego) const
Definition MSLane.cpp:4451
bool mySpeedByTraCI
Whether the current speed limit has been set through TraCI.
Definition MSLane.h:1535
bool hasPedestrians() const
whether the lane has pedestrians on it
Definition MSLane.cpp:4567
const std::vector< std::pair< const MSLane *, const MSEdge * > > getOutgoingViaLanes() const
get the list of outgoing lanes
Definition MSLane.cpp:3328
MSVehicle * getPartialBehind(const MSVehicle *ego) const
Definition MSLane.cpp:4214
void setLaneStopOffset(const StopOffset &stopOffset)
Set vehicle class specific stopOffsets.
Definition MSLane.cpp:3797
double myBruttoVehicleLengthSumToRemove
The length of all vehicles that have left this lane in the current step (this lane,...
Definition MSLane.h:1569
void leftByLaneChange(MSVehicle *v)
Definition MSLane.cpp:3352
MSLane * getCanonicalSuccessorLane() const
Definition MSLane.cpp:3296
std::vector< StopWatch< std::chrono::nanoseconds > > myStopWatch
Definition MSLane.h:1798
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:4522
const double myWidth
Lane width [m].
Definition MSLane.h:1516
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:4395
SVCPermissions myChangeRight
Definition MSLane.h:1542
const double myLengthGeometryFactor
precomputed myShape.length / myLength
Definition MSLane.h:1595
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:1261
MSLane * getLogicalPredecessorLane() const
get the most likely precedecessor lane (sorted using by_connections_to_sorter). The result is cached ...
Definition MSLane.cpp:3216
double getBruttoOccupancy() const
Returns the brutto (including minGaps) occupancy of this lane during the last step.
Definition MSLane.cpp:3396
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:1464
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:3460
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:3426
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:1579
MSVehicle * getLastAnyVehicle() const
returns the last vehicle that is fully or partially on this lane
Definition MSLane.cpp:2661
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:1489
void sortManeuverReservations()
sorts myManeuverReservations
Definition MSLane.cpp:2601
MinorLinkMode
determine whether/how getFollowers looks upstream beyond minor links
Definition MSLane.h:980
@ FOLLOW_ONCOMING
Definition MSLane.h:983
@ FOLLOW_ALWAYS
Definition MSLane.h:982
@ FOLLOW_NEVER
Definition MSLane.h:981
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:3338
bool mySpeedByVSS
Whether the current speed limit is set by a variable speed sign (VSS)
Definition MSLane.h:1532
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:3485
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:2919
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:1643
MSLane * getOpposite() const
return the neighboring opposite direction lane for lane changing or nullptr
Definition MSLane.cpp:4383
void setLength(double val)
Sets a new length for the lane (used by TraCI only)
Definition MSLane.cpp:2808
std::map< MSEdge *, std::vector< MSLane * > > myApproachingLanes
All direct internal and direct (disregarding internal predecessors) non-internal predecessor lanes of...
Definition MSLane.h:1582
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:4685
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:4679
static double myCollisionMinGapFactor
Definition MSLane.h:1642
SUMOTime myLeaderInfoTime
time step for which myLeaderInfo was last updated
Definition MSLane.h:1590
MSLane * myOpposite
Definition MSLane.h:1612
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:4389
std::map< std::string, MSLane * > DictType
definition of the static dictionary type
Definition MSLane.h:1624
double getFractionalVehicleLength(bool brutto) const
return length of fractional vehicles on this lane
Definition MSLane.cpp:3377
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:4694
const MSLane * getNormalPredecessorLane() const
get normal lane leading to this internal lane, for normal lanes, the lane itself is returned
Definition MSLane.cpp:3241
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:3803
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:2785
MSVehicle * getFirstFullVehicle() const
returns the first vehicle for which this lane is responsible or 0
Definition MSLane.cpp:2652
double getMeanSpeed() const
Returns the mean speed on this lane.
Definition MSLane.cpp:3439
double myNettoVehicleLengthSumToRemove
The length of all vehicles that have left this lane in the current step (this lane,...
Definition MSLane.h:1572
void setFrictionCoefficient(double val)
Sets a new friction coefficient for the lane [to be later (used by TraCI and MSCalibrator)].
Definition MSLane.cpp:2801
static CollisionAction getCollisionAction()
Definition MSLane.h:1364
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