SUMO - Simulation of Urban MObility
MSLane.cpp
Go to the documentation of this file.
1 /****************************************************************************/
14 // Representation of a lane in the micro simulation
15 /****************************************************************************/
16 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
17 // Copyright (C) 2001-2016 DLR (http://www.dlr.de/) and contributors
18 /****************************************************************************/
19 //
20 // This file is part of SUMO.
21 // SUMO is free software: you can redistribute it and/or modify
22 // it under the terms of the GNU General Public License as published by
23 // the Free Software Foundation, either version 3 of the License, or
24 // (at your option) any later version.
25 //
26 /****************************************************************************/
27 
28 
29 // ===========================================================================
30 // included modules
31 // ===========================================================================
32 #ifdef _MSC_VER
33 #include <windows_config.h>
34 #else
35 #include <config.h>
36 #endif
37 
38 #include <cmath>
39 #include <bitset>
40 #include <iostream>
41 #include <cassert>
42 #include <functional>
43 #include <algorithm>
44 #include <iterator>
45 #include <exception>
46 #include <climits>
47 #include <set>
49 #include <utils/common/StdDefs.h>
51 #include <utils/common/ToString.h>
54 #include <utils/geom/GeomHelper.h>
57 #include "MSNet.h"
58 #include "MSVehicleType.h"
59 #include "MSEdge.h"
60 #include "MSEdgeControl.h"
61 #include "MSJunction.h"
62 #include "MSLogicJunction.h"
63 #include "MSLink.h"
64 #include "MSLane.h"
65 #include "MSVehicleTransfer.h"
66 #include "MSGlobals.h"
67 #include "MSVehicleControl.h"
68 #include "MSInsertionControl.h"
69 #include "MSVehicleControl.h"
70 #include "MSLeaderInfo.h"
71 #include "MSVehicle.h"
72 
73 #ifdef CHECK_MEMORY_LEAKS
74 #include <foreign/nvwa/debug_new.h>
75 #endif // CHECK_MEMORY_LEAKS
76 
77 //#define DEBUG_INSERTION
78 //#define DEBUG_PLAN_MOVE
79 //#define DEBUG_CONTEXT
80 //#define DEBUG_OPPOSITE
81 #define DEBUG_COND (getID() == "disabled")
82 #define DEBUG_COND2(obj) ((obj != 0 && (obj)->getID() == "disabled"))
83 
84 // ===========================================================================
85 // static member definitions
86 // ===========================================================================
90 
91 // ===========================================================================
92 // internal class method definitions
93 // ===========================================================================
94 
95 
98  if (nextIsMyVehicles()) {
99  if (myI1 != myI1End) {
100  myI1 += myDirection;
101  }
102  // else: already at end
103  } else {
104  myI2 += myDirection;
105  }
106  //if (DEBUG_COND2(myLane)) std::cout << SIMTIME << " AnyVehicleIterator::operator++ lane=" << myLane->getID() << " myI1=" << myI1 << " myI2=" << myI2 << "\n";
107  return *this;
108 }
109 
110 
111 const MSVehicle*
113  if (nextIsMyVehicles()) {
114  if (myI1 != myI1End) {
115  return myLane->myVehicles[myI1];
116  } else {
117  return 0;
118  }
119  } else {
120  return myLane->myPartialVehicles[myI2];
121  }
122 }
123 
124 
125 bool
127  //if (DEBUG_COND2(myLane)) std::cout << SIMTIME << " AnyVehicleIterator::nextIsMyVehicles lane=" << myLane->getID()
128  // << " myI1=" << myI1
129  // << " myI2=" << myI2
130  // << "\n";
131  if (myI1 == myI1End) {
132  if (myI2 != myI2End) {
133  return false;
134  } else {
135  return true; // @note. must be caught
136  }
137  } else {
138  if (myI2 == myI2End) {
139  return true;
140  } else {
141  //if (DEBUG_COND2(myLane)) std::cout << " "
142  // << " veh1=" << myLane->myVehicles[myI1]->getID()
143  // << " veh2=" << myLane->myPartialVehicles[myI2]->getID()
144  // << " pos1=" << myLane->myVehicles[myI1]->getPositionOnLane(myLane)
145  // << " pos2=" << myLane->myPartialVehicles[myI2]->getPositionOnLane(myLane)
146  // << "\n";
147  if (myLane->myVehicles[myI1]->getPositionOnLane(myLane) < myLane->myPartialVehicles[myI2]->getPositionOnLane(myLane)) {
148  return myDownstream;
149  } else {
150  return !myDownstream;
151  }
152  }
153  }
154 }
155 
156 
157 // ===========================================================================
158 // member method definitions
159 // ===========================================================================
160 MSLane::MSLane(const std::string& id, SUMOReal maxSpeed, SUMOReal length, MSEdge* const edge,
161  int numericalID, const PositionVector& shape, SUMOReal width,
162  SVCPermissions permissions, int index) :
163  Named(id),
164  myNumericalID(numericalID), myShape(shape), myIndex(index),
165  myVehicles(), myLength(length), myWidth(width), myEdge(edge), myMaxSpeed(maxSpeed),
166  myPermissions(permissions),
167  myOriginalPermissions(permissions),
170  myLeaderInfo(this, 0, 0),
171  myFollowerInfo(this, 0, 0),
172  myLeaderInfoTmp(this, 0, 0),
175  myLengthGeometryFactor(MAX2(POSITION_EPS, myShape.length()) / myLength), // factor should not be 0
176  myRightSideOnEdge(0), // initialized in MSEdge::initialize
177  myRightmostSublane(0) { // initialized in MSEdge::initialize
179 }
180 
181 
183  for (MSLinkCont::iterator i = myLinks.begin(); i != myLinks.end(); ++i) {
184  delete *i;
185  }
186 }
187 
188 
189 void
191  myLinks.push_back(link);
192 }
193 
194 
195 void
196 MSLane::addNeigh(const std::string& id) {
197  myNeighs.push_back(id);
198 }
199 
200 
201 // ------ interaction with MSMoveReminder ------
202 void
204  myMoveReminders.push_back(rem);
205  for (VehCont::iterator veh = myVehicles.begin(); veh != myVehicles.end(); ++veh) {
206  (*veh)->addReminder(rem);
207  }
208 }
209 
210 
211 SUMOReal
213 #ifdef DEBUG_CONTEXT
214  if (DEBUG_COND2(v)) {
215  std::cout << SIMTIME << " setPartialOccupation. lane=" << getID() << " veh=" << v->getID() << "\n";
216  }
217 #endif
218  // XXX update occupancy here?
219  myPartialVehicles.push_back(v);
220  return myLength;
221 }
222 
223 
224 void
226 #ifdef DEBUG_CONTEXT
227  if (DEBUG_COND2(v)) {
228  std::cout << SIMTIME << " resetPartialOccupation. lane=" << getID() << " veh=" << v->getID() << "\n";
229  }
230 #endif
231  for (VehCont::iterator i = myPartialVehicles.begin(); i != myPartialVehicles.end(); ++i) {
232  if (v == *i) {
233  myPartialVehicles.erase(i);
234  // XXX update occupancy here?
235  //std::cout << " removed from myPartialVehicles\n";
236  return;
237  }
238  }
239  assert(false);
240 }
241 
242 
243 // ------ Vehicle emission ------
244 void
245 MSLane::incorporateVehicle(MSVehicle* veh, SUMOReal pos, SUMOReal speed, SUMOReal posLat, const MSLane::VehCont::iterator& at, MSMoveReminder::Notification notification) {
246  assert(pos <= myLength);
247  bool wasInactive = myVehicles.size() == 0;
248  veh->enterLaneAtInsertion(this, pos, speed, posLat, notification);
249  if (at == myVehicles.end()) {
250  // vehicle will be the first on the lane
251  myVehicles.push_back(veh);
252  } else {
253  myVehicles.insert(at, veh);
254  }
257  myEdge->markDelayed();
258  if (wasInactive) {
260  }
261 }
262 
263 
264 bool
266  // XXX interpret departPosLat value
267  const SUMOReal posLat = 0;
268  const bool adaptSpeed = false;
269  if (myVehicles.size() == 0) {
270  return isInsertionSuccess(&veh, mspeed, basePos(veh), posLat, adaptSpeed, MSMoveReminder::NOTIFICATION_DEPARTED);
271  }
272  // try to insert behind the last vehicle
273  const MSVehicle* leader = myVehicles.front();
274  const SUMOReal leaderBack = leader->getPositionOnLane() - leader->getVehicleType().getLength();
275  const SUMOReal frontGapNeeded = veh.getCarFollowModel().getSecureGap(mspeed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()) + veh.getVehicleType().getMinGap() + POSITION_EPS;
276  if (leaderBack >= frontGapNeeded) {
277  return isInsertionSuccess(&veh, mspeed, leaderBack - frontGapNeeded, posLat, adaptSpeed, MSMoveReminder::NOTIFICATION_DEPARTED);
278  }
279  return false;
280 }
281 
282 
283 bool
285  MSMoveReminder::Notification notification) {
286  bool adaptableSpeed = true;
287  // try to insert teleporting vehicles fully on this lane
288  const SUMOReal minPos = (notification == MSMoveReminder::NOTIFICATION_TELEPORT ?
289  MIN2(myLength, veh.getVehicleType().getLength()) : 0);
290 
291  if (myVehicles.size() == 0) {
292  // ensure sufficient gap to followers on predecessor lanes
293  const SUMOReal backOffset = minPos - veh.getVehicleType().getLength();
294  const SUMOReal missingRearGap = getMissingRearGap(backOffset, mspeed, veh.getCarFollowModel().getMaxDecel());
295  if (missingRearGap > 0) {
296  if (minPos + missingRearGap <= myLength) {
297  // @note. The rear gap is tailored to mspeed. If it changes due
298  // to a leader vehicle (on subsequent lanes) insertion will
299  // still fail. Under the right combination of acceleration and
300  // deceleration values there might be another insertion
301  // positions that would be successful be we do not look for it.
302  //std::cout << SIMTIME << " freeInsertion lane=" << getID() << " veh=" << veh.getID() << " unclear @(340)\n";
303  return isInsertionSuccess(&veh, mspeed, minPos + missingRearGap, 0, adaptableSpeed, notification);
304  } else {
305  return false;
306  }
307  } else {
308  return isInsertionSuccess(&veh, mspeed, minPos, 0, adaptableSpeed, notification);
309  }
310 
311  } else {
312  // check whether the vehicle can be put behind the last one if there is such
313  MSVehicle* leader = getFirstFullVehicle(); // @todo reproduction of bogus old behavior. see #1961
314  const SUMOReal leaderPos = leader->getBackPositionOnLane(this);
315  const SUMOReal speed = adaptableSpeed ? leader->getSpeed() : mspeed;
316  const SUMOReal frontGapNeeded = veh.getCarFollowModel().getSecureGap(speed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()) + veh.getVehicleType().getMinGap();
317  if (leaderPos >= frontGapNeeded) {
318  const SUMOReal tspeed = MIN2(veh.getCarFollowModel().insertionFollowSpeed(&veh, mspeed, frontGapNeeded, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()), mspeed);
319  // check whether we can insert our vehicle behind the last vehicle on the lane
320  if (isInsertionSuccess(&veh, tspeed, minPos, 0, adaptableSpeed, notification)) {
321  //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";
322  return true;
323  }
324  }
325  }
326  // go through the lane, look for free positions (starting after the last vehicle)
327  MSLane::VehCont::iterator predIt = myVehicles.begin();
328  while (predIt != myVehicles.end()) {
329  // get leader (may be zero) and follower
330  // @todo compute secure position in regard to sublane-model
331  const MSVehicle* leader = predIt != myVehicles.end() - 1 ? *(predIt + 1) : 0;
332  if (leader == 0 && myPartialVehicles.size() > 0) {
333  leader = myPartialVehicles.front();
334  }
335  const MSVehicle* follower = *predIt;
336 
337  // patch speed if allowed
338  SUMOReal speed = mspeed;
339  if (adaptableSpeed && leader != 0) {
340  speed = MIN2(leader->getSpeed(), mspeed);
341  }
342 
343  // compute the space needed to not collide with leader
344  SUMOReal frontMax = getLength();
345  if (leader != 0) {
346  SUMOReal leaderRearPos = leader->getBackPositionOnLane(this);
347  SUMOReal frontGapNeeded = veh.getCarFollowModel().getSecureGap(speed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()) + veh.getVehicleType().getMinGap();
348  frontMax = leaderRearPos - frontGapNeeded;
349  }
350  // compute the space needed to not let the follower collide
351  const SUMOReal followPos = follower->getPositionOnLane() + follower->getVehicleType().getMinGap();
352  const SUMOReal backGapNeeded = follower->getCarFollowModel().getSecureGap(follower->getSpeed(), veh.getSpeed(), veh.getCarFollowModel().getMaxDecel());
353  const SUMOReal backMin = followPos + backGapNeeded + veh.getVehicleType().getLength();
354 
355  // check whether there is enough room (given some extra space for rounding errors)
356  if (frontMax > minPos && backMin + POSITION_EPS < frontMax) {
357  // try to insert vehicle (should be always ok)
358  if (isInsertionSuccess(&veh, speed, backMin + POSITION_EPS, 0, adaptableSpeed, notification)) {
359  //std::cout << SIMTIME << " freeInsertion lane=" << getID() << " veh=" << veh.getID() << " @(393)\n";
360  return true;
361  }
362  }
363  ++predIt;
364  }
365  // first check at lane's begin
366  //std::cout << SIMTIME << " freeInsertion lane=" << getID() << " veh=" << veh.getID() << " fail final\n";
367  return false;
368 }
369 
370 
371 SUMOReal
372 MSLane::getDepartSpeed(const MSVehicle& veh, bool& patchSpeed) {
373  SUMOReal speed = 0;
374  const SUMOVehicleParameter& pars = veh.getParameter();
375  switch (pars.departSpeedProcedure) {
376  case DEPART_SPEED_GIVEN:
377  speed = pars.departSpeed;
378  patchSpeed = false;
379  break;
380  case DEPART_SPEED_RANDOM:
381  speed = RandHelper::rand(getVehicleMaxSpeed(&veh));
382  patchSpeed = true; // @todo check
383  break;
384  case DEPART_SPEED_MAX:
385  speed = getVehicleMaxSpeed(&veh);
386  patchSpeed = true; // @todo check
387  break;
389  default:
390  // speed = 0 was set before
391  patchSpeed = false; // @todo check
392  break;
393  }
394  return speed;
395 }
396 
397 
398 bool
400  SUMOReal pos = 0;
401  SUMOReal posLat = 0;
402  bool patchSpeed = true; // whether the speed shall be adapted to infrastructure/traffic in front
403  const SUMOVehicleParameter& pars = veh.getParameter();
404  SUMOReal speed = getDepartSpeed(veh, patchSpeed);
405 
406  // determine the position
407  switch (pars.departPosProcedure) {
408  case DEPART_POS_GIVEN:
409  pos = pars.departPos;
410  if (pos < 0.) {
411  pos += myLength;
412  }
413  break;
414  case DEPART_POS_RANDOM:
415  pos = RandHelper::rand(getLength());
416  break;
417  case DEPART_POS_RANDOM_FREE: {
418  for (int i = 0; i < 10; i++) {
419  // we will try some random positions ...
420  pos = RandHelper::rand(getLength());
423  posLat = RandHelper::rand(getWidth() - veh.getVehicleType().getWidth()) - getWidth() * 0.5 + veh.getVehicleType().getWidth() * 0.5;
424  }
425  if (isInsertionSuccess(&veh, speed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED)) {
426  return true;
427  }
428  }
429  // ... and if that doesn't work, we put the vehicle to the free position
430  return freeInsertion(veh, speed);
431  }
432  break;
433  case DEPART_POS_FREE:
434  return freeInsertion(veh, speed);
435  case DEPART_POS_LAST:
436  return lastInsertion(veh, speed);
437  case DEPART_POS_BASE:
438  case DEPART_POS_DEFAULT:
439  default:
440  pos = basePos(veh);
441  break;
442  }
443  // determine the lateral position
444  switch (pars.departPosLatProcedure) {
445  case DEPART_POSLAT_GIVEN:
446  posLat = pars.departPosLat;
447  break;
449  posLat = RandHelper::rand(getWidth() - veh.getVehicleType().getWidth()) - getWidth() * 0.5 + veh.getVehicleType().getWidth() * 0.5;
450  break;
452  for (int i = 0; i < 10; i++) {
453  // we will try some random positions ...
454  posLat = RandHelper::rand(getWidth()) - getWidth() * 0.5;
455  if (isInsertionSuccess(&veh, speed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED)) {
456  return true;
457  }
458  }
459  // ... and if that doesn't work, we put the vehicle to the free position
460  return freeInsertion(veh, speed);
461  }
462  break;
463  case DEPART_POSLAT_FREE:
464  return freeInsertion(veh, speed);
465  case DEPART_POSLAT_RIGHT:
466  posLat = -getWidth() * 0.5 + veh.getVehicleType().getWidth() * 0.5;
467  break;
468  case DEPART_POSLAT_LEFT:
469  posLat = getWidth() * 0.5 - veh.getVehicleType().getWidth() * 0.5;
470  break;
472  case DEPART_POS_DEFAULT:
473  default:
474  posLat = 0;
475  break;
476  }
477  // try to insert
478  return isInsertionSuccess(&veh, speed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED);
479 }
480 
481 
482 SUMOReal
483 MSLane::basePos(const MSVehicle& veh) const {
485 }
486 
487 bool
488 MSLane::checkFailure(MSVehicle* aVehicle, SUMOReal& speed, SUMOReal& dist, const SUMOReal nspeed, const bool patchSpeed, const std::string errorMsg) const {
489  if (nspeed < speed) {
490  if (patchSpeed) {
491  speed = MIN2(nspeed, speed);
492  dist = aVehicle->getCarFollowModel().brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
493  } else if (speed > 0) {
494  if (errorMsg != "") {
495  WRITE_ERROR("Vehicle '" + aVehicle->getID() + "' will not be able to depart using the given velocity (" + errorMsg + ")!");
497  }
498  return true;
499  }
500  }
501  return false;
502 }
503 
504 
505 bool
507  SUMOReal speed, SUMOReal pos, SUMOReal posLat, bool patchSpeed,
508  MSMoveReminder::Notification notification) {
509  if (pos < 0 || pos > myLength) {
510  // we may not start there
511  WRITE_WARNING("Invalid departPos " + toString(pos) + " given for vehicle '" +
512  aVehicle->getID() + "'. Inserting at lane end instead.");
513  pos = myLength;
514  }
515 
516 #ifdef DEBUG_INSERTION
517  if (DEBUG_COND2(aVehicle)) std::cout << "\nIS_INSERTION_SUCCESS\n"
518  << SIMTIME << " lane=" << getID()
519  << " veh '" << aVehicle->getID() << "'\n";
520 #endif
521 
522  aVehicle->setTentativeLaneAndPosition(this, pos, posLat);
523  aVehicle->updateBestLanes(false, this);
524  const MSCFModel& cfModel = aVehicle->getCarFollowModel();
525  const std::vector<MSLane*>& bestLaneConts = aVehicle->getBestLanesContinuation(this);
526  std::vector<MSLane*>::const_iterator ri = bestLaneConts.begin();
527  SUMOReal seen = getLength() - pos; // == distance from insertion position until the end of the currentLane
528  SUMOReal dist = cfModel.brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
529 
530  // before looping through the continuation lanes, check if a stop is scheduled on this lane
531  // (the code is duplicated in the loop)
532  if (aVehicle->hasStops()) {
533  const MSVehicle::Stop& nextStop = aVehicle->getNextStop();
534  if (nextStop.lane == this) {
535  std::stringstream msg;
536  msg << "scheduled stop on lane '" << myID << "' too close";
537  const SUMOReal distToStop = nextStop.endPos - pos; // XXX: Please approve whether endPos is appropriate, here. (Leo)
538  if (checkFailure(aVehicle, speed, dist, cfModel.stopSpeed(aVehicle, speed, distToStop),
539  patchSpeed, msg.str())) {
540  // we may not drive with the given velocity - we cannot stop at the stop
541  return false;
542  }
543  }
544  }
545 
546  const MSRoute& r = aVehicle->getRoute();
547  MSRouteIterator ce = r.begin();
548  int nRouteSuccs = 1;
549  MSLane* currentLane = this;
550  MSLane* nextLane = this;
552  while (seen < dist && ri != bestLaneConts.end()) {
553  // get the next link used...
554  MSLinkCont::const_iterator link = succLinkSec(*aVehicle, nRouteSuccs, *currentLane, bestLaneConts);
555  if (currentLane->isLinkEnd(link)) {
556  if (&currentLane->getEdge() == r.getLastEdge()) {
557  // reached the end of the route
559  if (checkFailure(aVehicle, speed, dist, cfModel.freeSpeed(aVehicle, speed, seen, aVehicle->getParameter().arrivalSpeed, true),
560  patchSpeed, "arrival speed too low")) {
561  // we may not drive with the given velocity - we cannot match the specified arrival speed
562  return false;
563  }
564  }
565  } else {
566  // lane does not continue
567  if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, seen),
568  patchSpeed, "junction too close")) {
569  // we may not drive with the given velocity - we cannot stop at the junction
570  return false;
571  }
572  }
573  break;
574  }
575 
576  if (!(*link)->opened(arrivalTime, speed, speed, aVehicle->getVehicleType().getLength(), aVehicle->getImpatience(), cfModel.getMaxDecel(), 0, posLat)
577  || !(*link)->havePriority()) {
578  // have to stop at junction
579  std::string errorMsg = "";
580  const LinkState state = (*link)->getState();
581  if (state == LINKSTATE_MINOR
582  || state == LINKSTATE_EQUAL
583  || state == LINKSTATE_STOP
584  || state == LINKSTATE_ALLWAY_STOP) {
585  // no sense in trying later
586  errorMsg = "unpriorised junction too close";
587  }
588  if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, seen),
589  patchSpeed, errorMsg)) {
590  // we may not drive with the given velocity - we cannot stop at the junction in time
591  return false;
592  }
593 #ifdef DEBUG_INSERTION
594  if DEBUG_COND2(aVehicle) {
595  std::cout << "trying insertion before minor link: "
596  << "insertion speed = " << speed << " dist=" << dist
597  << "\n";
598  }
599 #endif
600  break;
601  }
602  // get the next used lane (including internal)
603  nextLane = (*link)->getViaLaneOrLane();
604  // check how next lane affects the journey
605  if (nextLane != 0) {
606 
607  // check if there are stops on the next lane that should be regarded
608  // (this block is duplicated before the loop to deal with the insertion lane)
609  if (aVehicle->hasStops()) {
610  const MSVehicle::Stop& nextStop = aVehicle->getNextStop();
611  if (nextStop.lane == nextLane) {
612  std::stringstream msg;
613  msg << "scheduled stop on lane '" << nextStop.lane->getID() << "' too close";
614  const SUMOReal distToStop = seen + nextStop.endPos; // XXX: Please approve whether endPos is appropriate, here. (Leo)
615  if (checkFailure(aVehicle, speed, dist, cfModel.stopSpeed(aVehicle, speed, distToStop),
616  patchSpeed, msg.str())) {
617  // we may not drive with the given velocity - we cannot stop at the stop
618  return false;
619  }
620  }
621  }
622 
623  // check leader on next lane
624  // XXX check all leaders in the sublane case
625  SUMOReal gap = 0;
626  MSVehicle* leader = nextLane->getLastAnyVehicle();
627  if (leader != 0) {
628 #ifdef DEBUG_INSERTION
629  if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
630  << "leader on lane '" << nextLane->getID() << "': " << leader->getID() << "\n";
631 #endif
632  gap = seen + leader->getBackPositionOnLane(nextLane) - aVehicle->getVehicleType().getMinGap();
633  }
634  if (leader != 0) {
635  if (gap < 0) {
636  return false;
637  }
638  const SUMOReal nspeed = cfModel.insertionFollowSpeed(aVehicle, speed, gap, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
639  if (checkFailure(aVehicle, speed, dist, nspeed, patchSpeed, "")) {
640  // we may not drive with the given velocity - we crash into the leader
641 #ifdef DEBUG_INSERTION
642  if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
643  << " isInsertionSuccess lane=" << getID()
644  << " veh=" << aVehicle->getID()
645  << " pos=" << pos
646  << " posLat=" << posLat
647  << " patchSpeed=" << patchSpeed
648  << " speed=" << speed
649  << " nspeed=" << nspeed
650  << " nextLane=" << nextLane->getID()
651  << " lead=" << leader->getID()
652  << " gap=" << gap
653  << " failed (@641)!\n";
654 #endif
655  return false;
656  }
657  }
658  // check next lane's maximum velocity
659  const SUMOReal nspeed = cfModel.freeSpeed(aVehicle, speed, seen, nextLane->getVehicleMaxSpeed(aVehicle), true);
660  if (nspeed < speed) {
661  if (patchSpeed) {
662  speed = nspeed;
663  dist = cfModel.brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
664  } else {
665  // we may not drive with the given velocity - we would be too fast on the next lane
666  WRITE_ERROR("Vehicle '" + aVehicle->getID() + "' will not be able to depart using the given velocity (slow lane ahead)!");
668  return false;
669  }
670  }
671  // check traffic on next junction
672  // we cannot use (*link)->opened because a vehicle without priority
673  // may already be comitted to blocking the link and unable to stop
674  const SUMOTime leaveTime = (*link)->getLeaveTime(arrivalTime, speed, speed, aVehicle->getVehicleType().getLength());
675  if ((*link)->hasApproachingFoe(arrivalTime, leaveTime, speed, cfModel.getMaxDecel())) {
676  if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, seen), patchSpeed, "")) {
677  // we may not drive with the given velocity - we crash at the junction
678  return false;
679  }
680  }
681  arrivalTime += TIME2STEPS(nextLane->getLength() / MAX2(speed, NUMERICAL_EPS));
682  seen += nextLane->getLength();
683  currentLane = nextLane;
684 #ifdef HAVE_INTERNAL_LANES
685  if ((*link)->getViaLane() == 0) {
686 #else
687  if (true) {
688 #endif
689  nRouteSuccs++;
690  ++ce;
691  ++ri;
692  }
693  }
694  }
695 
696  // get the pointer to the vehicle next in front of the given position
697  MSLeaderInfo leaders = getLastVehicleInformation(aVehicle, 0, pos);
698  //if (aVehicle->getID() == "disabled") std::cout << " leaders=" << leaders.toString() << "\n";
699  const SUMOReal nspeed = safeInsertionSpeed(aVehicle, leaders, speed);
700  if (nspeed < 0 || checkFailure(aVehicle, speed, dist, nspeed, patchSpeed, "")) {
701  // XXX: checking for nspeed<0... Might appear naturally with ballistic update (see #860, Leo)
702  // TODO: check if ballistic update needs adjustments here, refs. #2577
703 
704  // we may not drive with the given velocity - we crash into the leader
705 #ifdef DEBUG_INSERTION
706  if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
707  << " isInsertionSuccess lane=" << getID()
708  << " veh=" << aVehicle->getID()
709  << " pos=" << pos
710  << " posLat=" << posLat
711  << " patchSpeed=" << patchSpeed
712  << " speed=" << speed
713  << " nspeed=" << nspeed
714  << " nextLane=" << nextLane->getID()
715  << " leaders=" << leaders.toString()
716  << " failed (@700)!\n";
717 #endif
718  return false;
719  }
720 #ifdef DEBUG_INSERTION
721  if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
722  << " speed = " << speed
723  << " nspeed = " << nspeed
724  << std::endl;
725 #endif
726 
727  MSLeaderDistanceInfo followers = getFollowersOnConsecutive(aVehicle, false);
728  for (int i = 0; i < followers.numSublanes(); ++i) {
729  const MSVehicle* follower = followers[i].first;
730  if (follower != 0) {
731  const SUMOReal backGapNeeded = follower->getCarFollowModel().getSecureGap(follower->getSpeed(), speed, cfModel.getMaxDecel());
732  if (followers[i].second < backGapNeeded) {
733  // too close to the follower on this lane
734 #ifdef DEBUG_INSERTION
735  if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
736  << " isInsertionSuccess lane=" << getID()
737  << " veh=" << aVehicle->getID()
738  << " pos=" << pos
739  << " posLat=" << posLat
740  << " patchSpeed=" << patchSpeed
741  << " speed=" << speed
742  << " nspeed=" << nspeed
743  << " follower=" << follower->getID()
744  << " backGapNeeded=" << backGapNeeded
745  << " gap=" << followers[i].second
746  << " failure (@719)!\n";
747 #endif
748  return false;
749  }
750  }
751  }
752  if (followers.numFreeSublanes() > 0) {
753  // check approaching vehicles to prevent rear-end collisions
754  const SUMOReal backOffset = pos - aVehicle->getVehicleType().getLength();
755  const SUMOReal missingRearGap = getMissingRearGap(backOffset, speed, aVehicle->getCarFollowModel().getMaxDecel());
756  if (missingRearGap > 0) {
757  // too close to a follower
758 #ifdef DEBUG_INSERTION
759  if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
760  << " isInsertionSuccess lane=" << getID()
761  << " veh=" << aVehicle->getID()
762  << " pos=" << pos
763  << " posLat=" << posLat
764  << " patchSpeed=" << patchSpeed
765  << " speed=" << speed
766  << " nspeed=" << nspeed
767  << " missingRearGap=" << missingRearGap
768  << " failure (@728)!\n";
769 #endif
770  return false;
771  }
772  }
773  // may got negative while adaptation
774  if (speed < 0) {
775 #ifdef DEBUG_INSERTION
776  if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
777  << " isInsertionSuccess lane=" << getID()
778  << " veh=" << aVehicle->getID()
779  << " pos=" << pos
780  << " posLat=" << posLat
781  << " patchSpeed=" << patchSpeed
782  << " speed=" << speed
783  << " nspeed=" << nspeed
784  << " failed (@733)!\n";
785 #endif
786  return false;
787  }
788  // enter
789  incorporateVehicle(aVehicle, pos, speed, posLat, find_if(myVehicles.begin(), myVehicles.end(), bind2nd(VehPosition(), pos)), notification);
790 #ifdef DEBUG_INSERTION
791  if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
792  << " isInsertionSuccess lane=" << getID()
793  << " veh=" << aVehicle->getID()
794  << " pos=" << pos
795  << " posLat=" << posLat
796  << " patchSpeed=" << patchSpeed
797  << " speed=" << speed
798  << " nspeed=" << nspeed
799  << " success!\n";
800 #endif
801  return true;
802 }
803 
804 
805 void
807  veh->updateBestLanes(true, this);
808  bool dummy;
809  const SUMOReal speed = veh->hasDeparted() ? veh->getSpeed() : getDepartSpeed(*veh, dummy);
810  incorporateVehicle(veh, pos, speed, posLat, find_if(myVehicles.begin(), myVehicles.end(), bind2nd(VehPosition(), pos)), notification);
811 }
812 
813 
814 SUMOReal
815 MSLane::safeInsertionSpeed(const MSVehicle* veh, const MSLeaderInfo& leaders, SUMOReal speed) {
816  SUMOReal nspeed = speed;
817  for (int i = 0; i < leaders.numSublanes(); ++i) {
818  const MSVehicle* leader = leaders[i];
819  if (leader != 0) {
820  const SUMOReal gap = leader->getBackPositionOnLane(this) - veh->getPositionOnLane() - veh->getVehicleType().getMinGap();
821  if (gap < 0) {
822  return -1;
823  }
824  nspeed = MIN2(nspeed,
825  veh->getCarFollowModel().insertionFollowSpeed(veh, speed, gap, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()));
826  }
827  }
828  return nspeed;
829 }
830 
831 
832 // ------ Handling vehicles lapping into lanes ------
833 const MSLeaderInfo&
834 MSLane::getLastVehicleInformation(const MSVehicle* ego, SUMOReal latOffset, SUMOReal minPos, bool allowCached) const {
835  if (myLeaderInfoTime < MSNet::getInstance()->getCurrentTimeStep() || ego != 0 || minPos > 0 || !allowCached) {
836  myLeaderInfoTmp = MSLeaderInfo(this, ego, latOffset);
838  int freeSublanes = 1; // number of sublanes for which no leader was found
839  //if (ego->getID() == "disabled" && SIMTIME == 58) {
840  // std::cout << "DEBUG\n";
841  //}
842  const MSVehicle* veh = *last;
843  while (freeSublanes > 0 && veh != 0) {
844 #ifdef DEBUG_PLAN_MOVE
845  if (DEBUG_COND2(ego)) {
846  std::cout << " getLastVehicleInformation lane=" << getID() << " minPos=" << minPos << " veh=" << veh->getID() << " pos=" << veh->getPositionOnLane(this) << "\n";
847  }
848 #endif
849  if (veh != ego && veh->getPositionOnLane(this) >= minPos) {
850  const SUMOReal latOffset = veh->getLatOffset(this);
851  freeSublanes = myLeaderInfoTmp.addLeader(veh, true, latOffset);
852 #ifdef DEBUG_PLAN_MOVE
853  if (DEBUG_COND2(ego)) {
854  std::cout << " latOffset=" << latOffset << " newLeaders=" << myLeaderInfoTmp.toString() << "\n";
855  }
856 #endif
857  }
858  veh = *(++last);
859  }
860  if (ego == 0 && minPos == 0) {
861  // update cached value
864  }
865 #ifdef DEBUG_PLAN_MOVE
866  //if (DEBUG_COND2(ego)) std::cout << SIMTIME
867  // << " getLastVehicleInformation lane=" << getID()
868  // << " ego=" << Named::getIDSecure(ego)
869  // << "\n"
870  // << " vehicles=" << toString(myVehicles)
871  // << " partials=" << toString(myPartialVehicles)
872  // << "\n"
873  // << " result=" << myLeaderInfoTmp.toString()
874  // << " cached=" << myLeaderInfo.toString()
875  // << " myLeaderInfoTime=" << myLeaderInfoTime
876  // << "\n";
877 #endif
878  return myLeaderInfoTmp;
879  }
880  return myLeaderInfo;
881 }
882 
883 
884 const MSLeaderInfo&
885 MSLane::getFirstVehicleInformation(const MSVehicle* ego, SUMOReal latOffset, bool onlyFrontOnLane, SUMOReal maxPos, bool allowCached) const {
886  if (myFollowerInfoTime < MSNet::getInstance()->getCurrentTimeStep() || ego != 0 || maxPos < myLength || !allowCached || onlyFrontOnLane) {
887  // XXX separate cache for onlyFrontOnLane = true
888  myLeaderInfoTmp = MSLeaderInfo(this, ego, latOffset);
890  int freeSublanes = 1; // number of sublanes for which no leader was found
891  const MSVehicle* veh = *first;
892  while (freeSublanes > 0 && veh != 0) {
893 #ifdef DEBUG_PLAN_MOVE
894  if (DEBUG_COND2(ego)) {
895  std::cout << " veh=" << veh->getID() << " pos=" << veh->getPositionOnLane(this) << " maxPos=" << maxPos << "\n";
896  }
897 #endif
898  if (veh != ego && veh->getPositionOnLane(this) <= maxPos
899  && (!onlyFrontOnLane || veh->isFrontOnLane(this))) {
900  //const SUMOReal latOffset = veh->getLane()->getRightSideOnEdge() - getRightSideOnEdge();
901  const SUMOReal latOffset = veh->getLatOffset(this);
902 #ifdef DEBUG_PLAN_MOVE
903  if (DEBUG_COND2(ego)) {
904  std::cout << " veh=" << veh->getID() << " latOffset=" << latOffset << "\n";
905  }
906 #endif
907  freeSublanes = myLeaderInfoTmp.addLeader(veh, true, latOffset);
908  }
909  veh = *(++first);
910  }
911  if (ego == 0 && maxPos == std::numeric_limits<SUMOReal>::max()) {
912  // update cached value
915  }
916 #ifdef DEBUG_PLAN_MOVE
917  //if (DEBUG_COND2(ego)) std::cout << SIMTIME
918  // << " getFirstVehicleInformation lane=" << getID()
919  // << " ego=" << Named::getIDSecure(ego)
920  // << "\n"
921  // << " vehicles=" << toString(myVehicles)
922  // << " partials=" << toString(myPartialVehicles)
923  // << "\n"
924  // << " result=" << myLeaderInfoTmp.toString()
925  // //<< " cached=" << myLeaderInfo.toString()
926  // << " myLeaderInfoTime=" << myLeaderInfoTime
927  // << "\n";
928 #endif
929  return myLeaderInfoTmp;
930  }
931  return myFollowerInfo;
932 }
933 
934 
935 // ------ ------
936 void
938  assert(myVehicles.size() != 0);
939  SUMOReal cumulatedVehLength = 0.;
940  MSLeaderInfo ahead(this);
941  // iterate over myVehicles and myPartialVehicles merge-sort style
942  VehCont::reverse_iterator veh = myVehicles.rbegin();
943  VehCont::reverse_iterator vehPart = myPartialVehicles.rbegin();
944 #ifdef DEBUG_PLAN_MOVE
945  if (DEBUG_COND) std::cout
946  << "\n"
947  << SIMTIME
948  << " planMovements lane=" << getID()
949  << "\n"
950  << " vehicles=" << toString(myVehicles)
951  << " partials=" << toString(myPartialVehicles)
952  << "\n";
953 #endif
954  for (; veh != myVehicles.rend(); ++veh) {
955  while (vehPart != myPartialVehicles.rend()
956  && ((*vehPart)->getPositionOnLane(this) > (*veh)->getPositionOnLane())) {
957  const SUMOReal latOffset = (*vehPart)->getLatOffset(this);
958 #ifdef DEBUG_PLAN_MOVE
959  if (DEBUG_COND) {
960  std::cout << " partial ahead: " << (*vehPart)->getID() << " latOffset=" << latOffset << "\n";
961  }
962 #endif
963  ahead.addLeader(*vehPart, false, latOffset);
964  ++vehPart;
965  }
966 #ifdef DEBUG_PLAN_MOVE
967  if (DEBUG_COND) {
968  std::cout << " plan move for: " << (*veh)->getID() << " ahead=" << ahead.toString() << "\n";
969  }
970 #endif
971  (*veh)->planMove(t, ahead, cumulatedVehLength);
972  cumulatedVehLength += (*veh)->getVehicleType().getLengthWithGap();
973  ahead.addLeader(*veh, false, 0);
974  }
975 }
976 
977 
978 void
979 MSLane::detectCollisions(SUMOTime timestep, const std::string& stage) {
980  //std::vector<const MSVehicle*> all;
981  //for (AnyVehicleIterator last = anyVehiclesBegin(); last != anyVehiclesEnd(); ++last) {
982  // all.push_back(*last);
983  //}
984  //std::cout << SIMTIME << " detectCollisions stage=" << stage << " lane=" << getID() << ":\n"
985  // << " vehs=" << toString(myVehicles) << "\n"
986  // << " part=" << toString(myPartialVehicles) << "\n"
987  // << " all=" << toString(all) << "\n"
988  // << "\n";
989 
990  if (myVehicles.size() == 0 || myCollisionAction == COLLISION_ACTION_NONE) {
991  return;
992  }
993  std::set<const MSVehicle*, SUMOVehicle::ComparatorIdLess> toRemove;
994  std::set<const MSVehicle*> toTeleport;
996  // no sublanes
997  VehCont::iterator lastVeh = myVehicles.end() - 1;
998  for (VehCont::iterator veh = myVehicles.begin(); veh != lastVeh; ++veh) {
999  VehCont::iterator pred = veh + 1;
1000  detectCollisionBetween(timestep, stage, *veh, *pred, toRemove, toTeleport);
1001  }
1002  if (myPartialVehicles.size() > 0) {
1003  detectCollisionBetween(timestep, stage, *lastVeh, myPartialVehicles.front(), toRemove, toTeleport);
1004  }
1005  } else {
1006  // in the sublane-case it is insufficient to check the vehicles ordered
1007  // by their front position as there might be more than 2 vehicles next to each
1008  // other on the same lane
1009  // instead, a moving-window approach is used where all vehicles that
1010  // overlap in the longitudinal direction receive pairwise checks
1011  // XXX for efficiency, all lanes of an edge should be checked together
1012  // (lanechanger-style)
1013 
1014  // XXX quick hack: check each in myVehicles against all others
1015  for (VehCont::iterator veh = myVehicles.begin(); veh != myVehicles.end(); ++veh) {
1016  MSVehicle* follow = *veh;
1017  for (AnyVehicleIterator veh2 = anyVehiclesBegin(); veh2 != anyVehiclesEnd(); ++veh2) {
1018  MSVehicle* lead = (MSVehicle*)*veh2;
1019  if (lead == follow) {
1020  continue;
1021  }
1022  if (lead->getPositionOnLane(this) < follow->getPositionOnLane()) {
1023  continue;
1024  }
1025  if (detectCollisionBetween(timestep, stage, follow, lead, toRemove, toTeleport)) {
1026  break;
1027  }
1028  }
1029  if (follow->getLaneChangeModel().getShadowLane() != 0) {
1030  // check whether follow collides on the shadow lane
1031  const MSLane* shadowLane = follow->getLaneChangeModel().getShadowLane();
1032  MSLeaderInfo ahead = shadowLane->getLastVehicleInformation(follow,
1033  getRightSideOnEdge() - shadowLane->getRightSideOnEdge(),
1034  follow->getPositionOnLane());
1035  for (int i = 0; i < ahead.numSublanes(); ++i) {
1036  const MSVehicle* lead = ahead[i];
1037  if (lead != 0 && lead != follow && shadowLane->detectCollisionBetween(timestep, stage, follow, lead, toRemove, toTeleport)) {
1038  break;
1039  }
1040  }
1041  }
1042  }
1043  }
1044 
1046  assert(myLinks.size() == 1);
1047  //std::cout << SIMTIME << " checkJunctionCollisions " << getID() << "\n";
1048  const std::vector<const MSLane*>& foeLanes = myLinks.front()->getFoeLanes();
1049  for (VehCont::iterator veh = myVehicles.begin(); veh != myVehicles.end(); ++veh) {
1050  const MSVehicle* collider = *veh;
1051  //std::cout << " collider " << collider->getID() << "\n";
1052  PositionVector colliderBoundary = collider->getBoundingBox();
1053  for (std::vector<const MSLane*>::const_iterator it = foeLanes.begin(); it != foeLanes.end(); ++it) {
1054  const MSLane* foeLane = *it;
1055  //std::cout << " foeLane " << foeLane->getID() << "\n";
1056  MSLane::AnyVehicleIterator end = foeLane->anyVehiclesEnd();
1057  for (MSLane::AnyVehicleIterator it_veh = foeLane->anyVehiclesBegin(); it_veh != end; ++it_veh) {
1058  MSVehicle* victim = (MSVehicle*)*it_veh;
1059  //std::cout << " victim " << victim->getID() << "\n";
1060  if (colliderBoundary.overlapsWith(victim->getBoundingBox())) {
1061  // make a detailed check
1062  if (collider->getBoundingPoly().overlapsWith(victim->getBoundingPoly())) {
1063  handleCollisionBetween(timestep, stage, collider, victim, -1, 0, toRemove, toTeleport);
1064  }
1065  }
1066  }
1067  }
1068  }
1069  }
1070 
1071  for (std::set<const MSVehicle*, SUMOVehicle::ComparatorIdLess>::iterator it = toRemove.begin(); it != toRemove.end(); ++it) {
1072  MSVehicle* veh = const_cast<MSVehicle*>(*it);
1073  MSLane* vehLane = veh->getLane();
1075  if (toTeleport.count(veh) > 0) {
1076  MSVehicleTransfer::getInstance()->add(timestep, veh);
1077  } else {
1080  }
1081  }
1082 }
1083 
1084 
1085 bool
1086 MSLane::detectCollisionBetween(SUMOTime timestep, const std::string& stage, const MSVehicle* collider, const MSVehicle* victim,
1087  std::set<const MSVehicle*, SUMOVehicle::ComparatorIdLess>& toRemove,
1088  std::set<const MSVehicle*>& toTeleport) const {
1089  assert(collider->isFrontOnLane(this));
1090 #ifndef NO_TRACI
1091  if (myCollisionAction == COLLISION_ACTION_TELEPORT && ((victim->hasInfluencer() && victim->getInfluencer()->isVTDAffected(timestep)) ||
1092  (collider->hasInfluencer() && collider->getInfluencer()->isVTDAffected(timestep)))) {
1093  return false;
1094  }
1095 #endif
1096  const SUMOReal gap = victim->getBackPositionOnLane(this) - collider->getPositionOnLane() - collider->getVehicleType().getMinGap();
1097  if (gap < -NUMERICAL_EPS) {
1098  //std::cout << SIMTIME
1099  // << " thisLane=" << getID()
1100  // << " collider=" << collider->getID()
1101  // << " victim=" << victim->getID()
1102  // << " colliderLane=" << collider->getLane()->getID()
1103  // << " victimLane=" << victim->getLane()->getID()
1104  // << " colliderPos=" << collider->getPositionOnLane()
1105  // << " victimBackPos=" << victim->getBackPositionOnLane(this)
1106  // << " colliderLat=" << collider->getCenterOnEdge()
1107  // << " victimLat=" << victim->getCenterOnEdge(this)
1108  // << "\n";
1109  SUMOReal latGap = 0;
1111  latGap = (fabs(victim->getCenterOnEdge(this) - collider->getCenterOnEdge())
1112  - 0.5 * fabs(victim->getVehicleType().getWidth() + collider->getVehicleType().getWidth()));
1113  if (latGap + NUMERICAL_EPS > 0) {
1114  return false;
1115  }
1116  }
1118  && collider->getLaneChangeModel().isChangingLanes()
1119  && victim->getLaneChangeModel().isChangingLanes()
1120  && victim->getLane() != this) {
1121  // synchroneous lane change maneuver
1122  return false;
1123  }
1124  handleCollisionBetween(timestep, stage, collider, victim, gap, latGap, toRemove, toTeleport);
1125  return true;
1126  }
1127  return false;
1128 }
1129 
1130 
1131 void
1132 MSLane::handleCollisionBetween(SUMOTime timestep, const std::string& stage, const MSVehicle* collider, const MSVehicle* victim,
1133  SUMOReal gap, SUMOReal latGap, std::set<const MSVehicle*, SUMOVehicle::ComparatorIdLess>& toRemove,
1134  std::set<const MSVehicle*>& toTeleport) const {
1135  std::string prefix;
1136  switch (myCollisionAction) {
1137  case COLLISION_ACTION_WARN:
1138  prefix = "Vehicle '" + collider->getID() + "'; collision with vehicle '" + victim->getID() ;
1139  break;
1141  prefix = "Teleporting vehicle '" + collider->getID() + "'; collision with vehicle '" + victim->getID() ;
1142  toRemove.insert(collider);
1143  toTeleport.insert(collider);
1144  break;
1145  case COLLISION_ACTION_REMOVE: {
1146  prefix = "Removing collision participants: vehicle '" + collider->getID() + "', vehicle '" + victim->getID();
1147  bool removeCollider = true;
1148  bool removeVictim = true;
1149 #ifndef NO_TRACI
1150  removeVictim = !(victim->hasInfluencer() && victim->getInfluencer()->isVTDAffected(timestep));
1151  removeCollider = !(collider->hasInfluencer() && collider->getInfluencer()->isVTDAffected(timestep));
1152  if (removeVictim) {
1153  toRemove.insert(victim);
1154  }
1155  if (removeCollider) {
1156  toRemove.insert(collider);
1157  }
1158  if (!removeVictim) {
1159  if (!removeCollider) {
1160  prefix = "Keeping remote-controlled collision participants: vehicle '" + collider->getID() + "', vehicle '" + victim->getID();
1161  } else {
1162  prefix = "Removing collision participant: vehicle '" + collider->getID() + "', keeping remote-controlled vehicle '" + victim->getID();
1163  }
1164  } else if (!removeCollider) {
1165  prefix = "Keeping remote-controlled collision participant: vehicle '" + collider->getID() + "', removing vehicle '" + victim->getID();
1166  }
1167 #else
1168  toRemove.insert(victim);
1169  toRemove.insert(collider);
1170 #endif
1171  break;
1172  }
1173  default:
1174  break;
1175  }
1176  WRITE_WARNING(prefix
1177  + "', lane='" + getID()
1178  + "', gap=" + toString(gap)
1179  + (latGap == 0 ? "" : "', latGap=" + toString(latGap))
1180  + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep())
1181  + " stage=" + stage + ".");
1183 }
1184 
1185 
1186 bool
1187 MSLane::executeMovements(SUMOTime t, std::vector<MSLane*>& lanesWithVehiclesToIntegrate) {
1188  // iterate over vehicles in reverse so that move reminders will be called in the correct order
1189  for (VehCont::reverse_iterator i = myVehicles.rbegin(); i != myVehicles.rend();) {
1190  MSVehicle* veh = *i;
1191  // length is needed later when the vehicle may not exist anymore
1192  const SUMOReal length = veh->getVehicleType().getLengthWithGap();
1193  const SUMOReal nettoLength = veh->getVehicleType().getLength();
1194  const bool moved = veh->executeMove();
1195  MSLane* const target = veh->getLane();
1196 #ifndef NO_TRACI
1197  const bool vtdControlled = veh->hasInfluencer() && veh->getInfluencer().isVTDControlled();
1198  if (veh->hasArrived() && !vtdControlled) {
1199 #else
1200  if (veh->hasArrived()) {
1201 #endif
1202  // vehicle has reached its arrival position
1205  } else if (target != 0 && moved) {
1206  if (target->getEdge().isVaporizing()) {
1207  // vehicle has reached a vaporizing edge
1210  } else {
1211  // vehicle has entered a new lane (leaveLane and workOnMoveReminders were already called in MSVehicle::executeMove)
1212  target->myVehBuffer.push_back(veh);
1213  lanesWithVehiclesToIntegrate.push_back(target);
1214  }
1215  } else if (veh->isParking()) {
1216  // vehicle started to park
1218  } else if (veh->getPositionOnLane() > getLength()) {
1219  // for any reasons the vehicle is beyond its lane...
1220  // this should never happen because it is handled in MSVehicle::executeMove
1221  assert(false);
1222  WRITE_WARNING("Teleporting vehicle '" + veh->getID() + "'; beyond end of lane, target lane='" + getID() + "', time=" +
1223  time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
1226  } else {
1227  ++i;
1228  continue;
1229  }
1230  myBruttoVehicleLengthSum -= length;
1231  myNettoVehicleLengthSum -= nettoLength;
1232  ++i;
1233  i = VehCont::reverse_iterator(myVehicles.erase(i.base()));
1234  }
1235  if (myVehicles.size() > 0) {
1237  MSVehicle* veh = myVehicles.back(); // the vehice at the front of the queue
1238  if (!veh->isStopped() && veh->getLane() == this) {
1239  const bool wrongLane = !veh->getLane()->appropriate(veh);
1241  const bool r2 = MSGlobals::gTimeToGridlockHighways > 0 && veh->getWaitingTime() > MSGlobals::gTimeToGridlockHighways && veh->getLane()->getSpeedLimit() > 69. / 3.6 && wrongLane;
1242  if (r1 || r2) {
1243  const MSLinkCont::const_iterator link = succLinkSec(*veh, 1, *this, veh->getBestLanesContinuation());
1244  const bool minorLink = !wrongLane && (link != myLinks.end()) && !((*link)->havePriority());
1245  const std::string reason = (wrongLane ? " (wrong lane)" : (minorLink ? " (yield)" : " (jam)"));
1246  MSVehicle* veh = *(myVehicles.end() - 1);
1249  myVehicles.erase(myVehicles.end() - 1);
1250  WRITE_WARNING("Teleporting vehicle '" + veh->getID() + "'; waited too long"
1251  + reason
1252  + (r2 ? " (highway)" : "")
1253  + ", lane='" + getID() + "', time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
1254  if (wrongLane) {
1256  } else if (minorLink) {
1258  } else {
1260  }
1262  }
1263  } // else look for a (waiting) vehicle that isn't stopped?
1264  }
1265  }
1267  // trigger sorting of vehicles as their order may have changed
1268  lanesWithVehiclesToIntegrate.push_back(this);
1269  }
1270  return myVehicles.size() == 0;
1271 }
1272 
1273 
1274 const MSEdge*
1276  const MSEdge* e = myEdge;
1277  while (e->getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL) {
1278  e = e->getSuccessors()[0];
1279  }
1280  return e;
1281 }
1282 
1283 
1284 // ------ Static (sic!) container methods ------
1285 bool
1286 MSLane::dictionary(const std::string& id, MSLane* ptr) {
1287  DictType::iterator it = myDict.find(id);
1288  if (it == myDict.end()) {
1289  // id not in myDict.
1290  myDict.insert(DictType::value_type(id, ptr));
1291  return true;
1292  }
1293  return false;
1294 }
1295 
1296 
1297 MSLane*
1298 MSLane::dictionary(const std::string& id) {
1299  DictType::iterator it = myDict.find(id);
1300  if (it == myDict.end()) {
1301  // id not in myDict.
1302  return 0;
1303  }
1304  return it->second;
1305 }
1306 
1307 
1308 void
1310  for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
1311  delete(*i).second;
1312  }
1313  myDict.clear();
1314 }
1315 
1316 
1317 void
1318 MSLane::insertIDs(std::vector<std::string>& into) {
1319  for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
1320  into.push_back((*i).first);
1321  }
1322 }
1323 
1324 
1325 template<class RTREE> void
1326 MSLane::fill(RTREE& into) {
1327  for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
1328  MSLane* l = (*i).second;
1329  Boundary b = l->getShape().getBoxBoundary();
1330  b.grow(3.);
1331  const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
1332  const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
1333  into.Insert(cmin, cmax, l);
1334  }
1335 }
1336 
1337 template void MSLane::fill<NamedRTree>(NamedRTree& into);
1338 #ifndef NO_TRACI
1339 template void MSLane::fill<LANE_RTREE_QUAL>(LANE_RTREE_QUAL& into);
1340 #endif
1341 
1342 // ------ ------
1343 bool
1346  return true;
1347  }
1348  if (veh->succEdge(1) == 0) {
1349  assert((int)veh->getBestLanes().size() > veh->getLaneIndex());
1350  if (veh->getBestLanes()[veh->getLaneIndex()].bestLaneOffset == 0) {
1351  return true;
1352  } else {
1353  return false;
1354  }
1355  }
1356  MSLinkCont::const_iterator link = succLinkSec(*veh, 1, *this, veh->getBestLanesContinuation());
1357  return (link != myLinks.end());
1358 }
1359 
1360 
1361 bool
1363  //std::cout << SIMTIME << " integrateNewVehicle lane=" << getID() << "\n";
1364  bool wasInactive = myVehicles.size() == 0;
1365  sort(myVehBuffer.begin(), myVehBuffer.end(), vehicle_position_sorter(this));
1366  for (std::vector<MSVehicle*>::const_iterator i = myVehBuffer.begin(); i != myVehBuffer.end(); ++i) {
1367  MSVehicle* veh = *i;
1368  assert(veh->getLane() == this);
1369  myVehicles.insert(myVehicles.begin(), veh);
1372  //if (true) std::cout << SIMTIME << " integrateNewVehicle lane=" << getID() << " veh=" << veh->getID() << " (on lane " << veh->getLane()->getID() << ") into lane=" << getID() << " myBrutto=" << myBruttoVehicleLengthSum << "\n";
1373  myEdge->markDelayed();
1374  }
1375  myVehBuffer.clear();
1376  //std::cout << SIMTIME << " integrateNewVehicle lane=" << getID() << " myVehicles1=" << toString(myVehicles);
1378  sort(myVehicles.begin(), myVehicles.end(), vehicle_natural_position_sorter(this));
1379  }
1381  //std::cout << " myVehicles2=" << toString(myVehicles) << "\n";
1382  return wasInactive && myVehicles.size() != 0;
1383 }
1384 
1385 
1386 void
1388  if (myPartialVehicles.size() > 1) {
1390  }
1391 }
1392 
1393 bool
1394 MSLane::isLinkEnd(MSLinkCont::const_iterator& i) const {
1395  return i == myLinks.end();
1396 }
1397 
1398 
1399 bool
1400 MSLane::isLinkEnd(MSLinkCont::iterator& i) {
1401  return i == myLinks.end();
1402 }
1403 
1404 bool
1406  return myVehicles.empty() && myPartialVehicles.empty();
1407 }
1408 
1409 bool
1412 }
1413 
1414 MSVehicle*
1416  if (myVehicles.size() == 0) {
1417  return 0;
1418  }
1419  return myVehicles.front();
1420 }
1421 
1422 
1423 MSVehicle*
1425  if (myVehicles.size() == 0) {
1426  return 0;
1427  }
1428  return myVehicles.back();
1429 }
1430 
1431 
1432 MSVehicle*
1434  // all vehicles in myVehicles should have positions smaller or equal to
1435  // those in myPartialVehicles
1436  if (myVehicles.size() > 0) {
1437  return myVehicles.front();
1438  }
1439  if (myPartialVehicles.size() > 0) {
1440  return myPartialVehicles.front();
1441  }
1442  return 0;
1443 }
1444 
1445 
1446 MSVehicle*
1448  MSVehicle* result = 0;
1449  if (myVehicles.size() > 0) {
1450  result = myVehicles.back();
1451  }
1452  if (myPartialVehicles.size() > 0
1453  && (result == 0 || result->getPositionOnLane(this) < myPartialVehicles.back()->getPositionOnLane(this))) {
1454  result = myPartialVehicles.back();
1455  }
1456  return result;
1457 }
1458 
1459 
1460 MSLinkCont::const_iterator
1461 MSLane::succLinkSec(const SUMOVehicle& veh, int nRouteSuccs,
1462  const MSLane& succLinkSource, const std::vector<MSLane*>& conts) {
1463  const MSEdge* nRouteEdge = veh.succEdge(nRouteSuccs);
1464  // check whether the vehicle tried to look beyond its route
1465  if (nRouteEdge == 0) {
1466  // return end (no succeeding link) if so
1467  return succLinkSource.myLinks.end();
1468  }
1469  // if we are on an internal lane there should only be one link and it must be allowed
1470  if (succLinkSource.isInternal()) {
1471  assert(succLinkSource.myLinks.size() == 1);
1472  // could have been disallowed dynamically with a rerouter or via TraCI
1473  // assert(succLinkSource.myLinks[0]->getLane()->allowsVehicleClass(veh.getVehicleType().getVehicleClass()));
1474  return succLinkSource.myLinks.begin();
1475  }
1476  // a link may be used if
1477  // 1) there is a destination lane ((*link)->getLane()!=0)
1478  // 2) the destination lane belongs to the next edge in route ((*link)->getLane()->myEdge == nRouteEdge)
1479  // 3) the destination lane allows the vehicle's class ((*link)->getLane()->allowsVehicleClass(veh.getVehicleClass()))
1480 
1481  // there should be a link which leads to the next desired lane our route in "conts" (built in "getBestLanes")
1482  // "conts" stores the best continuations of our current lane
1483  // we should never return an arbitrary link since this may cause collisions
1484 
1485  MSLinkCont::const_iterator link;
1486  if (nRouteSuccs < (int)conts.size()) {
1487  // we go through the links in our list and return the matching one
1488  for (link = succLinkSource.myLinks.begin(); link != succLinkSource.myLinks.end(); ++link) {
1489  if ((*link)->getLane() != 0 && (*link)->getLane()->myEdge == nRouteEdge && (*link)->getLane()->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
1490  // we should use the link if it connects us to the best lane
1491  if ((*link)->getLane() == conts[nRouteSuccs]) {
1492  return link;
1493  }
1494  }
1495  }
1496  } else {
1497  // the source lane is a dead end (no continuations exist)
1498  return succLinkSource.myLinks.end();
1499  }
1500  // the only case where this should happen is for a disconnected route (deliberately ignored)
1501 #ifdef _DEBUG
1502  // the "'" around the ids are missing intentionally in the message below because it slows messaging down, resulting in test timeouts
1503  WRITE_WARNING("Could not find connection between lane " + succLinkSource.getID() + " and lane " + conts[nRouteSuccs]->getID() +
1504  " for vehicle " + veh.getID() + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
1505 #endif
1506  return succLinkSource.myLinks.end();
1507 }
1508 
1509 
1510 
1511 const MSLinkCont&
1513  return myLinks;
1514 }
1515 
1516 
1517 void
1519  myMaxSpeed = val;
1520  myEdge->recalcCache();
1521 }
1522 
1523 
1524 void
1526  myLength = val;
1527  myEdge->recalcCache();
1528 }
1529 
1530 
1531 void
1533  //if (getID() == "disabled_lane") std::cout << SIMTIME << " swapAfterLaneChange lane=" << getID() << " myVehicles=" << toString(myVehicles) << " myTmpVehicles=" << toString(myTmpVehicles) << "\n";
1535  myTmpVehicles.clear();
1536  // this needs to be done after finishing lane-changing for all lanes on the
1537  // current edge (MSLaneChanger::updateLanes())
1539 }
1540 
1541 
1542 MSVehicle*
1543 MSLane::removeVehicle(MSVehicle* remVehicle, MSMoveReminder::Notification notification, bool notify) {
1544  assert(remVehicle->getLane() == this);
1545  for (MSLane::VehCont::iterator it = myVehicles.begin(); it < myVehicles.end(); it++) {
1546  if (remVehicle == *it) {
1547  if (notify) {
1548  remVehicle->leaveLane(notification);
1549  }
1550  myVehicles.erase(it);
1553  break;
1554  }
1555  }
1556  return remVehicle;
1557 }
1558 
1559 
1560 MSLane*
1561 MSLane::getParallelLane(int offset) const {
1562  return myEdge->parallelLane(this, offset);
1563 }
1564 
1565 
1566 void
1568  IncomingLaneInfo ili;
1569  ili.lane = lane;
1570  ili.viaLink = viaLink;
1571  ili.length = lane->getLength();
1572  myIncomingLanes.push_back(ili);
1573 }
1574 
1575 
1576 void
1577 MSLane::addApproachingLane(MSLane* lane, bool warnMultiCon) {
1578  MSEdge* approachingEdge = &lane->getEdge();
1579  if (myApproachingLanes.find(approachingEdge) == myApproachingLanes.end()) {
1580  myApproachingLanes[approachingEdge] = std::vector<MSLane*>();
1581  } else if (approachingEdge->getPurpose() != MSEdge::EDGEFUNCTION_INTERNAL && warnMultiCon) {
1582  // whenever a normal edge connects twice, there is a corresponding
1583  // internal edge wich connects twice, one warning is sufficient
1584  WRITE_WARNING("Lane '" + getID() + "' is approached multiple times from edge '" + approachingEdge->getID() + "'. This may cause collisions.");
1585  }
1586  myApproachingLanes[approachingEdge].push_back(lane);
1587 }
1588 
1589 
1590 bool
1592  return myApproachingLanes.find(edge) != myApproachingLanes.end();
1593 }
1594 
1595 
1596 bool
1597 MSLane::isApproachedFrom(MSEdge* const edge, MSLane* const lane) {
1598  std::map<MSEdge*, std::vector<MSLane*> >::const_iterator i = myApproachingLanes.find(edge);
1599  if (i == myApproachingLanes.end()) {
1600  return false;
1601  }
1602  const std::vector<MSLane*>& lanes = (*i).second;
1603  return find(lanes.begin(), lanes.end(), lane) != lanes.end();
1604 }
1605 
1606 
1608 public:
1609  inline int operator()(const std::pair<const MSVehicle*, SUMOReal>& p1, const std::pair<const MSVehicle*, SUMOReal>& p2) const {
1610  return p1.second < p2.second;
1611  }
1612 };
1613 
1614 
1616  SUMOReal backOffset, SUMOReal leaderSpeed, SUMOReal leaderMaxDecel) const {
1617  // this follows the same logic as getFollowerOnConsecutive. we do a tree
1618  // search and check for the vehicle with the largest missing rear gap within
1619  // relevant range
1620  SUMOReal result = 0;
1621  std::pair<MSVehicle* const, SUMOReal> followerInfo = getFollowerOnConsecutive(backOffset, leaderSpeed, leaderMaxDecel);
1622  MSVehicle* v = followerInfo.first;
1623  if (v != 0) {
1624  result = v->getCarFollowModel().getSecureGap(v->getSpeed(), leaderSpeed, leaderMaxDecel) - followerInfo.second;
1625  }
1626  return result;
1627 }
1628 
1629 
1630 SUMOReal
1633  const SUMOReal maxSpeed = getSpeedLimit() * vc.getMaxSpeedFactor();
1634  // NOTE: For the euler update this is an upper bound on the actual braking distance (see ticket #860)
1635  return maxSpeed * maxSpeed * 0.5 / vc.getMinDeceleration();
1636 }
1637 
1638 
1639 std::pair<MSVehicle* const, SUMOReal>
1641  SUMOReal backOffset, SUMOReal leaderSpeed, SUMOReal leaderMaxDecel, SUMOReal dist) const {
1642  // do a tree search among all follower lanes and check for the most
1643  // important vehicle (the one requiring the largest reargap)
1644  // to get a safe bound on the necessary search depth, we need to consider the maximum speed and minimum
1645  // deceleration of potential follower vehicles
1646  if (dist == -1) {
1647  dist = getMaximumBrakeDist() - backOffset;
1648  }
1649 #ifdef DEBUG_CONTEXT
1650  if (DEBUG_COND) std::cout << SIMTIME << " getFollowerOnConsecutive"
1651  << " backOffset=" << backOffset
1652  << " leaderSpeed=" << leaderSpeed
1653  << " dist=" << dist
1654  << "\n";
1655 #endif
1656  std::pair<MSVehicle*, SUMOReal> result(static_cast<MSVehicle*>(0), -1);
1657  SUMOReal missingRearGapMax = -std::numeric_limits<SUMOReal>::max();
1658  std::set<MSLane*> visited;
1659  std::vector<MSLane::IncomingLaneInfo> newFound;
1660  std::vector<MSLane::IncomingLaneInfo> toExamine = myIncomingLanes;
1661  while (toExamine.size() != 0) {
1662  for (std::vector<MSLane::IncomingLaneInfo>::iterator i = toExamine.begin(); i != toExamine.end(); ++i) {
1663  MSLane* next = (*i).lane;
1664 #ifdef DEBUG_CONTEXT
1665  if (DEBUG_COND) {
1666  std::cout << SIMTIME << " nextLane=" << next->getID() << "\n";
1667  }
1668 #endif
1669  // XXX: why take a MAX here? Even if some upcoming lane allows to go faster, the follower should be able
1670  // to brake in time if we only consider 'next->getMaximumBrakeDist() - backOffset'.
1671  dist = MAX2(dist, next->getMaximumBrakeDist() - backOffset);
1672  // Checking the first vehicle on the considered lane.
1673  // XXX: Could there be a problem if someone fast is just overtaking a a slow first vehicle, e.g.? (Leo) Refs.#2578
1674  MSVehicle* v = next->getFirstAnyVehicle();
1675  SUMOReal agap = 0;
1676  if (v != 0) {
1677  // the front of v is already on divergent trajectory from the ego vehicle
1678  // for which this method is called (in the context of MSLaneChanger).
1679  // Therefore, technically v is not a follower but only an obstruction and
1680  // the gap is not between the front of v and the back of ego
1681  // but rather between the flank of v and the back of ego.
1682  if (!v->isFrontOnLane(next)) {
1683  agap = (*i).length - next->getLength() + backOffset
1685  - v->getVehicleType().getMinGap();
1686  if (agap > 0) {
1687  // Only if ego overlaps we treat v as if it were a real follower
1688  // Otherwise we ignore it and look for another follower
1689  v = next->getFirstFullVehicle();
1690  if (v != 0) {
1691  agap = (*i).length - v->getPositionOnLane() + backOffset - v->getVehicleType().getMinGap();
1692  }
1693  }
1694  } else {
1695  agap = (*i).length - v->getPositionOnLane() + backOffset - v->getVehicleType().getMinGap();
1696  }
1697 #ifdef DEBUG_CONTEXT
1698  if (DEBUG_COND) std::cout << SIMTIME << " "
1699  << " v=" << Named::getIDSecure(v)
1700  << " agap=" << agap
1701  << " dist=" << dist
1702  << "\n";
1703 #endif
1704  }
1705  if (v != 0) {
1706  const SUMOReal missingRearGap = v->getCarFollowModel().getSecureGap(v->getSpeed(), leaderSpeed, leaderMaxDecel) - agap;
1707  if (missingRearGap > missingRearGapMax) {
1708  missingRearGapMax = missingRearGap;
1709  result.first = v;
1710  result.second = agap;
1711  }
1712  } else {
1713  if ((*i).length < dist) {
1714  const std::vector<MSLane::IncomingLaneInfo>& followers = next->getIncomingLanes();
1715  for (std::vector<MSLane::IncomingLaneInfo>::const_iterator j = followers.begin(); j != followers.end(); ++j) {
1716  if (visited.find((*j).lane) == visited.end()) {
1717  visited.insert((*j).lane);
1719  ili.lane = (*j).lane;
1720  ili.length = (*j).length + (*i).length;
1721  ili.viaLink = (*j).viaLink;
1722  newFound.push_back(ili);
1723  }
1724  }
1725  }
1726  }
1727  }
1728  toExamine.clear();
1729  swap(newFound, toExamine);
1730  }
1731  return result;
1732 }
1733 
1734 std::pair<MSVehicle* const, SUMOReal>
1735 MSLane::getLeader(const MSVehicle* veh, const SUMOReal vehPos, const std::vector<MSLane*>& bestLaneConts, SUMOReal dist, bool checkTmpVehicles) const {
1736  // get the leading vehicle for (shadow) veh
1737  // XXX this only works as long as all lanes of an edge have equal length
1738 #ifdef DEBUG_CONTEXT
1739  if (DEBUG_COND2(veh)) {
1740  std::cout << " getLeader lane=" << getID() << " ego=" << veh->getID() << " vehs=" << toString(myVehicles) << " tmpVehs=" << toString(myTmpVehicles) << "\n";
1741  }
1742 #endif
1743  if (checkTmpVehicles) {
1744  for (VehCont::const_iterator last = myTmpVehicles.begin(); last != myTmpVehicles.end(); ++last) {
1745  // XXX refactor leaderInfo to use a const vehicle all the way through the call hierarchy
1746  MSVehicle* pred = (MSVehicle*)*last;
1747 #ifdef DEBUG_CONTEXT
1748  if (DEBUG_COND2(veh)) {
1749  std::cout << " getLeader lane=" << getID() << " ego=" << veh->getID() << " egoPos=" << vehPos << " pred=" << pred->getID() << " predPos=" << pred->getPositionOnLane() << "\n";
1750  }
1751 #endif
1752  if (pred->getPositionOnLane() > vehPos + NUMERICAL_EPS) {
1753  return std::pair<MSVehicle* const, SUMOReal>(pred, pred->getBackPositionOnLane(this) - veh->getVehicleType().getMinGap() - vehPos);
1754  }
1755  }
1756  } else {
1757  for (AnyVehicleIterator last = anyVehiclesBegin(); last != anyVehiclesEnd(); ++last) {
1758  // XXX refactor leaderInfo to use a const vehicle all the way through the call hierarchy
1759  MSVehicle* pred = (MSVehicle*)*last;
1760 #ifdef DEBUG_CONTEXT
1761  if (DEBUG_COND2(veh)) {
1762  std::cout << " getLeader lane=" << getID() << " ego=" << veh->getID() << " egoPos=" << vehPos << " pred=" << pred->getID() << " predPos=" << pred->getPositionOnLane() << "\n";
1763  }
1764 #endif
1765  if (pred->getPositionOnLane() > vehPos + NUMERICAL_EPS) {
1766  return std::pair<MSVehicle* const, SUMOReal>(pred, pred->getBackPositionOnLane(this) - veh->getVehicleType().getMinGap() - vehPos);
1767  }
1768  }
1769  }
1770  // XXX from here on the code mirrors MSLaneChanger::getRealLeader
1771  if (bestLaneConts.size() > 0) {
1772  SUMOReal seen = getLength() - vehPos;
1773  SUMOReal speed = veh->getSpeed();
1774  if (dist < 0) {
1775  dist = veh->getCarFollowModel().brakeGap(speed) + veh->getVehicleType().getMinGap();
1776  }
1777 #ifdef DEBUG_CONTEXT
1778  if (DEBUG_COND2(veh)) {
1779  std::cout << " getLeader lane=" << getID() << " seen=" << seen << " dist=" << dist << "\n";
1780  }
1781 #endif
1782  if (seen > dist) {
1783  return std::pair<MSVehicle* const, SUMOReal>(static_cast<MSVehicle*>(0), -1);
1784  }
1785  return getLeaderOnConsecutive(dist, seen, speed, *veh, bestLaneConts);
1786  } else {
1787  return std::make_pair(static_cast<MSVehicle*>(0), -1);
1788  }
1789 }
1790 
1791 
1792 std::pair<MSVehicle* const, SUMOReal>
1794  const std::vector<MSLane*>& bestLaneConts) const {
1795 #ifdef DEBUG_CONTEXT
1796  if (DEBUG_COND2(&veh)) {
1797  std::cout << " getLeaderOnConsecutive lane=" << getID() << " ego=" << veh.getID() << " seen=" << seen << " dist=" << dist << " conts=" << toString(bestLaneConts) << "\n";
1798  }
1799 #endif
1800  if (seen > dist) {
1801  return std::make_pair(static_cast<MSVehicle*>(0), -1);
1802  }
1803  int view = 1;
1804  // loop over following lanes
1805  if (myPartialVehicles.size() > 0) {
1806  // XXX
1807  MSVehicle* pred = myPartialVehicles.front();
1808 #ifdef DEBUG_CONTEXT
1809  if (DEBUG_COND2(&veh)) {
1810  std::cout << " partials=" << toString(myPartialVehicles) << "\n";
1811  }
1812 #endif
1813  return std::pair<MSVehicle* const, SUMOReal>(pred, seen - (getLength() - pred->getBackPositionOnLane(this)) - veh.getVehicleType().getMinGap());
1814  }
1815  const MSLane* nextLane = this;
1816  SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / MAX2(speed, NUMERICAL_EPS));
1817  do {
1818  nextLane->getVehiclesSecure(); // lock against running sim when called from GUI for time gap coloring
1819  // get the next link used
1820  MSLinkCont::const_iterator link = succLinkSec(veh, view, *nextLane, bestLaneConts);
1821  if (nextLane->isLinkEnd(link) || !(*link)->opened(arrivalTime, speed, speed, veh.getVehicleType().getLength(),
1822  veh.getImpatience(), veh.getCarFollowModel().getMaxDecel(), 0, veh.getLateralPositionOnLane()) || (*link)->haveRed()) {
1823 #ifdef DEBUG_CONTEXT
1824  if (DEBUG_COND2(&veh)) {
1825  std::cout << " cannot continue after nextLane=" << nextLane->getID() << "\n";
1826  }
1827 #endif
1828  nextLane->releaseVehicles();
1829  break;
1830  }
1831 #ifdef HAVE_INTERNAL_LANES
1832  // check for link leaders
1833  const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(seen, veh.getVehicleType().getMinGap());
1834  nextLane->releaseVehicles();
1835  if (linkLeaders.size() > 0) {
1836  // XXX if there is more than one link leader we should return the most important
1837  // one (gap, decel) but this is hard to know at this point
1838 #ifdef DEBUG_CONTEXT
1839  if (DEBUG_COND2(&veh)) {
1840  std::cout << " found linkLeader after nextLane=" << nextLane->getID() << "\n";
1841  }
1842 #endif
1843  return linkLeaders[0].vehAndGap;
1844  }
1845  bool nextInternal = (*link)->getViaLane() != 0;
1846 #endif
1847  nextLane = (*link)->getViaLaneOrLane();
1848  if (nextLane == 0) {
1849  break;
1850  }
1851  nextLane->getVehiclesSecure(); // lock against running sim when called from GUI for time gap coloring
1852  MSVehicle* leader = nextLane->getLastAnyVehicle();
1853  if (leader != 0) {
1854 #ifdef DEBUG_CONTEXT
1855  if (DEBUG_COND2(&veh)) {
1856  std::cout << " found leader " << leader->getID() << " on nextLane=" << nextLane->getID() << "\n";
1857  }
1858 #endif
1859  const SUMOReal dist = seen + leader->getBackPositionOnLane(nextLane) - veh.getVehicleType().getMinGap();
1860  nextLane->releaseVehicles();
1861  return std::make_pair(leader, dist);
1862  }
1863  nextLane->releaseVehicles();
1864  if (nextLane->getVehicleMaxSpeed(&veh) < speed) {
1865  dist = veh.getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(&veh));
1866  }
1867  seen += nextLane->getLength();
1868  if (seen <= dist) {
1869  // delaying the update of arrivalTime and making it conditional to avoid possible integer overflows
1870  arrivalTime += TIME2STEPS(nextLane->getLength() / MAX2(speed, NUMERICAL_EPS));
1871  }
1872 #ifdef HAVE_INTERNAL_LANES
1873  if (!nextInternal) {
1874  view++;
1875  }
1876 #else
1877  view++;
1878 #endif
1879  } while (seen <= dist);
1880  return std::make_pair(static_cast<MSVehicle*>(0), -1);
1881 }
1882 
1883 
1884 std::pair<MSVehicle* const, SUMOReal>
1885 MSLane::getCriticalLeader(SUMOReal dist, SUMOReal seen, SUMOReal speed, const MSVehicle& veh) const {
1886  const std::vector<MSLane*>& bestLaneConts = veh.getBestLanesContinuation(this);
1887  std::pair<MSVehicle*, SUMOReal> result = std::make_pair(static_cast<MSVehicle*>(0), -1);
1889  int view = 1;
1890  // loop over following lanes
1891  // @note: we don't check the partial occupator for this lane since it was
1892  // already checked in MSLaneChanger::getRealLeader()
1893  const MSLane* nextLane = this;
1894  SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / MAX2(speed, NUMERICAL_EPS));
1895  do {
1896  // get the next link used
1897  MSLinkCont::const_iterator link = succLinkSec(veh, view, *nextLane, bestLaneConts);
1898  if (nextLane->isLinkEnd(link) || !(*link)->opened(arrivalTime, speed, speed, veh.getVehicleType().getLength(),
1899  veh.getImpatience(), veh.getCarFollowModel().getMaxDecel(), 0, veh.getLateralPositionOnLane()) || (*link)->haveRed()) {
1900  return result;
1901  }
1902 #ifdef HAVE_INTERNAL_LANES
1903  // check for link leaders
1904  const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(seen, veh.getVehicleType().getMinGap());
1905  for (MSLink::LinkLeaders::const_iterator it = linkLeaders.begin(); it != linkLeaders.end(); ++it) {
1906  const MSVehicle* leader = (*it).vehAndGap.first;
1907  if (leader != 0 && leader != result.first) {
1908  // XXX ignoring pedestrians here!
1909  // XXX ignoring the fact that the link leader may alread by following us
1910  // XXX ignoring the fact that we may drive up to the crossing point
1911  const SUMOReal tmpSpeed = veh.getSafeFollowSpeed((*it).vehAndGap, seen, nextLane, (*it).distToCrossing);
1912  if (tmpSpeed < safeSpeed) {
1913  safeSpeed = tmpSpeed;
1914  result = (*it).vehAndGap;
1915  }
1916  }
1917  }
1918  bool nextInternal = (*link)->getViaLane() != 0;
1919 #endif
1920  nextLane = (*link)->getViaLaneOrLane();
1921  if (nextLane == 0) {
1922  break;
1923  }
1924  MSVehicle* leader = nextLane->getLastAnyVehicle();
1925  if (leader != 0 && leader != result.first) {
1926  const SUMOReal gap = seen + leader->getBackPositionOnLane(nextLane) - veh.getVehicleType().getMinGap();
1927  const SUMOReal tmpSpeed = veh.getCarFollowModel().insertionFollowSpeed(leader, speed, gap, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
1928  if (tmpSpeed < safeSpeed) {
1929  safeSpeed = tmpSpeed;
1930  result = std::make_pair(leader, gap);
1931  }
1932  }
1933  if (nextLane->getVehicleMaxSpeed(&veh) < speed) {
1934  dist = veh.getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(&veh));
1935  }
1936  seen += nextLane->getLength();
1937  if (seen <= dist) {
1938  // delaying the update of arrivalTime and making it conditional to avoid possible integer overflows
1939  arrivalTime += TIME2STEPS(nextLane->getLength() / MAX2(speed, NUMERICAL_EPS));
1940  }
1941 #ifdef HAVE_INTERNAL_LANES
1942  if (!nextInternal) {
1943  view++;
1944  }
1945 #else
1946  view++;
1947 #endif
1948  } while (seen <= dist);
1949  return result;
1950 }
1951 
1952 
1953 MSLane*
1955  if (myLogicalPredecessorLane != 0) {
1956  return myLogicalPredecessorLane;
1957  }
1958  if (myLogicalPredecessorLane == 0) {
1960  // get only those edges which connect to this lane
1961  for (MSEdgeVector::iterator i = pred.begin(); i != pred.end();) {
1962  std::vector<IncomingLaneInfo>::const_iterator j = find_if(myIncomingLanes.begin(), myIncomingLanes.end(), edge_finder(*i));
1963  if (j == myIncomingLanes.end()) {
1964  i = pred.erase(i);
1965  } else {
1966  ++i;
1967  }
1968  }
1969  // get the lane with the "straightest" connection
1970  if (pred.size() != 0) {
1971  std::sort(pred.begin(), pred.end(), by_connections_to_sorter(&getEdge()));
1972  MSEdge* best = *pred.begin();
1973  std::vector<IncomingLaneInfo>::const_iterator j = find_if(myIncomingLanes.begin(), myIncomingLanes.end(), edge_finder(best));
1974  myLogicalPredecessorLane = (*j).lane;
1975  }
1976  }
1977  return myLogicalPredecessorLane;
1978 }
1979 
1980 
1981 MSLane*
1983  for (std::vector<IncomingLaneInfo>::const_iterator i = myIncomingLanes.begin(); i != myIncomingLanes.end(); ++i) {
1984  MSLane* cand = (*i).lane;
1985  if (&(cand->getEdge()) == &fromEdge) {
1986  return (*i).lane;
1987  }
1988  }
1989  return 0;
1990 }
1991 
1992 
1993 LinkState
1996  if (pred == 0) {
1997  return LINKSTATE_DEADEND;
1998  } else {
1999  return MSLinkContHelper::getConnectingLink(*pred, *this)->getState();
2000  }
2001 }
2002 
2003 
2004 std::vector<const MSLane*>
2006  std::vector<const MSLane*> result;
2007  for (MSLinkCont::const_iterator i = myLinks.begin(); i != myLinks.end(); ++i) {
2008  assert((*i)->getLane() != 0);
2009  result.push_back((*i)->getLane());
2010  }
2011  return result;
2012 }
2013 
2014 
2015 void
2019 }
2020 
2021 
2022 void
2026 }
2027 
2028 
2029 int
2031  for (MSLinkCont::const_iterator i = myLinks.begin(); i != myLinks.end(); ++i) {
2032  if ((*i)->getLane()->getEdge().isCrossing()) {
2033  return (int)(i - myLinks.begin());
2034  }
2035  }
2036  return -1;
2037 }
2038 
2039 // ------------ Current state retrieval
2040 SUMOReal
2042  SUMOReal fractions = myPartialVehicles.size() > 0 ? myLength - myPartialVehicles.front()->getBackPositionOnLane(this) : 0;
2044  if (myVehicles.size() != 0) {
2045  MSVehicle* lastVeh = myVehicles.front();
2046  if (lastVeh->getPositionOnLane() < lastVeh->getVehicleType().getLength()) {
2047  fractions -= (lastVeh->getVehicleType().getLength() - lastVeh->getPositionOnLane());
2048  }
2049  }
2050  releaseVehicles();
2051  return (myBruttoVehicleLengthSum + fractions) / myLength;
2052 }
2053 
2054 
2055 SUMOReal
2057  SUMOReal fractions = myPartialVehicles.size() > 0 ? myLength - myPartialVehicles.front()->getBackPositionOnLane(this) : 0;
2059  if (myVehicles.size() != 0) {
2060  MSVehicle* lastVeh = myVehicles.front();
2061  if (lastVeh->getPositionOnLane() < lastVeh->getVehicleType().getLength()) {
2062  fractions -= (lastVeh->getVehicleType().getLength() - lastVeh->getPositionOnLane());
2063  }
2064  }
2065  releaseVehicles();
2066  return (myNettoVehicleLengthSum + fractions) / myLength;
2067 }
2068 
2069 
2070 SUMOReal
2072  if (myVehicles.size() == 0) {
2073  return 0;
2074  }
2075  SUMOReal wtime = 0;
2076  for (VehCont::const_iterator i = myVehicles.begin(); i != myVehicles.end(); ++i) {
2077  wtime += (*i)->getWaitingSeconds();
2078  }
2079  return wtime;
2080 }
2081 
2082 
2083 SUMOReal
2085  if (myVehicles.size() == 0) {
2086  return myMaxSpeed;
2087  }
2088  SUMOReal v = 0;
2089  const MSLane::VehCont& vehs = getVehiclesSecure();
2090  for (VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
2091  v += (*i)->getSpeed();
2092  }
2093  SUMOReal ret = v / (SUMOReal) myVehicles.size();
2094  releaseVehicles();
2095  return ret;
2096 }
2097 
2098 
2099 SUMOReal
2101  SUMOReal ret = 0;
2102  const MSLane::VehCont& vehs = getVehiclesSecure();
2103  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
2104  ret += (*i)->getCO2Emissions();
2105  }
2106  releaseVehicles();
2107  return ret;
2108 }
2109 
2110 
2111 SUMOReal
2113  SUMOReal ret = 0;
2114  const MSLane::VehCont& vehs = getVehiclesSecure();
2115  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
2116  ret += (*i)->getCOEmissions();
2117  }
2118  releaseVehicles();
2119  return ret;
2120 }
2121 
2122 
2123 SUMOReal
2125  SUMOReal ret = 0;
2126  const MSLane::VehCont& vehs = getVehiclesSecure();
2127  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
2128  ret += (*i)->getPMxEmissions();
2129  }
2130  releaseVehicles();
2131  return ret;
2132 }
2133 
2134 
2135 SUMOReal
2137  SUMOReal ret = 0;
2138  const MSLane::VehCont& vehs = getVehiclesSecure();
2139  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
2140  ret += (*i)->getNOxEmissions();
2141  }
2142  releaseVehicles();
2143  return ret;
2144 }
2145 
2146 
2147 SUMOReal
2149  SUMOReal ret = 0;
2150  const MSLane::VehCont& vehs = getVehiclesSecure();
2151  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
2152  ret += (*i)->getHCEmissions();
2153  }
2154  releaseVehicles();
2155  return ret;
2156 }
2157 
2158 
2159 SUMOReal
2161  SUMOReal ret = 0;
2162  const MSLane::VehCont& vehs = getVehiclesSecure();
2163  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
2164  ret += (*i)->getFuelConsumption();
2165  }
2166  releaseVehicles();
2167  return ret;
2168 }
2169 
2170 
2171 SUMOReal
2173  SUMOReal ret = 0;
2174  const MSLane::VehCont& vehs = getVehiclesSecure();
2175  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
2176  ret += (*i)->getElectricityConsumption();
2177  }
2178  releaseVehicles();
2179  return ret;
2180 }
2181 
2182 
2183 SUMOReal
2185  SUMOReal ret = 0;
2186  const MSLane::VehCont& vehs = getVehiclesSecure();
2187  if (vehs.size() == 0) {
2188  releaseVehicles();
2189  return 0;
2190  }
2191  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
2192  SUMOReal sv = (*i)->getHarmonoise_NoiseEmissions();
2193  ret += (SUMOReal) pow(10., (sv / 10.));
2194  }
2195  releaseVehicles();
2196  return HelpersHarmonoise::sum(ret);
2197 }
2198 
2199 
2200 bool
2202  return cmp->getPositionOnLane() >= pos;
2203 }
2204 
2205 
2206 int
2208  return v1->getBackPositionOnLane(myLane) > v2->getBackPositionOnLane(myLane);
2209 }
2210 
2211 int
2213  const SUMOReal pos1 = v1->getBackPositionOnLane(myLane);
2214  const SUMOReal pos2 = v2->getBackPositionOnLane(myLane);
2215  if (pos1 != pos2) {
2216  return pos1 < pos2;
2217  } else {
2219  }
2220 }
2221 
2223  myEdge(e),
2224  myLaneDir(e->getLanes()[0]->getShape().angleAt2D(0)) {
2225 }
2226 
2227 
2228 int
2229 MSLane::by_connections_to_sorter::operator()(const MSEdge* const e1, const MSEdge* const e2) const {
2230  const std::vector<MSLane*>* ae1 = e1->allowedLanes(*myEdge);
2231  const std::vector<MSLane*>* ae2 = e2->allowedLanes(*myEdge);
2232  SUMOReal s1 = 0;
2233  if (ae1 != 0 && ae1->size() != 0) {
2234  s1 = (SUMOReal) ae1->size() + fabs(GeomHelper::angleDiff((*ae1)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.;
2235  }
2236  SUMOReal s2 = 0;
2237  if (ae2 != 0 && ae2->size() != 0) {
2238  s2 = (SUMOReal) ae2->size() + fabs(GeomHelper::angleDiff((*ae2)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.;
2239  }
2240  return s1 < s2;
2241 }
2242 
2243 
2244 void
2246  out.openTag(SUMO_TAG_LANE);
2247  out.writeAttr("id", getID()); // using "id" instead of SUMO_ATTR_ID makes the value only show up in xml state
2250  out.closeTag();
2251  out.closeTag();
2252 }
2253 
2254 
2255 void
2256 MSLane::loadState(std::vector<std::string>& vehIds, MSVehicleControl& vc) {
2257  for (std::vector<std::string>::const_iterator it = vehIds.begin(); it != vehIds.end(); ++it) {
2258  MSVehicle* v = dynamic_cast<MSVehicle*>(vc.getVehicle(*it));
2259  assert(v != 0);
2260  v->updateBestLanes(false, this);
2263  }
2264 }
2265 
2266 
2268 MSLane::getFollowersOnConsecutive(const MSVehicle* ego, bool allSublanes) const {
2269  // get the follower vehicle on the lane to change to
2270 #ifdef DEBUG_CONTEXT
2271  if (DEBUG_COND2(ego)) {
2272  std::cout << SIMTIME << " getFollowers lane=" << getID() << " ego=" << ego->getID() << " pos=" << ego->getPositionOnLane() << "\n";
2273  }
2274 #endif
2275  assert(ego != 0);
2276  assert(&ego->getLane()->getEdge() == &getEdge());
2277  const SUMOReal egoLatDist = ego->getLane()->getRightSideOnEdge() - getRightSideOnEdge();
2278  MSCriticalFollowerDistanceInfo result(this, allSublanes ? 0 : ego, allSublanes ? 0 : egoLatDist);
2280  for (AnyVehicleIterator last = anyVehiclesBegin(); last != anyVehiclesEnd(); ++last) {
2281  const MSVehicle* veh = *last;
2282 #ifdef DEBUG_CONTEXT
2283  if (DEBUG_COND2(ego)) {
2284  std::cout << " veh=" << veh->getID() << " lane=" << veh->getLane()->getID() << " pos=" << veh->getPositionOnLane(this) << "\n";
2285  }
2286 #endif
2287  if (veh != ego && veh->getPositionOnLane(this) <= ego->getPositionOnLane()) {
2288  //const SUMOReal latOffset = veh->getLane()->getRightSideOnEdge() - getRightSideOnEdge();
2289  const SUMOReal latOffset = veh->getLatOffset(this);
2290  const SUMOReal dist = ego->getBackPositionOnLane() - veh->getPositionOnLane(this) - veh->getVehicleType().getMinGap();
2291  result.addFollower(veh, ego, dist, latOffset);
2292 #ifdef DEBUG_CONTEXT
2293  if (DEBUG_COND2(ego)) {
2294  std::cout << " (1) added veh=" << veh->getID() << " latOffset=" << latOffset << " result=" << result.toString() << "\n";
2295  }
2296 #endif
2297  }
2298  }
2299 #ifdef DEBUG_CONTEXT
2300  if (DEBUG_COND2(ego)) {
2301  std::cout << " result.numFreeSublanes=" << result.numFreeSublanes() << "\n";
2302  }
2303 #endif
2304  if (result.numFreeSublanes() > 0) {
2305  const SUMOReal backOffset = ego->getBackPositionOnLane(ego->getLane());
2306  // do a tree search among all follower lanes and check for the most
2307  // important vehicle (the one requiring the largest reargap)
2308  // to get a safe bound on the necessary search depth, we need to consider the maximum speed and minimum
2309  // deceleration of potential follower vehicles
2310  SUMOReal dist = getMaximumBrakeDist() - backOffset;
2311 
2312  std::set<MSLane*> visited;
2313  std::vector<MSLane::IncomingLaneInfo> newFound;
2314  std::vector<MSLane::IncomingLaneInfo> toExamine = myIncomingLanes;
2315  while (toExamine.size() != 0) {
2316  for (std::vector<MSLane::IncomingLaneInfo>::iterator it = toExamine.begin(); it != toExamine.end(); ++it) {
2317  MSLane* next = (*it).lane;
2318  dist = MAX2(dist, next->getMaximumBrakeDist() - backOffset);
2319  MSLeaderInfo first = next->getFirstVehicleInformation(0, 0, false);
2320  MSLeaderInfo firstFront = next->getFirstVehicleInformation(0, 0, true);
2321 #ifdef DEBUG_CONTEXT
2322  if (DEBUG_COND2(ego)) {
2323  std::cout << " next=" << next->getID() << " first=" << first.toString() << " firstFront=" << firstFront.toString() << "\n";
2324  }
2325 #endif
2326  for (int i = 0; i < first.numSublanes(); ++i) {
2327  const MSVehicle* v = first[i];
2328  SUMOReal agap = 0;
2329  if (v != 0 && v != ego) {
2330  if (!v->isFrontOnLane(next)) {
2331  // the front of v is already on divergent trajectory from the ego vehicle
2332  // for which this method is called (in the context of MSLaneChanger).
2333  // Therefore, technically v is not a follower but only an obstruction and
2334  // the gap is not between the front of v and the back of ego
2335  // but rather between the flank of v and the back of ego.
2336  agap = (*it).length - next->getLength() + backOffset
2338  - v->getVehicleType().getMinGap();
2339  if (agap > 0) {
2340  // Only if ego overlaps we treat v as if it were a real follower
2341  // Otherwise we ignore it and look for another follower
2342  v = firstFront[i];
2343  if (v != 0 && v != ego) {
2344  agap = (*it).length - v->getPositionOnLane() + backOffset - v->getVehicleType().getMinGap();
2345  } else {
2346  v = 0;
2347  }
2348  }
2349  } else {
2350  agap = (*it).length - v->getPositionOnLane() + backOffset - v->getVehicleType().getMinGap();
2351  }
2352  result.addFollower(v, ego, agap, 0, i);
2353 #ifdef DEBUG_CONTEXT
2354  if (DEBUG_COND2(ego)) {
2355  std::cout << " (2) added veh=" << Named::getIDSecure(v) << " agap=" << agap << " next=" << next->getID() << " result=" << result.toString() << "\n";
2356  }
2357 #endif
2358  }
2359  }
2360  if ((*it).length < dist) {
2361  const std::vector<MSLane::IncomingLaneInfo>& followers = next->getIncomingLanes();
2362  for (std::vector<MSLane::IncomingLaneInfo>::const_iterator j = followers.begin(); j != followers.end(); ++j) {
2363  if (visited.find((*j).lane) == visited.end()) {
2364  visited.insert((*j).lane);
2366  ili.lane = (*j).lane;
2367  ili.length = (*j).length + (*it).length;
2368  ili.viaLink = (*j).viaLink;
2369  newFound.push_back(ili);
2370  }
2371  }
2372  }
2373  }
2374  toExamine.clear();
2375  swap(newFound, toExamine);
2376  }
2377  //return result;
2378 
2379  }
2380  return result;
2381 }
2382 
2383 
2384 void
2386  const std::vector<MSLane*>& bestLaneConts, MSLeaderDistanceInfo& result) const {
2387  if (seen > dist) {
2388  return;
2389  }
2390  // check partial vehicles (they might be on a different route and thus not
2391  // found when iterating along bestLaneConts)
2392  for (VehCont::const_iterator it = myPartialVehicles.begin(); it != myPartialVehicles.end(); ++it) {
2393  MSVehicle* veh = *it;
2394  if (!veh->isFrontOnLane(this)) {
2395  result.addLeader(veh, seen);
2396  } else {
2397  break;
2398  }
2399  }
2400  const MSLane* nextLane = this;
2401  int view = 1;
2402  SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / MAX2(speed, NUMERICAL_EPS));
2403  // loop over following lanes
2404  while (seen < dist && result.numFreeSublanes() > 0) {
2405  // get the next link used
2406  MSLinkCont::const_iterator link = succLinkSec(*ego, view, *nextLane, bestLaneConts);
2407  if (nextLane->isLinkEnd(link) || !(*link)->opened(arrivalTime, speed, speed, ego->getVehicleType().getLength(),
2408  ego->getImpatience(), ego->getCarFollowModel().getMaxDecel(), 0, ego->getLateralPositionOnLane()) || (*link)->haveRed()) {
2409  break;
2410  }
2411 #ifdef HAVE_INTERNAL_LANES
2412  // check for link leaders
2413  const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(seen, ego->getVehicleType().getMinGap());
2414  if (linkLeaders.size() > 0) {
2415  const MSLink::LinkLeader ll = linkLeaders[0];
2416  if (ll.vehAndGap.first != 0) {
2417  // add link leader to all sublanes and return
2418  for (int i = 0; i < result.numSublanes(); ++i) {
2419  MSVehicle* veh = ll.vehAndGap.first;
2420  result.addLeader(veh, ll.vehAndGap.second, 0);
2421  }
2422  return; ;
2423  } // XXX else, deal with pedestrians
2424  }
2425  bool nextInternal = (*link)->getViaLane() != 0;
2426 #endif
2427  nextLane = (*link)->getViaLaneOrLane();
2428  if (nextLane == 0) {
2429  break;
2430  }
2431 
2432  MSLeaderInfo leaders = nextLane->getLastVehicleInformation(0, 0, 0, false);
2433 #ifdef DEBUG_CONTEXT
2434  if (DEBUG_COND2(ego)) {
2435  std::cout << SIMTIME << " getLeadersOnConsecutive lane=" << getID() << " nextLane=" << nextLane->getID() << " leaders=" << leaders.toString() << "\n";
2436  }
2437 #endif
2438  // @todo check alignment issues if the lane width changes
2439  const int iMax = MIN2(leaders.numSublanes(), result.numSublanes());
2440  for (int i = 0; i < iMax; ++i) {
2441  const MSVehicle* veh = leaders[i];
2442  if (veh != 0) {
2443 #ifdef DEBUG_CONTEXT
2444  if (DEBUG_COND2(ego)) std::cout << " lead=" << veh->getID()
2445  << " seen=" << seen
2446  << " minGap=" << ego->getVehicleType().getMinGap()
2447  << " backPos=" << veh->getBackPositionOnLane(nextLane)
2448  << " gap=" << seen - ego->getVehicleType().getMinGap() + veh->getBackPositionOnLane(nextLane)
2449  << "\n";
2450 #endif
2451  result.addLeader(veh, seen - ego->getVehicleType().getMinGap() + veh->getBackPositionOnLane(nextLane), 0, i);
2452  }
2453  }
2454 
2455  if (nextLane->getVehicleMaxSpeed(ego) < speed) {
2456  dist = ego->getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(ego));
2457  }
2458  seen += nextLane->getLength();
2459  if (seen <= dist) {
2460  // delaying the update of arrivalTime and making it conditional to avoid possible integer overflows
2461  arrivalTime += TIME2STEPS(nextLane->getLength() / MAX2(speed, NUMERICAL_EPS));
2462  }
2463 #ifdef HAVE_INTERNAL_LANES
2464  if (!nextInternal) {
2465  view++;
2466  }
2467 #else
2468  view++;
2469 #endif
2470  }
2471 }
2472 
2473 
2474 
2475 MSVehicle*
2477  for (VehCont::const_reverse_iterator i = myPartialVehicles.rbegin(); i != myPartialVehicles.rend(); ++i) {
2478  MSVehicle* veh = *i;
2479  if (veh->isFrontOnLane(this)
2480  && veh != ego
2481  && veh->getPositionOnLane() <= ego->getPositionOnLane()) {
2482 #ifdef DEBUG_CONTEXT
2483  if (DEBUG_COND2(ego)) {
2484  std::cout << SIMTIME << " getPartialBehind lane=" << getID() << " ego=" << ego->getID() << " found=" << veh->getID() << "\n";
2485  }
2486 #endif
2487  return veh;
2488  }
2489  }
2490 #ifdef DEBUG_CONTEXT
2491  if (DEBUG_COND2(ego)) {
2492  std::cout << SIMTIME << " getPartialBehind lane=" << getID() << " ego=" << ego->getID() << " nothing found. partials=" << toString(myPartialVehicles) << "\n";
2493  }
2494 #endif
2495  return 0;
2496 }
2497 
2498 
2499 MSLane*
2501  if (myNeighs.size() == 1) {
2502  return dictionary(myNeighs[0]);
2503  }
2504  return 0;
2505 }
2506 
2507 
2508 SUMOReal
2510  MSLane* opposite = getOpposite();
2511  if (opposite == 0) {
2512  assert(false);
2513  throw ProcessError("Lane '" + getID() + "' cannot compute oppositePos as there is no opposite lane.");
2514  }
2515  // XXX transformations for curved geometries
2516  return opposite->getLength() - pos;
2517 
2518 }
2519 
2520 std::pair<MSVehicle* const, SUMOReal>
2521 MSLane::getFollower(const MSVehicle* ego, SUMOReal egoPos, SUMOReal dist) const {
2522  for (AnyVehicleIterator first = anyVehiclesUpstreamBegin(); first != anyVehiclesUpstreamEnd(); ++first) {
2523  // XXX refactor leaderInfo to use a const vehicle all the way through the call hierarchy
2524  MSVehicle* pred = (MSVehicle*)*first;
2525 #ifdef DEBUG_CONTEXT
2526  if (DEBUG_COND2(ego)) {
2527  std::cout << " getFollower lane=" << getID() << " egoPos=" << egoPos << " pred=" << pred->getID() << " predPos=" << pred->getPositionOnLane() << "\n";
2528  }
2529 #endif
2530  if (pred->getPositionOnLane() < egoPos) {
2531  return std::pair<MSVehicle* const, SUMOReal>(pred, egoPos - pred->getPositionOnLane(this) - ego->getVehicleType().getLength() - pred->getVehicleType().getMinGap());
2532  }
2533  }
2534  return getFollowerOnConsecutive(
2535  egoPos - ego->getVehicleType().getLength(),
2536  ego->getSpeed(), ego->getCarFollowModel().getMaxDecel(), dist);
2537 }
2538 
2539 std::pair<MSVehicle* const, SUMOReal>
2541 #ifdef DEBUG_OPPOSITE
2542  if (DEBUG_COND2(ego)) std::cout << SIMTIME << " getOppositeLeader lane=" << getID()
2543  << " ego=" << ego->getID()
2544  << " pos=" << ego->getPositionOnLane()
2545  << " posOnOpposite=" << getOppositePos(ego->getPositionOnLane())
2546  << " dist=" << dist
2547  << "\n";
2548 #endif
2549  if (ego->getLaneChangeModel().isOpposite()) {
2550  return getLeader(ego, getOppositePos(ego->getPositionOnLane()), ego->getBestLanesContinuation(this));
2551  } else {
2552  const SUMOReal egoLength = ego->getVehicleType().getLength();
2553  std::pair<MSVehicle* const, SUMOReal> result = getFollower(ego, getOppositePos(ego->getPositionOnLane() - egoLength), dist);
2554  result.second -= ego->getVehicleType().getMinGap();
2555  return result;
2556  }
2557 }
2558 
2559 
2560 std::pair<MSVehicle* const, SUMOReal>
2562 #ifdef DEBUG_OPPOSITE
2563  if (DEBUG_COND2(ego)) std::cout << SIMTIME << " getOppositeFollower lane=" << getID()
2564  << " ego=" << ego->getID()
2565  << " backPos=" << ego->getBackPositionOnLane()
2566  << " posOnOpposite=" << getOppositePos(ego->getBackPositionOnLane())
2567  << "\n";
2568 #endif
2569  if (ego->getLaneChangeModel().isOpposite()) {
2570  std::pair<MSVehicle* const, SUMOReal> result = getFollower(ego, getOppositePos(ego->getPositionOnLane()), -1);
2571  return result;
2572  } else {
2573  std::pair<MSVehicle* const, SUMOReal> result = getLeader(ego, getOppositePos(ego->getPositionOnLane() - ego->getVehicleType().getLength()), std::vector<MSLane*>());
2574  if (result.second > 0) {
2575  // follower can be safely ignored since it is going the other way
2576  return std::make_pair(static_cast<MSVehicle*>(0), -1);
2577  } else {
2578  return result;
2579  }
2580  }
2581 }
2582 
2583 
2584 void
2586  const std::string action = oc.getString("collision.action");
2587  if (action == "none") {
2589  } else if (action == "warn") {
2591  } else if (action == "teleport") {
2593  } else if (action == "remove") {
2595  } else {
2596  throw ProcessError("Invalid collision.action '" + action + "'.");
2597  }
2598  myCheckJunctionCollisions = oc.getBool("collision.check-junctions");
2599 }
2600 
2601 
2602 void
2603 MSLane::setPermissions(SVCPermissions permissions, long transientID) {
2604  if (transientID == CHANGE_PERMISSIONS_PERMANENT) {
2605  myPermissions = permissions;
2606  myOriginalPermissions = permissions;
2607  } else {
2608  myPermissionChanges[transientID] = permissions;
2610  }
2611 }
2612 
2613 
2614 void
2615 MSLane::resetPermissions(long transientID) {
2616  myPermissionChanges.erase(transientID);
2617  if (myPermissionChanges.empty()) {
2619  } else {
2620  // combine all permission changes
2622  for (std::map<long, SVCPermissions>::iterator it = myPermissionChanges.begin(); it != myPermissionChanges.end(); ++it) {
2623  myPermissions &= it->second;
2624  }
2625  }
2626 }
2627 
2628 /****************************************************************************/
2629 
const std::vector< IncomingLaneInfo > & getIncomingLanes() const
Definition: MSLane.h:708
SUMOReal getOppositePos(SUMOReal pos) const
return the corresponding position on the opposite lane
Definition: MSLane.cpp:2509
SUMOReal getWidth() const
Returns the lane&#39;s width.
Definition: MSLane.h:496
SUMOReal getCenterOnEdge(const MSLane *lane=0) const
Get the vehicle&#39;s lateral position on the edge of the given lane (or its current edge if lane == 0) ...
Definition: MSVehicle.cpp:3367
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
const std::map< SUMOVehicleClass, SUMOReal > * myRestrictions
The vClass speed restrictions for this lane.
Definition: MSLane.h:1090
bool overlapsWith(const AbstractPoly &poly, SUMOReal offset=0) const
Returns the information whether the given polygon overlaps with this.
void loadState(std::vector< std::string > &vehIDs, MSVehicleControl &vc)
Loads the state of this segment with the given parameters.
Definition: MSLane.cpp:2256
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:257
SVCPermissions myPermissions
The vClass permissions for this lane.
Definition: MSLane.h:1084
MSLane * getLogicalPredecessorLane() const
get the most likely precedecessor lane (sorted using by_connections_to_sorter). The result is cached ...
Definition: MSLane.cpp:1954
SUMOReal getLength() const
Returns the lane&#39;s length.
Definition: MSLane.h:480
VehCont myVehicles
The lane&#39;s vehicles. This container holds all vehicles that have their front (longitudinally) and the...
Definition: MSLane.h:1048
saves leader/follower vehicles and their distances relative to an ego vehicle
Definition: MSLeaderInfo.h:127
std::pair< MSVehicle *const, SUMOReal > getLeaderOnConsecutive(SUMOReal dist, SUMOReal seen, SUMOReal speed, const MSVehicle &veh, const std::vector< MSLane *> &bestLaneConts) const
Returns the immediate leader and the distance to him.
Definition: MSLane.cpp:1793
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:571
A free lateral position is chosen.
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:82
const MSLeaderInfo & getFirstVehicleInformation(const MSVehicle *ego, SUMOReal latOffset, bool onlyFrontOnLane, SUMOReal maxPos=std::numeric_limits< SUMOReal >::max(), bool allowCached=true) const
analogue to getLastVehicleInformation but in the upstream direction
Definition: MSLane.cpp:885
The position is given.
long long int SUMOTime
Definition: SUMOTime.h:43
MSVehicle * getFirstFullVehicle() const
returns the first vehicle for which this lane is responsible or 0
Definition: MSLane.cpp:1424
void resetPermissions(long transientID)
Definition: MSLane.cpp:2615
void descheduleDeparture(SUMOVehicle *veh)
stops trying to emit the given vehicle (and delete it)
At the leftmost side of the lane.
SUMOReal getPMxEmissions() const
Returns the sum of last step PMx emissions.
Definition: MSLane.cpp:2124
SUMOReal getMaxSpeedFactor() const
return the maximum speed factor for all vehicles that ever entered the network
PositionVector getBoundingPoly() const
get bounding polygon
Definition: MSVehicle.cpp:3527
int operator()(MSVehicle *v1, MSVehicle *v2) const
Comparing operator.
Definition: MSLane.cpp:2207
bool checkFailure(MSVehicle *aVehicle, SUMOReal &speed, SUMOReal &dist, const SUMOReal nspeed, const bool patchSpeed, const std::string errorMsg) const
Definition: MSLane.cpp:488
SUMOTime getWaitingTime() const
Returns the SUMOTime waited (speed was lesser than 0.1m/s)
Definition: MSVehicle.h:535
static void insertIDs(std::vector< std::string > &into)
Adds the ids of all stored lanes into the given vector.
Definition: MSLane.cpp:1318
MSLane * parallelLane(const MSLane *const lane, int offset) const
Returns the lane with the given offset parallel to the given lane one or 0 if it does not exist...
Definition: MSEdge.cpp:285
bool operator()(const MSVehicle *cmp, SUMOReal pos) const
compares vehicle position to the detector position
Definition: MSLane.cpp:2201
bool hasDeparted() const
Returns whether this vehicle has already departed.
void setTentativeLaneAndPosition(MSLane *lane, SUMOReal pos, SUMOReal posLat=0)
set tentative lane and position during insertion to ensure that all cfmodels work (some of them requi...
Definition: MSVehicle.cpp:3345
virtual SUMOReal insertionFollowSpeed(const MSVehicle *const veh, SUMOReal speed, SUMOReal gap2pred, SUMOReal predSpeed, SUMOReal predMaxDecel) const
Computes the vehicle&#39;s safe speed (no dawdling) This method is used during the insertion stage...
Definition: MSCFModel.cpp:213
SUMOReal getSafeFollowSpeed(const std::pair< const MSVehicle *, SUMOReal > leaderInfo, const SUMOReal seen, const MSLane *const lane, SUMOReal distToCrossing) const
compute safe speed for following the given leader
Definition: MSVehicle.cpp:1650
Stop & getNextStop()
Definition: MSVehicle.cpp:3684
int myI2
index for myPartialVehicles
Definition: MSLane.h:145
void enterLaneAtInsertion(MSLane *enteredLane, SUMOReal pos, SUMOReal speed, SUMOReal posLat, MSMoveReminder::Notification notification)
Update when the vehicle enters a new lane in the emit step.
Definition: MSVehicle.cpp:2611
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:487
The speed is given.
#define M_PI
Definition: angles.h:37
void registerTeleportYield()
register one non-collision-related teleport
static void fill(RTREE &into)
Fills the given RTree with lane instances.
Definition: MSLane.cpp:1326
The vehicle arrived at a junction.
bool isVTDAffected(SUMOTime t) const
Definition: MSVehicle.cpp:464
void recalcCache()
Recalculates the cached values.
Definition: MSEdge.cpp:136
This is an uncontrolled, minor link, has to stop.
SUMOReal departSpeed
(optional) The initial speed of the vehicle
std::vector< IncomingLaneInfo > myIncomingLanes
Definition: MSLane.h:1092
The position is given.
The car-following model abstraction.
Definition: MSCFModel.h:60
int SVCPermissions
int myI2End
end index for myPartialVehicles
Definition: MSLane.h:149
void setLength(SUMOReal val)
Sets a new length for the lane (used by TraCI only)
Definition: MSLane.cpp:1525
void addLink(MSLink *link)
Delayed initialization.
Definition: MSLane.cpp:190
int myIndex
The lane index.
Definition: MSLane.h:1035
SUMOReal getLatOffset(const MSLane *lane) const
Get the offset that that must be added to interpret myState.myPosLat for the given lane...
Definition: MSVehicle.cpp:3399
virtual bool integrateNewVehicle(SUMOTime t)
Insert buffered vehicle into the real lane.
Definition: MSLane.cpp:1362
The lateral position is chosen randomly.
const SUMOVehicleParameter & getParameter() const
Returns the vehicle&#39;s parameter (including departure definition)
SUMOReal arrivalSpeed
(optional) The final speed of the vehicle (not used yet)
SUMOReal getMaxDecel() const
Get the vehicle type&#39;s maximum deceleration [m/s^2].
Definition: MSCFModel.h:201
SUMOTime myLeaderInfoTime
time step for which myLeaderInfo was last updated
Definition: MSLane.h:1116
If a fixed number of random choices fails, a free lateral position is chosen.
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
Notification
Definition of a vehicle state.
static SUMOReal rand()
Returns a random real number in [0, 1)
Definition: RandHelper.h:62
void handleCollisionBetween(SUMOTime timestep, const std::string &stage, const MSVehicle *collider, const MSVehicle *victim, SUMOReal gap, SUMOReal latGap, std::set< const MSVehicle *, SUMOVehicle::ComparatorIdLess > &toRemove, std::set< const MSVehicle *> &toTeleport) const
take action upon collision
Definition: MSLane.cpp:1132
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:59
std::vector< const MSLane * > getOutgoingLanes() const
get the list of outgoing lanes
Definition: MSLane.cpp:2005
SUMOReal getLength() const
Get vehicle&#39;s length [m].
A RT-tree for efficient storing of SUMO&#39;s Named objects.
Definition: NamedRTree.h:72
virtual MSVehicle * removeVehicle(MSVehicle *remVehicle, MSMoveReminder::Notification notification, bool notify=true)
Definition: MSLane.cpp:1543
SUMOReal ymin() const
Returns minimum y-coordinate.
Definition: Boundary.cpp:142
MSVehicle * getFirstAnyVehicle() const
returns the first vehicle that is fully or partially on this lane
Definition: MSLane.cpp:1447
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:300
const MSEdge *const myEdge
Definition: MSLane.h:1209
This is a dead end link.
void addIncomingLane(MSLane *lane, MSLink *viaLink)
Definition: MSLane.cpp:1567
SUMOReal getSpeedLimit() const
Returns the lane&#39;s maximum allowed speed.
Definition: MSLane.h:472
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:159
T MAX2(T a, T b)
Definition: StdDefs.h:75
by_connections_to_sorter(const MSEdge *const e)
constructor
Definition: MSLane.cpp:2222
SUMOTime DELTA_T
Definition: SUMOTime.cpp:39
virtual const VehCont & getVehiclesSecure() const
Returns the vehicles container; locks it for microsimulation.
Definition: MSLane.h:380
const PositionVector & getShape() const
Returns this lane&#39;s shape.
Definition: MSLane.h:427
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:59
The speed is chosen randomly.
PositionVector getBoundingBox() const
get bounding rectangle
Definition: MSVehicle.cpp:3514
bool isLinkEnd(MSLinkCont::const_iterator &i) const
Definition: MSLane.cpp:1394
static void initCollisionOptions(const OptionsCont &oc)
Definition: MSLane.cpp:2585
void getLeadersOnConsecutive(SUMOReal dist, SUMOReal seen, SUMOReal 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:2385
virtual void addMoveReminder(MSMoveReminder *rem)
Add a move-reminder to move-reminder container.
Definition: MSLane.cpp:203
const MSRoute & getRoute() const
Returns the current route.
Definition: MSBaseVehicle.h:97
The vehicle got vaporized.
SUMOReal getMinDeceleration() const
return the minimum deceleration capability for all vehicles that ever entered the network ...
void leftByLaneChange(MSVehicle *v)
Definition: MSLane.cpp:2016
const MSEdge * getLastEdge() const
returns the destination edge
Definition: MSRoute.cpp:96
Definition of vehicle stop (position and duration)
Definition: MSVehicle.h:778
This is an uncontrolled, right-before-left link.
std::map< long, SVCPermissions > myPermissionChanges
Definition: MSLane.h:1132
bool executeMove()
Executes planned vehicle movements with regards to right-of-way.
Definition: MSVehicle.cpp:1692
const MSEdgeVector & getIncomingEdges() const
Returns the list of edges from which this edge may be reached.
Definition: MSEdge.h:332
void addNeigh(const std::string &id)
Adds a neighbor to this lane.
Definition: MSLane.cpp:196
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
ArrivalSpeedDefinition arrivalSpeedProcedure
Information how the vehicle&#39;s end speed shall be chosen.
SUMOReal ymax() const
Returns maximum y-coordinate.
Definition: Boundary.cpp:148
const std::string & getID() const
Returns the id.
Definition: Named.h:66
#define TIME2STEPS(x)
Definition: SUMOTime.h:66
const SVCPermissions SVCAll
std::pair< MSVehicle *const, SUMOReal > getOppositeLeader(const MSVehicle *ego, SUMOReal dist) const
Definition: MSLane.cpp:2540
void gotActive(MSLane *l)
Informs the control that the given lane got active.
const SUMOReal myWidth
Lane width [m].
Definition: MSLane.h:1075
static SUMOReal angleDiff(const SUMOReal angle1, const SUMOReal angle2)
Returns the difference of the second angle to the first angle in radiants.
Definition: GeomHelper.cpp:178
bool freeInsertion(MSVehicle &veh, SUMOReal speed, MSMoveReminder::Notification notification=MSMoveReminder::NOTIFICATION_DEPARTED)
Tries to insert the given vehicle on any place.
Definition: MSLane.cpp:284
VehCont myPartialVehicles
The lane&#39;s partial vehicles. This container holds all vehicles that are partially on this lane but wh...
Definition: MSLane.h:1060
The position is chosen randomly.
static bool myCheckJunctionCollisions
Definition: MSLane.h:1146
This is an uncontrolled, all-way stop link.
SUMOReal myMaxSpeed
Lane-wide speedlimit [m/s].
Definition: MSLane.h:1081
SUMOReal getSecureGap(const SUMOReal speed, const SUMOReal leaderSpeed, const SUMOReal leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum (>=0)
Definition: MSCFModel.h:276
int myI1End
end index for myVehicles
Definition: MSLane.h:147
bool hasArrived() const
Returns whether this vehicle has already arived (reached the arrivalPosition on its final edge) ...
Definition: MSVehicle.cpp:610
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:48
int myDirection
index delta
Definition: MSLane.h:153
SUMOReal xmin() const
Returns minimum x-coordinate.
Definition: Boundary.cpp:130
PositionVector myShape
The shape of the lane.
Definition: MSLane.h:1032
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
The speed is given.
bool myDownstream
iteration direction
Definition: MSLane.h:151
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:2702
bool isVaporizing() const
Returns whether vehicles on this edge shall be vaporized.
Definition: MSEdge.h:406
#define SIMTIME
Definition: SUMOTime.h:70
const MSEdge * getInternalFollower() const
Returns the lane&#39;s follower if it is an internal lane, the edge of the lane otherwise.
Definition: MSLane.cpp:1275
bool isFrontOnLane(const MSLane *lane) const
Returns the information whether the front of the vehicle is on the given lane.
Definition: MSVehicle.cpp:2258
std::pair< MSVehicle *const, SUMOReal > getLeader(const MSVehicle *veh, const SUMOReal vehPos, const std::vector< MSLane *> &bestLaneConts, SUMOReal dist=-1, bool checkTmpVehicles=false) const
Returns the immediate leader of veh and the distance to veh starting on this lane.
Definition: MSLane.cpp:1735
int getLaneIndex() const
Definition: MSVehicle.cpp:3338
std::vector< std::string > myNeighs
Definition: MSLane.h:1129
void setMaxSpeed(SUMOReal val)
Sets a new maximum speed for the lane (used by TraCI and MSCalibrator)
Definition: MSLane.cpp:1518
static CollisionAction myCollisionAction
the action to take on collisions
Definition: MSLane.h:1145
const std::string & getEdgeType() const
Returns the type of the edge.
Definition: MSEdge.h:288
std::map< std::string, MSLane *> DictType
definition of the static dictionary type
Definition: MSLane.h:1135
SUMOReal getMaximumBrakeDist() const
compute maximum braking distance on this lane
Definition: MSLane.cpp:1631
bool lastInsertion(MSVehicle &veh, SUMOReal mspeed)
Definition: MSLane.cpp:265
virtual void incorporateVehicle(MSVehicle *veh, SUMOReal pos, SUMOReal speed, SUMOReal 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:245
MSLinkCont myLinks
Definition: MSLane.h:1104
virtual void detectCollisions(SUMOTime timestep, const std::string &stage)
Check if vehicles are too close.
Definition: MSLane.cpp:979
static DictType myDict
Static dictionary to associate string-ids with objects.
Definition: MSLane.h:1138
bool isInternal() const
Definition: MSLane.cpp:1410
#define SUMOTime_MIN
Definition: SUMOTime.h:45
void addApproachingLane(MSLane *lane, bool warnMultiCon)
Definition: MSLane.cpp:1577
virtual const MSEdge * succEdge(int nSuccs) const =0
Returns the nSuccs&#39;th successor of edge the vehicle is currently at.
A road/street connecting two junctions.
Definition: MSEdge.h:80
bool insertVehicle(MSVehicle &v)
Tries to insert the given vehicle.
Definition: MSLane.cpp:399
SUMOReal getWidth() const
Get the width which vehicles of this class shall have when being drawn.
const MSCFModel & getCarFollowModel() const
Returns the vehicle&#39;s car following model definition.
Definition: MSVehicle.h:758
SUMOReal myRightSideOnEdge
the combined width of all lanes with lower index on myEdge
Definition: MSLane.h:1124
#define max(a, b)
Definition: polyfonts.c:65
DepartSpeedDefinition departSpeedProcedure
Information how the vehicle&#39;s initial speed shall be chosen.
VehCont myTmpVehicles
Container for lane-changing vehicles. After completion of lane-change- process, the containers will b...
Definition: MSLane.h:1064
SUMOReal getNettoOccupancy() const
Returns the netto (excluding minGaps) occupancy of this lane during the last step (including minGaps)...
Definition: MSLane.cpp:2056
const MSVehicle * operator*()
Definition: MSLane.cpp:112
int getCrossingIndex() const
return the index of the link to the next crossing if this is walkingArea, else -1 ...
Definition: MSLane.cpp:2030
virtual void resetPartialOccupation(MSVehicle *v)
Removes the information about a vehicle lapping into this lane.
Definition: MSLane.cpp:225
SUMOReal getNOxEmissions() const
Returns the sum of last step NOx emissions.
Definition: MSLane.cpp:2136
SUMOReal getFuelConsumption() const
Returns the sum of last step fuel consumption.
Definition: MSLane.cpp:2160
Representation of a vehicle.
Definition: SUMOVehicle.h:66
DepartPosDefinition departPosProcedure
Information how the vehicle shall choose the departure position.
virtual int addLeader(const MSVehicle *veh, bool beyond, SUMOReal latOffset=0)
This is an uncontrolled, minor link, has to brake.
SUMOReal getDepartSpeed(const MSVehicle &veh, bool &patchSpeed)
Definition: MSLane.cpp:372
Sorts vehicles by their position (descending)
Definition: MSLane.h:1152
bool isVTDControlled() const
Definition: MSVehicle.cpp:458
SUMOReal getHCEmissions() const
Returns the sum of last step HC emissions.
Definition: MSLane.cpp:2148
SUMOReal getHarmonoise_NoiseEmissions() const
Returns the sum of last step noise emissions.
Definition: MSLane.cpp:2184
virtual SUMOReal freeSpeed(const MSVehicle *const veh, SUMOReal speed, SUMOReal seen, SUMOReal maxSpeed, const bool onInsertion=false) const
Computes the vehicle&#39;s safe speed without a leader.
Definition: MSCFModel.cpp:206
SVCPermissions myOriginalPermissions
The original vClass permissions for this lane (before temporary modifications)
Definition: MSLane.h:1087
A list of positions.
void updateBestLanes(bool forceRebuild=false, const MSLane *startLane=0)
computes the best lanes to use in order to continue the route
Definition: MSVehicle.cpp:2720
void enteredByLaneChange(MSVehicle *v)
Definition: MSLane.cpp:2023
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the subpart of best lanes that describes the vehicle&#39;s current lane and their successors...
Definition: MSVehicle.cpp:3048
std::pair< MSVehicle *const, SUMOReal > getCriticalLeader(SUMOReal dist, SUMOReal seen, SUMOReal speed, const MSVehicle &veh) const
Returns the most dangerous leader and the distance to him.
Definition: MSLane.cpp:1885
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:307
const MSLane * lane
The lane to stop at.
Definition: MSVehicle.h:782
bool isEmpty() const
Definition: MSLane.cpp:1405
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
ConstMSEdgeVector::const_iterator MSRouteIterator
Definition: MSRoute.h:65
SUMOReal getWaitingSeconds() const
Returns the overall waiting time on this lane.
Definition: MSLane.cpp:2071
The vehicle arrived at its destination (is deleted)
bool hasStops() const
Returns whether the vehicle has to stop somewhere.
Definition: MSVehicle.h:829
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic, in MSLink and GNEInternalLane.
SUMOReal basePos(const MSVehicle &veh) const
departure position where the vehicle fits fully onto the lane (if possible)
Definition: MSLane.cpp:483
The maximum speed is used.
std::string toString() const
print a debugging representation
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:254
SUMOReal getElectricityConsumption() const
Returns the sum of last step electricity consumption.
Definition: MSLane.cpp:2172
SUMOReal getPositionOnLane() const
Get the vehicle&#39;s position along the lane.
Definition: MSVehicle.h:374
T MIN2(T a, T b)
Definition: StdDefs.h:69
MSVehicle * getPartialBehind(const MSVehicle *ego) const
Definition: MSLane.cpp:2476
AnyVehicleIterator anyVehiclesEnd() const
end iterator for iterating over all vehicles touching this lane in downstream direction ...
Definition: MSLane.h:391
void add(const SUMOTime t, MSVehicle *veh)
Adds a vehicle to this transfer object.
AnyVehicleIterator anyVehiclesBegin() const
begin iterator for iterating over all vehicles touching this lane in downstream direction ...
Definition: MSLane.h:386
#define POSITION_EPS
Definition: config.h:187
std::pair< MSVehicle *const, SUMOReal > getFollowerOnConsecutive(SUMOReal backOffset, SUMOReal leaderSpeed, SUMOReal leaderMaxDecel, SUMOReal dist=-1) const
return the follower with the largest missing rear gap among all predecessor lanes (within dist) ...
Definition: MSLane.cpp:1640
LinkState getIncomingLinkState() const
get the state of the link from the logical predecessor to this lane
Definition: MSLane.cpp:1994
No information given; use default.
virtual bool executeMovements(SUMOTime t, std::vector< MSLane *> &lanesWithVehiclesToIntegrate)
Executes planned vehicle movements with regards to right-of-way.
Definition: MSLane.cpp:1187
CollisionAction
Definition: MSLane.h:162
void onRemovalFromNet(const MSMoveReminder::Notification reason)
Called when the vehicle is removed from the network.
Definition: MSVehicle.cpp:601
MSLane(const std::string &id, SUMOReal maxSpeed, SUMOReal length, MSEdge *const edge, int numericalID, const PositionVector &shape, SUMOReal width, SVCPermissions permissions, int index)
Constructor.
Definition: MSLane.cpp:160
bool hasInfluencer() const
Definition: MSVehicle.h:1359
int myRightmostSublane
the index of the rightmost sublane of this lane on myEdge
Definition: MSLane.h:1126
MSLane * myLogicalPredecessorLane
Definition: MSLane.h:1093
virtual int addLeader(const MSVehicle *veh, SUMOReal gap, SUMOReal latOffset=0, int sublane=-1)
Something on a lane to be noticed about vehicle movement.
SUMOReal myLength
Lane length [m].
Definition: MSLane.h:1072
EdgeBasicFunction getPurpose() const
Returns the edge type (EdgeBasicFunction)
Definition: MSEdge.h:249
MSLane * getOpposite() const
return the opposite direction lane for lane changing or 0
Definition: MSLane.cpp:2500
AnyVehicleIterator anyVehiclesUpstreamBegin() const
begin iterator for iterating over all vehicles touching this lane in upstream direction ...
Definition: MSLane.h:396
virtual SUMOReal setPartialOccupation(MSVehicle *v)
Sets the information about a vehicle lapping into this lane.
Definition: MSLane.cpp:212
virtual void swapAfterLaneChange(SUMOTime t)
moves myTmpVehicles int myVehicles after a lane change procedure
Definition: MSLane.cpp:1532
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:55
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:254
void registerTeleportJam()
register one non-collision-related teleport
SUMOReal getVehicleMaxSpeed(const SUMOVehicle *const veh) const
Returns the lane&#39;s maximum speed, given a vehicle&#39;s speed limit adaptation.
Definition: MSLane.h:458
If a fixed number of random choices fails, a free position is chosen.
std::map< MSEdge *, std::vector< MSLane * > > myApproachingLanes
Definition: MSLane.h:1106
int addFollower(const MSVehicle *veh, const MSVehicle *ego, SUMOReal gap, SUMOReal latOffset=0, int sublane=-1)
std::vector< MSVehicle * > VehCont
Container for vehicles.
Definition: MSLane.h:91
bool detectCollisionBetween(SUMOTime timestep, const std::string &stage, const MSVehicle *collider, const MSVehicle *victim, std::set< const MSVehicle *, SUMOVehicle::ComparatorIdLess > &toRemove, std::set< const MSVehicle *> &toTeleport) const
detect whether there is a collision between the two vehicles
Definition: MSLane.cpp:1086
static MSLinkCont::const_iterator succLinkSec(const SUMOVehicle &veh, int nRouteSuccs, const MSLane &succLinkSource, const std::vector< MSLane *> &conts)
Definition: MSLane.cpp:1461
int operator()(const MSEdge *const e1, const MSEdge *const e2) const
comparing operator
Definition: MSLane.cpp:2229
Base class for objects which have an id.
Definition: Named.h:46
int myNumericalID
Unique numerical ID (set on reading by netload)
Definition: MSLane.h:1029
std::vector< MSMoveReminder *> myMoveReminders
This lane&#39;s move reminder.
Definition: MSLane.h:1142
MSLeaderDistanceInfo getFollowersOnConsecutive(const MSVehicle *ego, bool allSublanes) const
return the sublane followers with the largest missing rear gap among all predecessor lanes (within di...
Definition: MSLane.cpp:2268
SUMOReal safeInsertionSpeed(const MSVehicle *veh, const MSLeaderInfo &leaders, SUMOReal speed)
return the maximum safe speed for insertion behind leaders (a negative value indicates that safe inse...
Definition: MSLane.cpp:815
SUMOReal getBruttoOccupancy() const
Returns the brutto (including minGaps) occupancy of this lane during the last step.
Definition: MSLane.cpp:2041
SUMOReal getMissingRearGap(SUMOReal backOffset, SUMOReal leaderSpeed, SUMOReal leaderMaxDecel) const
return by how much further the leader must be inserted to avoid rear end collisions ...
Definition: MSLane.cpp:1615
const SUMOReal myLengthGeometryFactor
precomputed myShape.length / myLength
Definition: MSLane.h:1121
SUMOReal brakeGap(const SUMOReal speed) const
Returns the distance the vehicle needs to halt including driver&#39;s reaction time, assuming that during...
Definition: MSCFModel.h:263
AnyVehicleIterator & operator++()
Definition: MSLane.cpp:97
static MSVehicleTransfer * getInstance()
Returns the instance of this object.
void leaveLane(const MSMoveReminder::Notification reason)
Update of members if vehicle leaves a new lane in the lane change step or at arrival.
Definition: MSVehicle.cpp:2653
void forceVehicleInsertion(MSVehicle *veh, SUMOReal pos, MSMoveReminder::Notification notification, SUMOReal posLat=0)
Inserts the given vehicle at the given position.
Definition: MSLane.cpp:806
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:206
SUMOReal getMeanSpeed() const
Returns the mean speed on this lane.
Definition: MSLane.cpp:2084
MSVehicle * getLastFullVehicle() const
returns the last vehicle for which this lane is responsible or 0
Definition: MSLane.cpp:1415
void sortPartialVehicles()
sorts myPartialVehicles
Definition: MSLane.cpp:1387
void markDelayed() const
Definition: MSEdge.h:646
void setPermissions(SVCPermissions permissions, long transientID)
Sets the permissions to the given value. If a transientID is given, the permissions are recored as te...
Definition: MSLane.cpp:2603
virtual std::string toString() const
print a debugging representation
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition: MSLane.cpp:1286
static SUMOTime gTimeToGridlockHighways
Definition: MSGlobals.h:70
SUMOReal getLateralPositionOnLane() const
Get the vehicle&#39;s lateral position on the lane.
Definition: MSVehicle.h:406
Boundary & grow(SUMOReal by)
extends the boundary by the given amount
Definition: Boundary.cpp:232
std::string myID
The name of the object.
Definition: Named.h:136
The vehicle has departed (was inserted into the network)
Influencer & getInfluencer()
Returns the velocity/lane influencer.
Definition: MSVehicle.cpp:3690
void scheduleVehicleRemoval(SUMOVehicle *veh)
Removes a vehicle after it has ended.
Structure representing possible vehicle parameter.
int myI1
index for myVehicles
Definition: MSLane.h:143
const MSVehicleType & getVehicleType() const
Returns the vehicle&#39;s type definition.
SUMOReal getCO2Emissions() const
Returns the sum of last step CO2 emissions.
Definition: MSLane.cpp:2100
#define DEBUG_COND
Definition: MSLane.cpp:81
SUMOReal xmax() const
Returns maximum x-coordinate.
Definition: Boundary.cpp:136
SUMOReal myBruttoVehicleLengthSum
The current length of all vehicles on this lane, including their minGaps.
Definition: MSLane.h:1097
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition: MSNet.h:360
static void clear()
Clears the dictionary.
Definition: MSLane.cpp:1309
int operator()(const std::pair< const MSVehicle *, SUMOReal > &p1, const std::pair< const MSVehicle *, SUMOReal > &p2) const
Definition: MSLane.cpp:1609
const MSLeaderInfo & getLastVehicleInformation(const MSVehicle *ego, SUMOReal latOffset, SUMOReal minPos=0, bool allowCached=true) const
Returns the last vehicles on the lane.
Definition: MSLane.cpp:834
bool nextIsMyVehicles() const
Definition: MSLane.cpp:126
MSEdge *const myEdge
The lane&#39;s edge, for routing only.
Definition: MSLane.h:1078
At the rightmost side of the lane.
At the center of the lane.
const MSLane * myLane
the lane that is being iterated
Definition: MSLane.h:141
SUMOReal getCOEmissions() const
Returns the sum of last step CO emissions.
Definition: MSLane.cpp:2112
A storage for options typed value containers)
Definition: OptionsCont.h:99
static SUMOReal gLateralResolution
Definition: MSGlobals.h:89
MSVehicle * getLastAnyVehicle() const
returns the last vehicle that is fully or partially on this lane
Definition: MSLane.cpp:1433
bool isApproachedFrom(MSEdge *const edge)
Definition: MSLane.cpp:1591
virtual SUMOReal stopSpeed(const MSVehicle *const veh, const SUMOReal speed, SUMOReal gap) const =0
Computes the vehicle&#39;s safe speed for approaching a non-moving obstacle (no dawdling) ...
const SUMOReal SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition: StdDefs.h:57
const MSEdgeVector & getSuccessors() const
Returns the following edges.
Definition: MSEdge.h:353
static SUMOReal sum(SUMOReal val)
Computes the resulting noise.
#define LANE_RTREE_QUAL
static SUMOTime gTimeToGridlock
Definition: MSGlobals.h:67
SUMOReal departPos
(optional) The position the vehicle shall depart from
AnyVehicleIterator anyVehiclesUpstreamEnd() const
end iterator for iterating over all vehicles touching this lane in upstream direction ...
Definition: MSLane.h:401
const MSEdge * succEdge(int nSuccs) const
Returns the nSuccs&#39;th successor of edge the vehicle is currently at.
int operator()(MSVehicle *v1, MSVehicle *v2) const
Comparing operator.
Definition: MSLane.cpp:2212
void saveState(OutputDevice &out)
Saves the state of this lane into the given stream.
Definition: MSLane.cpp:2245
SUMOReal getMinGap() const
Get the free space in front of vehicles of this class.
MSLeaderInfo myLeaderInfo
leaders on all sublanes as seen by approaching vehicles (cached)
Definition: MSLane.h:1109
SUMOReal endPos
The stopping position end.
Definition: MSVehicle.h:792
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:71
bool closeTag()
Closes the most recently opened tag.
#define SUMOReal
Definition: config.h:213
#define DEBUG_COND2(obj)
Definition: MSLane.cpp:82
void registerCollision()
registers one collision-related teleport
MSEdgeControl & getEdgeControl()
Returns the edge control.
Definition: MSNet.h:350
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
#define NUMERICAL_EPS
Definition: config.h:160
MSLeaderInfo myFollowerInfo
followers on all sublanes as seen by vehicles on consecutive lanes (cached)
Definition: MSLane.h:1111
int numSublanes() const
Definition: MSLeaderInfo.h:86
virtual ~MSLane()
Destructor.
Definition: MSLane.cpp:182
MSLane * getShadowLane() const
Returns the lane the vehicles shadow is on during continuous/sublane lane change. ...
SUMOReal myNettoVehicleLengthSum
The current length of all vehicles on this lane, excluding their minGaps.
Definition: MSLane.h:1100
MSRouteIterator begin() const
Returns the begin of the list of edges to pass.
Definition: MSRoute.cpp:78
bool isInsertionSuccess(MSVehicle *vehicle, SUMOReal speed, SUMOReal pos, SUMOReal posLat, bool recheckNextLanes, MSMoveReminder::Notification notification)
Tries to insert the given vehicle with the given state (speed and pos)
Definition: MSLane.cpp:506
int numFreeSublanes() const
Definition: MSLeaderInfo.h:90
bool isStopped() const
Returns whether the vehicle is at a stop.
Definition: MSVehicle.cpp:1003
No information given; use default.
A free position is chosen.
The class responsible for building and deletion of vehicles.
std::vector< MSEdge * > MSEdgeVector
Definition: MSEdge.h:77
MSLeaderInfo myLeaderInfoTmp
Definition: MSLane.h:1113
Insert behind the last vehicle as close as possible to still allow the specified departSpeed. Fallback to DEPART_POS_BASE if there is no vehicle on the departLane yet.
const MSLinkCont & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.cpp:1512
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
Definition: MSVehicle.cpp:2714
VehCont myVehBuffer
Buffer for vehicles that moved from their previous lane onto this one. Integrated after all vehicles ...
Definition: MSLane.h:1068
bool isParking() const
Returns whether the vehicle is parking.
Definition: MSVehicle.cpp:1009
static const long CHANGE_PERMISSIONS_PERMANENT
Definition: MSLane.h:977
SUMOReal getImpatience() const
Returns this vehicles impatience.
The edge is an internal edge.
Definition: MSEdge.h:97
SUMOTime myFollowerInfoTime
time step for which myFollowerInfo was last updated
Definition: MSLane.h:1118
virtual void releaseVehicles() const
Allows to use the container for microsimulation again.
Definition: MSLane.h:407
static SUMOTime gLaneChangeDuration
Definition: MSGlobals.h:86
SUMOReal getRightSideOnEdge() const
Definition: MSLane.h:897
const std::string & getID() const
Returns the name of the vehicle.
void registerTeleportWrongLane()
register one non-collision-related teleport
SUMOReal departPosLat
(optional) The lateral position the vehicle shall depart from
Representation of a lane in the micro simulation.
Definition: MSLane.h:79
SUMOReal getBackPositionOnLane(const MSLane *lane) const
Get the vehicle&#39;s position relative to the given lane.
Definition: MSVehicle.cpp:2198
Back-at-zero position.
SUMOReal getSpeed() const
Returns the vehicle&#39;s current speed.
Definition: MSVehicle.h:441
std::pair< MSVehicle *const, SUMOReal > getFollower(const MSVehicle *ego, SUMOReal egoPos, SUMOReal dist) const
Find follower vehicle for the given ego vehicle (which may be on the opposite direction lane) ...
Definition: MSLane.cpp:2521
virtual const std::string & getID() const =0
Get the vehicle&#39;s ID.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
std::pair< MSVehicle *const, SUMOReal > getOppositeFollower(const MSVehicle *ego) const
Definition: MSLane.cpp:2561
SUMOVehicleClass getVehicleClass() const
Get this vehicle type&#39;s vehicle class.
SUMOReal getLengthWithGap() const
Get vehicle&#39;s length including the minimum gap [m].
virtual bool appropriate(const MSVehicle *veh)
Definition: MSLane.cpp:1344
The vehicle is being teleported.
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:937
MSLane * getParallelLane(int offset) const
Returns the lane with the given offset parallel to this one or 0 if it does not exist.
Definition: MSLane.cpp:1561
const std::map< SUMOVehicleClass, SUMOReal > * getRestrictions(const std::string &id) const
Returns the restrictions for an edge type If no restrictions are present, 0 is returned.
Definition: MSNet.cpp:296
virtual const MSVehicleType & getVehicleType() const =0
Returns the vehicle&#39;s type.
virtual SUMOReal insertionStopSpeed(const MSVehicle *const veh, SUMOReal speed, SUMOReal gap) const
Computes the vehicle&#39;s safe speed for approaching an obstacle at insertion without constraints due to...
Definition: MSCFModel.cpp:224
DepartPosLatDefinition departPosLatProcedure
Information how the vehicle shall choose the lateral departure position.