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