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