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