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