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