SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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-sim.org/
17 // Copyright (C) 2001-2014 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 
39 #include <utils/common/StdDefs.h>
40 #include "MSVehicle.h"
41 #include "MSPModel.h"
43 #include "MSNet.h"
44 #include "MSVehicleType.h"
45 #include "MSEdge.h"
46 #include "MSEdgeControl.h"
47 #include "MSJunction.h"
48 #include "MSLogicJunction.h"
49 #include "MSLink.h"
50 #include "MSLane.h"
51 #include "MSVehicleTransfer.h"
52 #include "MSGlobals.h"
53 #include "MSVehicleControl.h"
54 #include "MSInsertionControl.h"
55 #include "MSVehicleControl.h"
56 #include <cmath>
57 #include <bitset>
58 #include <iostream>
59 #include <cassert>
60 #include <functional>
61 #include <algorithm>
62 #include <iterator>
63 #include <exception>
64 #include <climits>
65 #include <set>
67 #include <utils/common/ToString.h>
70 #include <utils/geom/Line.h>
71 #include <utils/geom/GeomHelper.h>
72 
73 #ifdef CHECK_MEMORY_LEAKS
74 #include <foreign/nvwa/debug_new.h>
75 #endif // CHECK_MEMORY_LEAKS
76 
77 
78 // ===========================================================================
79 // static member definitions
80 // ===========================================================================
82 
83 
84 // ===========================================================================
85 // member method definitions
86 // ===========================================================================
87 MSLane::MSLane(const std::string& id, SUMOReal maxSpeed, SUMOReal length, MSEdge* const edge,
88  unsigned int numericalID, const PositionVector& shape, SUMOReal width,
89  SVCPermissions permissions) :
90  Named(id),
91  myShape(shape), myNumericalID(numericalID),
92  myVehicles(), myLength(length), myWidth(width), myEdge(edge), myMaxSpeed(maxSpeed),
93  myPermissions(permissions),
94  myLogicalPredecessorLane(0),
95  myBruttoVehicleLengthSum(0), myNettoVehicleLengthSum(0), myInlappingVehicleEnd(10000), myInlappingVehicle(0),
96  myLengthGeometryFactor(myShape.length() / myLength) {}
97 
98 
100  for (MSLinkCont::iterator i = myLinks.begin(); i != myLinks.end(); ++i) {
101  delete *i;
102  }
103 }
104 
105 
106 void
108  myLinks.push_back(link);
109 }
110 
111 
112 // ------ interaction with MSMoveReminder ------
113 void
115  myMoveReminders.push_back(rem);
116  for (VehCont::iterator veh = myVehicles.begin(); veh != myVehicles.end(); ++veh) {
117  (*veh)->addReminder(rem);
118  }
119 }
120 
121 
122 
123 // ------ Vehicle emission ------
124 void
125 MSLane::incorporateVehicle(MSVehicle* veh, SUMOReal pos, SUMOReal speed, const MSLane::VehCont::iterator& at, MSMoveReminder::Notification notification) {
126  assert(pos <= myLength);
127  bool wasInactive = myVehicles.size() == 0;
128  veh->enterLaneAtInsertion(this, pos, speed, notification);
129  if (at == myVehicles.end()) {
130  // vehicle will be the first on the lane
131  myVehicles.push_back(veh);
132  } else {
133  myVehicles.insert(at, veh);
134  }
137  if (wasInactive) {
139  }
140 }
141 
142 
143 bool
145  SUMOReal xIn = maxPos;
146  SUMOReal vIn = mspeed;
147  SUMOReal leaderDecel;
148  if (myVehicles.size() != 0) {
149  MSVehicle* leader = myVehicles.front();
150  xIn = leader->getPositionOnLane() - leader->getVehicleType().getLength() - veh.getVehicleType().getMinGap();
151  vIn = leader->getSpeed();
152  leaderDecel = leader->getCarFollowModel().getMaxDecel();
153  } else {
154  SUMOReal brakeGap = veh.getCarFollowModel().brakeGap(mspeed);
155  std::pair<MSVehicle* const, SUMOReal> leader = getLeaderOnConsecutive(brakeGap, 0, mspeed, veh, veh.getBestLanesContinuation(this));
156  if (leader.first != 0) {
157  xIn = getLength() + leader.second;
158  vIn = leader.first->getSpeed();
159  leaderDecel = leader.first->getCarFollowModel().getMaxDecel();
160  } else {
161  incorporateVehicle(&veh, maxPos, mspeed, myVehicles.end());
162  return true;
163  }
164  }
165  const SUMOReal vHlp = 0.5 * (vIn + mspeed);
166  SUMOReal x2 = xIn;// have seen leader length already - skCar::lCar;
167  SUMOReal x1 = x2 - 100.0;
168  SUMOReal x = 0;
169  for (int i = 0; i <= 10; i++) {
170  x = 0.5 * (x1 + x2);
171  SUMOReal vSafe = veh.getCarFollowModel().followSpeed(&veh, vHlp, xIn - x, vIn, leaderDecel);
172  if (vSafe < vHlp) {
173  x2 = x;
174  } else {
175  x1 = x;
176  }
177  }
178  if (x < minPos) {
179  return false;
180  } else if (x > maxPos) {
181  x = maxPos;
182  }
183  incorporateVehicle(&veh, x, vHlp, myVehicles.begin());
184  return true;
185 }
186 
187 
188 bool
190  SUMOReal xIn = maxPos;
191  SUMOReal vIn = mspeed;
192  if (myVehicles.size() != 0) {
193  MSVehicle* leader = myVehicles.front();
194  xIn = leader->getPositionOnLane() - leader->getVehicleType().getLength() - veh.getVehicleType().getMinGap();
195  vIn = leader->getSpeed();
196  } else {
197  SUMOReal brakeGap = veh.getCarFollowModel().brakeGap(mspeed);
198  std::pair<MSVehicle* const, SUMOReal> leader = getLeaderOnConsecutive(brakeGap, 0, mspeed, veh, veh.getBestLanesContinuation(this));
199  if (leader.first != 0) {
200  xIn = getLength() + leader.second;
201  vIn = leader.first->getSpeed();
202  } else {
203  incorporateVehicle(&veh, maxPos, mspeed, myVehicles.end());
204  return true;
205  }
206  }
207  const SUMOReal vHlp = 0.5 * (mspeed + vIn);
208  xIn = xIn - vHlp * veh.getCarFollowModel().getHeadwayTime() - veh.getVehicleType().getMinGap();
209  if (xIn < minPos) {
210  return false;
211  } else if (xIn > maxPos) {
212  xIn = maxPos;
213  }
214  incorporateVehicle(&veh, xIn, vHlp, myVehicles.begin());
215  return true;
216 }
217 
218 
219 bool
221  if (myVehicles.size() == 0) {
222  return isInsertionSuccess(&veh, mspeed, myLength / 2, true);
223  }
224  // go through the lane, look for free positions (starting after the last vehicle)
225  MSLane::VehCont::iterator predIt = myVehicles.begin();
226  SUMOReal maxSpeed = 0;
227  SUMOReal maxPos = 0;
228  MSLane::VehCont::iterator maxIt = myVehicles.begin();
229  while (predIt != myVehicles.end()) {
230  // get leader (may be zero) and follower
231  const MSVehicle* leader = predIt != myVehicles.end() - 1 ? *(predIt + 1) : getPartialOccupator();
232  const MSVehicle* follower = *predIt;
233  SUMOReal leaderRearPos = getLength();
234  SUMOReal leaderSpeed = mspeed;
235  if (leader != 0) {
236  leaderRearPos = leader->getPositionOnLane() - leader->getVehicleType().getLength();
237  if (leader == getPartialOccupator()) {
238  leaderRearPos = getPartialOccupatorEnd();
239  }
240  leaderSpeed = leader->getSpeed();
241  }
242  const SUMOReal nettoGap = leaderRearPos - follower->getPositionOnLane() - veh.getVehicleType().getLengthWithGap();
243  if (nettoGap > 0) {
244  const SUMOReal tau = veh.getCarFollowModel().getHeadwayTime();
245  const SUMOReal tauDecel = tau * veh.getCarFollowModel().getMaxDecel();
246  const SUMOReal fSpeed = follower->getSpeed();
247  const SUMOReal lhs = nettoGap / tau + tauDecel - fSpeed - fSpeed * fSpeed / (2 * tauDecel) + leaderSpeed * leaderSpeed / (2 * tauDecel);
248  if (lhs >= sqrt(tauDecel * tauDecel + leaderSpeed * leaderSpeed)) {
249  const SUMOReal frontGap = (lhs * lhs - tauDecel * tauDecel - leaderSpeed * leaderSpeed) / (2 * veh.getCarFollowModel().getMaxDecel());
250  const SUMOReal currentMaxSpeed = lhs - tauDecel;
251  if (MIN2(currentMaxSpeed, mspeed) > maxSpeed) {
252  maxSpeed = currentMaxSpeed;
253  maxPos = MIN2(leaderRearPos + frontGap, myLength);
254  maxIt = predIt + 1;
255  }
256  }
257  }
258  ++predIt;
259  }
260  if (maxSpeed > 0) {
261  incorporateVehicle(&veh, maxPos, maxSpeed, maxIt);
262  return true;
263  }
264  return false;
265 }
266 
267 
268 bool
270  MSMoveReminder::Notification notification) {
271  bool adaptableSpeed = true;
272  if (myVehicles.size() == 0) {
273  if (isInsertionSuccess(&veh, mspeed, 0, adaptableSpeed, notification)) {
274  return true;
275  }
276  } else {
277  // check whether the vehicle can be put behind the last one if there is such
278  MSVehicle* leader = myVehicles.back();
279  SUMOReal leaderPos = leader->getPositionOnLane() - leader->getVehicleType().getLength();
280  SUMOReal speed = mspeed;
281  if (adaptableSpeed) {
282  speed = leader->getSpeed();
283  }
284  SUMOReal frontGapNeeded = veh.getCarFollowModel().getSecureGap(speed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()) + veh.getVehicleType().getMinGap();
285  if (leaderPos - frontGapNeeded >= 0) {
286  SUMOReal tspeed = MIN2(veh.getCarFollowModel().followSpeed(&veh, mspeed, frontGapNeeded, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()), mspeed);
287  // check whether we can insert our vehicle behind the last vehicle on the lane
288  if (isInsertionSuccess(&veh, tspeed, 0, adaptableSpeed, notification)) {
289  return true;
290  }
291  }
292  }
293  // go through the lane, look for free positions (starting after the last vehicle)
294  MSLane::VehCont::iterator predIt = myVehicles.begin();
295  while (predIt != myVehicles.end()) {
296  // get leader (may be zero) and follower
297  const MSVehicle* leader = predIt != myVehicles.end() - 1 ? *(predIt + 1) : getPartialOccupator();
298  const MSVehicle* follower = *predIt;
299 
300  // patch speed if allowed
301  SUMOReal speed = mspeed;
302  if (adaptableSpeed && leader != 0) {
303  speed = MIN2(leader->getSpeed(), mspeed);
304  }
305 
306  // compute the space needed to not collide with leader
307  SUMOReal frontMax = getLength();
308  if (leader != 0) {
309  SUMOReal leaderRearPos = leader->getPositionOnLane() - leader->getVehicleType().getLength();
310  if (leader == getPartialOccupator()) {
311  leaderRearPos = getPartialOccupatorEnd();
312  }
313  SUMOReal frontGapNeeded = veh.getCarFollowModel().getSecureGap(speed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()) + veh.getVehicleType().getMinGap();
314  frontMax = leaderRearPos - frontGapNeeded;
315  }
316  // compute the space needed to not let the follower collide
317  const SUMOReal followPos = follower->getPositionOnLane() + follower->getVehicleType().getMinGap();
318  const SUMOReal backGapNeeded = follower->getCarFollowModel().getSecureGap(follower->getSpeed(), veh.getSpeed(), veh.getCarFollowModel().getMaxDecel());
319  const SUMOReal backMin = followPos + backGapNeeded + veh.getVehicleType().getLength();
320 
321  // check whether there is enough room (given some extra space for rounding errors)
322  if (frontMax > 0 && backMin + POSITION_EPS < frontMax) {
323  // try to insert vehicle (should be always ok)
324  if (isInsertionSuccess(&veh, speed, backMin + POSITION_EPS, adaptableSpeed, notification)) {
325  return true;
326  }
327  }
328  ++predIt;
329  }
330  // first check at lane's begin
331  return false;
332 }
333 
334 
335 bool
337  SUMOReal pos = 0;
338  SUMOReal speed = 0;
339  bool patchSpeed = true; // whether the speed shall be adapted to infrastructure/traffic in front
340 
341  // determine the speed
342  const SUMOVehicleParameter& pars = veh.getParameter();
343  switch (pars.departSpeedProcedure) {
344  case DEPART_SPEED_GIVEN:
345  speed = pars.departSpeed;
346  patchSpeed = false;
347  break;
348  case DEPART_SPEED_RANDOM:
349  speed = RandHelper::rand(MIN2(veh.getMaxSpeed(), getVehicleMaxSpeed(&veh)));
350  patchSpeed = true; // @todo check
351  break;
352  case DEPART_SPEED_MAX:
353  speed = MIN2(veh.getMaxSpeed(), getVehicleMaxSpeed(&veh));
354  patchSpeed = true; // @todo check
355  break;
357  default:
358  // speed = 0 was set before
359  patchSpeed = false; // @todo check
360  break;
361  }
362 
363  // determine the position
364  switch (pars.departPosProcedure) {
365  case DEPART_POS_GIVEN:
366  pos = pars.departPos;
367  if (pos < 0.) {
368  pos += myLength;
369  }
370  break;
371  case DEPART_POS_RANDOM:
372  pos = RandHelper::rand(getLength());
373  break;
374  case DEPART_POS_RANDOM_FREE: {
375  for (unsigned int i = 0; i < 10; i++) {
376  // we will try some random positions ...
377  pos = RandHelper::rand(getLength());
378  if (isInsertionSuccess(&veh, speed, pos, patchSpeed)) {
379  return true;
380  }
381  }
382  // ... and if that doesn't work, we put the vehicle to the free position
383  return freeInsertion(veh, speed);
384  }
385  break;
386  case DEPART_POS_FREE:
387  return freeInsertion(veh, speed);
389  return pWagSimpleInsertion(veh, speed, getLength(), 0.0);
391  return pWagGenericInsertion(veh, speed, getLength(), 0.0);
393  return maxSpeedGapInsertion(veh, speed);
394  case DEPART_POS_BASE:
395  case DEPART_POS_DEFAULT:
396  default:
397  pos = MIN2(static_cast<SUMOReal>(veh.getVehicleType().getLength() + POSITION_EPS), myLength);
398  break;
399  }
400  // try to insert
401  return isInsertionSuccess(&veh, speed, pos, patchSpeed);
402 }
403 
404 
405 bool
406 MSLane::checkFailure(MSVehicle* aVehicle, SUMOReal& speed, SUMOReal& dist, const SUMOReal nspeed, const bool patchSpeed, const std::string errorMsg) const {
407  if (nspeed < speed) {
408  if (patchSpeed) {
409  speed = MIN2(nspeed, speed);
410  dist = aVehicle->getCarFollowModel().brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
411  } else {
412  if (errorMsg != "") {
413  WRITE_ERROR("Vehicle '" + aVehicle->getID() + "' will not be able to depart using the given velocity (" + errorMsg + ")!");
415  }
416  return true;
417  }
418  }
419  return false;
420 }
421 
422 
423 bool
425  SUMOReal speed, SUMOReal pos, bool patchSpeed,
426  MSMoveReminder::Notification notification) {
427  if (pos < 0 || pos > myLength) {
428  // we may not start there
429  WRITE_WARNING("Invalid departPos " + toString(pos) + " given for vehicle '" +
430  aVehicle->getID() + "'. Inserting at lane end instead.");
431  pos = myLength;
432  }
433  aVehicle->updateBestLanes(true, this);
434  const MSCFModel& cfModel = aVehicle->getCarFollowModel();
435  const std::vector<MSLane*>& bestLaneConts = aVehicle->getBestLanesContinuation(this);
436  std::vector<MSLane*>::const_iterator ri = bestLaneConts.begin();
437  SUMOReal seen = getLength() - pos;
438  SUMOReal dist = cfModel.brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
439  const MSRoute& r = aVehicle->getRoute();
440  MSRouteIterator ce = r.begin();
441  unsigned int nRouteSuccs = 1;
442  MSLane* currentLane = this;
443  MSLane* nextLane = this;
444  SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / MAX2(speed, NUMERICAL_EPS));
445  while (seen < dist && ri != bestLaneConts.end()) {
446  // get the next link used...
447  MSLinkCont::const_iterator link = succLinkSec(*aVehicle, nRouteSuccs, *currentLane, bestLaneConts);
448  if (currentLane->isLinkEnd(link)) {
449  if (&currentLane->getEdge() == r.getLastEdge()) {
450  // reached the end of the route
452  if (checkFailure(aVehicle, speed, dist, cfModel.freeSpeed(aVehicle, speed, seen, aVehicle->getParameter().arrivalSpeed),
453  patchSpeed, "arrival speed too low")) {
454  // we may not drive with the given velocity - we cannot match the specified arrival speed
455  return false;
456  }
457  }
458  } else {
459  // lane does not continue
460  if (checkFailure(aVehicle, speed, dist, cfModel.stopSpeed(aVehicle, speed, seen),
461  patchSpeed, "junction too close")) {
462  // we may not drive with the given velocity - we cannot stop at the junction
463  return false;
464  }
465  }
466  break;
467  }
468  if (!(*link)->opened(arrivalTime, speed, speed, aVehicle->getVehicleType().getLength(), aVehicle->getImpatience(), cfModel.getMaxDecel(), 0)
469  || !(*link)->havePriority()) {
470  // have to stop at junction
471  std::string errorMsg = "";
472  const LinkState state = (*link)->getState();
473  if (state == LINKSTATE_MINOR
474  || state == LINKSTATE_EQUAL
475  || state == LINKSTATE_STOP
476  || state == LINKSTATE_ALLWAY_STOP) {
477  // no sense in trying later
478  errorMsg = "unpriorised junction too close";
479  }
480  if (checkFailure(aVehicle, speed, dist, cfModel.stopSpeed(aVehicle, speed, seen),
481  patchSpeed, errorMsg)) {
482  // we may not drive with the given velocity - we cannot stop at the junction in time
483  return false;
484  }
485  break;
486  }
487  // get the next used lane (including internal)
488  nextLane = (*link)->getViaLaneOrLane();
489  // check how next lane effects the journey
490  if (nextLane != 0) {
491  arrivalTime += TIME2STEPS(nextLane->getLength() / MAX2(speed, NUMERICAL_EPS));
492  SUMOReal gap = 0;
493  MSVehicle* leader = currentLane->getPartialOccupator();
494  if (leader != 0) {
495  gap = seen + currentLane->getPartialOccupatorEnd() - currentLane->getLength() - aVehicle->getVehicleType().getMinGap();
496  } else {
497  // check leader on next lane
498  leader = nextLane->getLastVehicle();
499  if (leader != 0) {
500  gap = seen + leader->getPositionOnLane() - leader->getVehicleType().getLength() - aVehicle->getVehicleType().getMinGap();
501  }
502  }
503  if (leader != 0) {
504  if (gap < 0) {
505  return false;
506  }
507  const SUMOReal nspeed = cfModel.followSpeed(aVehicle, speed, gap, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
508  if (checkFailure(aVehicle, speed, dist, nspeed, patchSpeed, "")) {
509  // we may not drive with the given velocity - we crash into the leader
510  return false;
511  }
512  }
513  // check next lane's maximum velocity
514  const SUMOReal nspeed = cfModel.freeSpeed(aVehicle, speed, seen, nextLane->getVehicleMaxSpeed(aVehicle));
515  if (nspeed < speed) {
516  if (patchSpeed) {
517  speed = nspeed;
518  dist = cfModel.brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
519  } else {
520  // we may not drive with the given velocity - we would be too fast on the next lane
521  WRITE_ERROR("Vehicle '" + aVehicle->getID() + "' will not be able to depart using the given velocity (slow lane ahead)!");
523  return false;
524  }
525  }
526  // check traffic on next junction
527  // we cannot use (*link)->opened because a vehicle without priority
528  // may already be comitted to blocking the link and unable to stop
529  const SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / MAX2(speed, NUMERICAL_EPS));
530  const SUMOTime leaveTime = arrivalTime + TIME2STEPS((*link)->getLength() * speed);
531  if ((*link)->hasApproachingFoe(arrivalTime, leaveTime, speed, cfModel.getMaxDecel())) {
532  if (checkFailure(aVehicle, speed, dist, cfModel.followSpeed(aVehicle, speed, seen, 0, 0),
533  patchSpeed, "")) {
534  // we may not drive with the given velocity - we crash at the junction
535  return false;
536  }
537  }
538  seen += nextLane->getLength();
539  currentLane = nextLane;
540 #ifdef HAVE_INTERNAL_LANES
541  if ((*link)->getViaLane() == 0) {
542 #else
543  if (true) {
544 #endif
545  nRouteSuccs++;
546  ++ce;
547  ++ri;
548  }
549  }
550  }
551 
552  // get the pointer to the vehicle next in front of the given position
553  MSLane::VehCont::iterator predIt = find_if(myVehicles.begin(), myVehicles.end(), bind2nd(VehPosition(), pos));
554  if (predIt != myVehicles.end()) {
555  // ok, there is one (a leader)
556  MSVehicle* leader = *predIt;
557  SUMOReal frontGapNeeded = cfModel.getSecureGap(speed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
558  SUMOReal gap = MSVehicle::gap(leader->getPositionOnLane(), leader->getVehicleType().getLength(), pos + aVehicle->getVehicleType().getMinGap());
559  if (gap < frontGapNeeded) {
560  // too close to the leader on this lane
561  return false;
562  }
563  }
564 
565  // check back vehicle
566  if (predIt != myVehicles.begin()) {
567  // there is direct follower on this lane
568  MSVehicle* follower = *(predIt - 1);
569  SUMOReal backGapNeeded = follower->getCarFollowModel().getSecureGap(follower->getSpeed(), speed, cfModel.getMaxDecel());
570  SUMOReal gap = MSVehicle::gap(pos, aVehicle->getVehicleType().getLength(), follower->getPositionOnLane() + follower->getVehicleType().getMinGap());
571  if (gap < backGapNeeded) {
572  // too close to the follower on this lane
573  return false;
574  }
575  } else {
576  // check approaching vehicles to prevent rear-end collisions
577  // to compute an uper bound on the look-back distance we need
578  // the chosenSpeedFactor, minGap and maxDeceleration of approaching vehicles
579  // since we do not know these we use the values from the vehicle to be inserted
580  // and add a safety factor
581  const SUMOReal dist = 2 * (aVehicle->getCarFollowModel().brakeGap(myMaxSpeed) + aVehicle->getVehicleType().getMinGap());
582  const SUMOReal backOffset = pos - aVehicle->getVehicleType().getLength();
583  const SUMOReal missingRearGap = getMissingRearGap(dist, backOffset, speed, aVehicle->getCarFollowModel().getMaxDecel());
584  if (missingRearGap > 0) {
585  // too close to a follower
586  const SUMOReal neededStartPos = pos + missingRearGap;
587  if (myVehicles.size() == 0 && notification == MSMoveReminder::NOTIFICATION_TELEPORT && neededStartPos <= myLength) {
588  // shift starting positiong as needed entering from teleport
589  pos = neededStartPos;
590  } else {
591  return false;
592  }
593  }
594  }
595  // may got negative while adaptation
596  if (speed < 0) {
597  return false;
598  }
599  // enter
600  incorporateVehicle(aVehicle, pos, speed, predIt, notification);
601  return true;
602 }
603 
604 
605 void
607  veh->updateBestLanes(true, this);
608  incorporateVehicle(veh, pos, veh->getSpeed(), find_if(myVehicles.begin(), myVehicles.end(), bind2nd(VehPosition(), pos)));
609 }
610 
611 
612 // ------ Handling vehicles lapping into lanes ------
613 SUMOReal
615  myInlappingVehicle = v;
616  if (leftVehicleLength > myLength) {
618  } else {
619  myInlappingVehicleEnd = myLength - leftVehicleLength;
620  }
621  return myLength;
622 }
623 
624 
625 void
627  if (v == myInlappingVehicle) {
628  myInlappingVehicleEnd = 10000;
629  }
630  myInlappingVehicle = 0;
631 }
632 
633 
634 std::pair<MSVehicle*, SUMOReal>
636  if (myVehicles.size() != 0) {
637  // the last vehicle is the one in scheduled by this lane
638  MSVehicle* last = *myVehicles.begin();
639  const SUMOReal pos = last->getPositionOnLane() - last->getVehicleType().getLength();
640  return std::make_pair(last, pos);
641  }
642  if (myInlappingVehicle != 0) {
643  // the last one is a vehicle extending into this lane
644  return std::make_pair(myInlappingVehicle, myInlappingVehicleEnd);
645  }
646  return std::make_pair<MSVehicle*, SUMOReal>(0, 0);
647 }
648 
649 
650 // ------ ------
651 void
653  assert(myVehicles.size() != 0);
654  SUMOReal cumulatedVehLength = 0.;
655  const MSVehicle* pred = getPartialOccupator();
656  for (VehCont::reverse_iterator veh = myVehicles.rbegin(); veh != myVehicles.rend(); ++veh) {
657  if ((*veh)->getLane() == this) {
658  (*veh)->planMove(t, pred, cumulatedVehLength);
659  }
660  pred = *veh;
661  cumulatedVehLength += pred->getVehicleType().getLengthWithGap();
662  }
663 }
664 
665 
666 void
667 MSLane::detectCollisions(SUMOTime timestep, const std::string& stage) {
668  if (myVehicles.size() < 2) {
669  return;
670  }
671 
672  VehCont::iterator lastVeh = myVehicles.end() - 1;
673  for (VehCont::iterator veh = myVehicles.begin(); veh != lastVeh;) {
674  VehCont::iterator pred = veh + 1;
675  if ((*veh)->hasInfluencer() && (*veh)->getInfluencer().isVTDControlled()) {
676  ++veh;
677  continue;
678  }
679  if ((*pred)->hasInfluencer() && (*pred)->getInfluencer().isVTDControlled()) {
680  ++veh;
681  continue;
682  }
683  SUMOReal gap = (*pred)->getPositionOnLane() - (*pred)->getVehicleType().getLength() - (*veh)->getPositionOnLane() - (*veh)->getVehicleType().getMinGap();
684  if (gap < -NUMERICAL_EPS) {
685  MSVehicle* vehV = *veh;
686  if (vehV->getLane() == this) {
687  WRITE_WARNING("Teleporting vehicle '" + vehV->getID() + "'; collision with '"
688  + (*pred)->getID() + "', lane='" + getID() + "', gap=" + toString(gap)
689  + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + " stage=" + stage + ".");
693  MSVehicleTransfer::getInstance()->add(timestep, vehV);
694  veh = myVehicles.erase(veh); // remove current vehicle
695  lastVeh = myVehicles.end() - 1;
696  if (veh == myVehicles.end()) {
697  break;
698  }
699  } else {
700  WRITE_WARNING("Shadow of vehicle '" + vehV->getID() + "'; collision with '"
701  + (*pred)->getID() + "', lane='" + getID() + "', gap=" + toString(gap)
702  + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + " stage=" + stage + ".");
703  veh = myVehicles.erase(veh); // remove current vehicle
704  lastVeh = myVehicles.end() - 1;
706  if (veh == myVehicles.end()) {
707  break;
708  }
709  }
710  } else {
711  ++veh;
712  }
713  }
714 }
715 
716 
717 bool
718 MSLane::executeMovements(SUMOTime t, std::vector<MSLane*>& into) {
719  // iteratate over vehicles in reverse so that move reminders will be called in the correct order
720  for (VehCont::reverse_iterator i = myVehicles.rbegin(); i != myVehicles.rend();) {
721  MSVehicle* veh = *i;
722  if (veh->getLane() != this || veh->getLaneChangeModel().alreadyMoved()) {
723  // this is the shadow during a continuous lane change
724  ++i;
725  continue;
726  }
727  // length is needed later when the vehicle may not exist anymore
728  const SUMOReal length = veh->getVehicleType().getLengthWithGap();
729  const SUMOReal nettoLength = veh->getVehicleType().getLength();
730  bool moved = veh->executeMove();
731  MSLane* target = veh->getLane();
732 #ifndef NO_TRACI
733  bool vtdControlled = veh->hasInfluencer() && veh->getInfluencer().isVTDControlled();
734  if (veh->hasArrived() && !vtdControlled) {
735 #else
736  if (veh->hasArrived()) {
737 #endif
738  // vehicle has reached its arrival position
741  } else if (target != 0 && moved) {
742  if (target->getEdge().isVaporizing()) {
743  // vehicle has reached a vaporizing edge
746  } else {
747  // vehicle has entered a new lane (leaveLane was already called in MSVehicle::executeMove)
748  target->myVehBuffer.push_back(veh);
749  SUMOReal pspeed = veh->getSpeed();
750  SUMOReal oldPos = veh->getPositionOnLane() - SPEED2DIST(veh->getSpeed());
751  veh->workOnMoveReminders(oldPos, veh->getPositionOnLane(), pspeed);
752  into.push_back(target);
753  if (veh->getLaneChangeModel().isChangingLanes()) {
754  MSLane* shadowLane = veh->getLaneChangeModel().getShadowLane();
755  if (shadowLane != 0) {
756  into.push_back(shadowLane);
757  shadowLane->myVehBuffer.push_back(veh);
758  }
759  }
760  }
761  } else if (veh->isParking()) {
762  // vehicle started to park
764  } else if (veh->getPositionOnLane() > getLength()) {
765  // for any reasons the vehicle is beyond its lane...
766  // this should never happen because it is handled in MSVehicle::executeMove
767  assert(false);
768  WRITE_WARNING("Teleporting vehicle '" + veh->getID() + "'; beyond end of lane, targetLane='" + getID() + "', time=" +
769  time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
772  } else {
773  ++i;
774  continue;
775  }
776  myBruttoVehicleLengthSum -= length;
777  myNettoVehicleLengthSum -= nettoLength;
778  ++i;
779  i = VehCont::reverse_iterator(myVehicles.erase(i.base()));
780  }
781  if (myVehicles.size() > 0) {
783  MSVehicle* veh = myVehicles.back(); // the vehice at the front of the queue
784  if (!veh->isStopped()) {
785  const bool wrongLane = !veh->getLane()->appropriate(veh);
787  const bool r2 = MSGlobals::gTimeToGridlockHighways > 0 && veh->getWaitingTime() > MSGlobals::gTimeToGridlockHighways && veh->getLane()->getSpeedLimit() > 69. / 3.6 && wrongLane;
788  if (r1 || r2) {
789  const MSLinkCont::const_iterator link = succLinkSec(*veh, 1, *this, veh->getBestLanesContinuation());
790  const bool minorLink = !wrongLane && (link != myLinks.end()) && !((*link)->havePriority());
791  const std::string reason = (wrongLane ? " (wrong lane)" : (minorLink ? " (yield)" : " (jam)"));
792  MSVehicle* veh = *(myVehicles.end() - 1);
795  myVehicles.erase(myVehicles.end() - 1);
796  WRITE_WARNING("Teleporting vehicle '" + veh->getID() + "'; waited too long"
797  + reason
798  + (r2 ? " (highway)" : "")
799  + ", lane='" + getID() + "', time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
800  if (wrongLane) {
802  } else if (minorLink) {
804  } else {
806  }
808  }
809  } // else look for a vehicle that isn't stopped?
810  }
811  }
812  return myVehicles.size() == 0;
813 }
814 
815 
816 const MSEdge*
818  const MSEdge* e = myEdge;
819  while (e->getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL) {
820  e = e->getFollower(0);
821  }
822  return e;
823 }
824 
825 
826 // ------ Static (sic!) container methods ------
827 bool
828 MSLane::dictionary(const std::string& id, MSLane* ptr) {
829  DictType::iterator it = myDict.find(id);
830  if (it == myDict.end()) {
831  // id not in myDict.
832  myDict.insert(DictType::value_type(id, ptr));
833  return true;
834  }
835  return false;
836 }
837 
838 
839 MSLane*
840 MSLane::dictionary(const std::string& id) {
841  DictType::iterator it = myDict.find(id);
842  if (it == myDict.end()) {
843  // id not in myDict.
844  return 0;
845  }
846  return it->second;
847 }
848 
849 
850 void
852  for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
853  delete(*i).second;
854  }
855  myDict.clear();
856 }
857 
858 
859 void
860 MSLane::insertIDs(std::vector<std::string>& into) {
861  for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
862  into.push_back((*i).first);
863  }
864 }
865 
866 
867 template<class RTREE> void
868 MSLane::fill(RTREE& into) {
869  for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
870  MSLane* l = (*i).second;
871  Boundary b = l->getShape().getBoxBoundary();
872  b.grow(3.);
873  const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
874  const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
875  into.Insert(cmin, cmax, l);
876  }
877 }
878 
879 template void MSLane::fill<NamedRTree>(NamedRTree& into);
880 #ifndef NO_TRACI
881 template void MSLane::fill<LANE_RTREE_QUAL>(LANE_RTREE_QUAL& into);
882 #endif
883 
884 // ------ ------
885 bool
888  return true;
889  }
890  if (veh->succEdge(1) == 0) {
891  assert(veh->getBestLanes().size() > veh->getLaneIndex());
892  if (veh->getBestLanes()[veh->getLaneIndex()].bestLaneOffset == 0) {
893  return true;
894  } else {
895  return false;
896  }
897  }
898  MSLinkCont::const_iterator link = succLinkSec(*veh, 1, *this, veh->getBestLanesContinuation());
899  return (link != myLinks.end());
900 }
901 
902 
903 bool
905  bool wasInactive = myVehicles.size() == 0;
906  sort(myVehBuffer.begin(), myVehBuffer.end(), vehicle_position_sorter());
907  for (std::vector<MSVehicle*>::const_iterator i = myVehBuffer.begin(); i != myVehBuffer.end(); ++i) {
908  MSVehicle* veh = *i;
909  myVehicles.insert(myVehicles.begin(), veh);
912  }
913  myVehBuffer.clear();
914  return wasInactive && myVehicles.size() != 0;
915 }
916 
917 
918 bool
919 MSLane::isLinkEnd(MSLinkCont::const_iterator& i) const {
920  return i == myLinks.end();
921 }
922 
923 
924 bool
925 MSLane::isLinkEnd(MSLinkCont::iterator& i) {
926  return i == myLinks.end();
927 }
928 
929 
930 MSVehicle*
932  if (myVehicles.size() == 0) {
933  return 0;
934  }
935  return *myVehicles.begin();
936 }
937 
938 
939 const MSVehicle*
941  if (myVehicles.size() == 0) {
942  return 0;
943  }
944  return *(myVehicles.end() - 1);
945 }
946 
947 
948 MSLinkCont::const_iterator
949 MSLane::succLinkSec(const SUMOVehicle& veh, unsigned int nRouteSuccs,
950  const MSLane& succLinkSource, const std::vector<MSLane*>& conts) {
951  const MSEdge* nRouteEdge = veh.succEdge(nRouteSuccs);
952  // check whether the vehicle tried to look beyond its route
953  if (nRouteEdge == 0) {
954  // return end (no succeeding link) if so
955  return succLinkSource.myLinks.end();
956  }
957  // if we are on an internal lane there should only be one link and it must be allowed
958  if (succLinkSource.getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL) {
959  assert(succLinkSource.myLinks.size() == 1);
960  assert(succLinkSource.myLinks[0]->getLane()->allowsVehicleClass(veh.getVehicleType().getVehicleClass()));
961  return succLinkSource.myLinks.begin();
962  }
963  // a link may be used if
964  // 1) there is a destination lane ((*link)->getLane()!=0)
965  // 2) the destination lane belongs to the next edge in route ((*link)->getLane()->myEdge == nRouteEdge)
966  // 3) the destination lane allows the vehicle's class ((*link)->getLane()->allowsVehicleClass(veh.getVehicleClass()))
967 
968  // there should be a link which leads to the next desired lane our route in "conts" (built in "getBestLanes")
969  // "conts" stores the best continuations of our current lane
970  // we should never return an arbitrary link since this may cause collisions
971  MSLinkCont::const_iterator link;
972  if (nRouteSuccs < conts.size()) {
973  // we go through the links in our list and return the matching one
974  for (link = succLinkSource.myLinks.begin(); link != succLinkSource.myLinks.end(); ++link) {
975  if ((*link)->getLane() != 0 && (*link)->getLane()->myEdge == nRouteEdge && (*link)->getLane()->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
976  // we should use the link if it connects us to the best lane
977  if ((*link)->getLane() == conts[nRouteSuccs]) {
978  return link;
979  }
980  }
981  }
982  } else {
983  // the source lane is a dead end (no continuations exist)
984  return succLinkSource.myLinks.end();
985  }
986  // the only case where this should happen is for a disconnected route (deliberately ignored)
987 #ifdef _DEBUG
988  WRITE_WARNING("Could not find connection between '" + succLinkSource.getID() + "' and '" + conts[nRouteSuccs]->getID() +
989  "' for vehicle '" + veh.getID() + "' time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
990 #endif
991  return succLinkSource.myLinks.end();
992 }
993 
994 
995 
996 const MSLinkCont&
998  return myLinks;
999 }
1000 
1001 
1002 void
1005  myTmpVehicles.clear();
1006 }
1007 
1008 
1009 MSVehicle*
1010 MSLane::removeVehicle(MSVehicle* remVehicle, MSMoveReminder::Notification notification, bool notify) {
1011  for (MSLane::VehCont::iterator it = myVehicles.begin(); it < myVehicles.end(); it++) {
1012  if (remVehicle == *it) {
1013  if (notify) {
1014  remVehicle->leaveLane(notification);
1015  }
1016  myVehicles.erase(it);
1019  break;
1020  }
1021  }
1022  return remVehicle;
1023 }
1024 
1025 
1026 MSLane*
1027 MSLane::getParallelLane(int offset) const {
1028  return myEdge->parallelLane(this, offset);
1029 }
1030 
1031 
1032 void
1034  IncomingLaneInfo ili;
1035  ili.lane = lane;
1036  ili.viaLink = viaLink;
1037  ili.length = lane->getLength();
1038  myIncomingLanes.push_back(ili);
1039 }
1040 
1041 
1042 void
1044  MSEdge* approachingEdge = &lane->getEdge();
1045  if (myApproachingLanes.find(approachingEdge) == myApproachingLanes.end()) {
1046  myApproachingLanes[approachingEdge] = std::vector<MSLane*>();
1047  }
1048  myApproachingLanes[approachingEdge].push_back(lane);
1049 }
1050 
1051 
1052 bool
1054  return myApproachingLanes.find(edge) != myApproachingLanes.end();
1055 }
1056 
1057 
1058 bool
1059 MSLane::isApproachedFrom(MSEdge* const edge, MSLane* const lane) {
1060  std::map<MSEdge*, std::vector<MSLane*> >::const_iterator i = myApproachingLanes.find(edge);
1061  if (i == myApproachingLanes.end()) {
1062  return false;
1063  }
1064  const std::vector<MSLane*>& lanes = (*i).second;
1065  return find(lanes.begin(), lanes.end(), lane) != lanes.end();
1066 }
1067 
1068 
1070 public:
1071  inline int operator()(const std::pair<const MSVehicle* , SUMOReal>& p1, const std::pair<const MSVehicle* , SUMOReal>& p2) const {
1072  return p1.second < p2.second;
1073  }
1074 };
1075 
1076 
1078  SUMOReal dist, SUMOReal backOffset, SUMOReal leaderSpeed, SUMOReal leaderMaxDecel) const {
1079  // this follows the same logic as getFollowerOnConsecutive. we do a tree
1080  // search until dist and check for the vehicle with the largest missing rear gap
1081  SUMOReal result = 0;
1082  std::set<MSLane*> visited;
1083  std::vector<MSLane::IncomingLaneInfo> newFound;
1084  std::vector<MSLane::IncomingLaneInfo> toExamine = myIncomingLanes;
1085  while (toExamine.size() != 0) {
1086  for (std::vector<MSLane::IncomingLaneInfo>::iterator i = toExamine.begin(); i != toExamine.end(); ++i) {
1087  MSLane* next = (*i).lane;
1088  if (next->getFirstVehicle() != 0) {
1089  MSVehicle* v = (MSVehicle*) next->getFirstVehicle();
1090  const SUMOReal agap = (*i).length - v->getPositionOnLane() + backOffset - v->getVehicleType().getMinGap();
1091  const SUMOReal missingRearGap = v->getCarFollowModel().getSecureGap(
1092  v->getCarFollowModel().maxNextSpeed(v->getSpeed(), v), leaderSpeed, leaderMaxDecel) - agap;
1093  result = MAX2(result, missingRearGap);
1094  } else {
1095  if ((*i).length < dist) {
1096  const std::vector<MSLane::IncomingLaneInfo>& followers = next->getIncomingLanes();
1097  for (std::vector<MSLane::IncomingLaneInfo>::const_iterator j = followers.begin(); j != followers.end(); ++j) {
1098  if (visited.find((*j).lane) == visited.end()) {
1099  visited.insert((*j).lane);
1101  ili.lane = (*j).lane;
1102  ili.length = (*j).length + (*i).length;
1103  ili.viaLink = (*j).viaLink;
1104  newFound.push_back(ili);
1105  }
1106  }
1107  }
1108  }
1109  }
1110  toExamine.clear();
1111  swap(newFound, toExamine);
1112  }
1113  return result;
1114 }
1115 
1116 
1117 std::pair<MSVehicle* const, SUMOReal>
1119  SUMOReal backOffset, SUMOReal leaderMaxDecel) const {
1120  // do a tree search among all follower lanes and check for the most
1121  // important vehicle (the one requiring the largest reargap)
1122  std::pair<MSVehicle*, SUMOReal> result(static_cast<MSVehicle*>(0), -1);
1123  SUMOReal missingRearGapMax = 0;
1124  std::set<MSLane*> visited;
1125  std::vector<MSLane::IncomingLaneInfo> newFound;
1126  std::vector<MSLane::IncomingLaneInfo> toExamine = myIncomingLanes;
1127  while (toExamine.size() != 0) {
1128  for (std::vector<MSLane::IncomingLaneInfo>::iterator i = toExamine.begin(); i != toExamine.end(); ++i) {
1129  MSLane* next = (*i).lane;
1130  if (next->getFirstVehicle() != 0) {
1131  MSVehicle* v = (MSVehicle*) next->getFirstVehicle();
1132  const SUMOReal agap = (*i).length - v->getPositionOnLane() + backOffset - v->getVehicleType().getMinGap();
1133  const SUMOReal missingRearGap = v->getCarFollowModel().getSecureGap(v->getSpeed(), leaderSpeed, leaderMaxDecel) - agap;
1134  if (missingRearGap > missingRearGapMax) {
1135  missingRearGapMax = missingRearGap;
1136  result.first = v;
1137  result.second = agap;
1138  }
1139  } else {
1140  if ((*i).length < dist) {
1141  const std::vector<MSLane::IncomingLaneInfo>& followers = next->getIncomingLanes();
1142  for (std::vector<MSLane::IncomingLaneInfo>::const_iterator j = followers.begin(); j != followers.end(); ++j) {
1143  if (visited.find((*j).lane) == visited.end()) {
1144  visited.insert((*j).lane);
1146  ili.lane = (*j).lane;
1147  ili.length = (*j).length + (*i).length;
1148  ili.viaLink = (*j).viaLink;
1149  newFound.push_back(ili);
1150  }
1151  }
1152  }
1153  }
1154  }
1155  toExamine.clear();
1156  swap(newFound, toExamine);
1157  }
1158  return result;
1159 }
1160 
1161 
1162 std::pair<MSVehicle* const, SUMOReal>
1164  const std::vector<MSLane*>& bestLaneConts) const {
1165  if (seen > dist) {
1166  return std::make_pair(static_cast<MSVehicle*>(0), -1);
1167  }
1168  unsigned int view = 1;
1169  // loop over following lanes
1170  if (getPartialOccupator() != 0) {
1171  return std::make_pair(getPartialOccupator(), seen - (getLength() - getPartialOccupatorEnd()) - veh.getVehicleType().getMinGap());
1172  }
1173  const MSLane* nextLane = this;
1174  SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / MAX2(speed, NUMERICAL_EPS));
1175  do {
1176  // get the next link used
1177  MSLinkCont::const_iterator link = succLinkSec(veh, view, *nextLane, bestLaneConts);
1178  if (nextLane->isLinkEnd(link) || !(*link)->opened(arrivalTime, speed, speed, veh.getVehicleType().getLength(),
1179  veh.getImpatience(), veh.getCarFollowModel().getMaxDecel(), 0) || (*link)->getState() == LINKSTATE_TL_RED) {
1180  break;
1181  }
1182 #ifdef HAVE_INTERNAL_LANES
1183  // check for link leaders
1184  const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(seen, veh.getVehicleType().getMinGap());
1185  if (linkLeaders.size() > 0) {
1186  // XXX if there is more than one link leader we should return the most important
1187  // one (gap, decel) but this is hard to know at this point
1188  return linkLeaders[0].vehAndGap;
1189  }
1190  bool nextInternal = (*link)->getViaLane() != 0;
1191 #endif
1192  nextLane = (*link)->getViaLaneOrLane();
1193  if (nextLane == 0) {
1194  break;
1195  }
1196  MSVehicle* leader = nextLane->getLastVehicle();
1197  if (leader != 0) {
1198  return std::make_pair(leader, seen + leader->getPositionOnLane() - leader->getVehicleType().getLength() - veh.getVehicleType().getMinGap());
1199  } else {
1200  leader = nextLane->getPartialOccupator();
1201  if (leader != 0) {
1202  return std::make_pair(leader, seen + nextLane->getPartialOccupatorEnd() - veh.getVehicleType().getMinGap());
1203  }
1204  }
1205  if (nextLane->getVehicleMaxSpeed(&veh) < speed) {
1206  dist = veh.getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(&veh));
1207  }
1208  seen += nextLane->getLength();
1209  if (seen <= dist) {
1210  // delaying the update of arrivalTime and making it conditional to avoid possible integer overflows
1211  arrivalTime += TIME2STEPS(nextLane->getLength() / MAX2(speed, NUMERICAL_EPS));
1212  }
1213 #ifdef HAVE_INTERNAL_LANES
1214  if (!nextInternal) {
1215  view++;
1216  }
1217 #else
1218  view++;
1219 #endif
1220  } while (seen <= dist);
1221  return std::make_pair(static_cast<MSVehicle*>(0), -1);
1222 }
1223 
1224 
1225 MSLane*
1227  if (myLogicalPredecessorLane != 0) {
1228  return myLogicalPredecessorLane;
1229  }
1230  if (myLogicalPredecessorLane == 0) {
1231  std::vector<MSEdge*> pred = myEdge->getIncomingEdges();
1232  // get only those edges which connect to this lane
1233  for (std::vector<MSEdge*>::iterator i = pred.begin(); i != pred.end();) {
1234  std::vector<IncomingLaneInfo>::const_iterator j = find_if(myIncomingLanes.begin(), myIncomingLanes.end(), edge_finder(*i));
1235  if (j == myIncomingLanes.end()) {
1236  i = pred.erase(i);
1237  } else {
1238  ++i;
1239  }
1240  }
1241  // get the edge with the most connections to this lane's edge
1242  if (pred.size() != 0) {
1243  std::sort(pred.begin(), pred.end(), by_connections_to_sorter(&getEdge()));
1244  MSEdge* best = *pred.begin();
1245  std::vector<IncomingLaneInfo>::const_iterator j = find_if(myIncomingLanes.begin(), myIncomingLanes.end(), edge_finder(best));
1246  myLogicalPredecessorLane = (*j).lane;
1247  }
1248  }
1249  return myLogicalPredecessorLane;
1250 }
1251 
1252 
1253 LinkState
1256  if (pred == 0) {
1257  return LINKSTATE_DEADEND;
1258  } else {
1259  return MSLinkContHelper::getConnectingLink(*pred, *this)->getState();
1260  }
1261 }
1262 
1263 
1264 std::vector<const MSLane*>
1266  std::vector<const MSLane*> result;
1267  for (MSLinkCont::const_iterator i = myLinks.begin(); i != myLinks.end(); ++i) {
1268  assert((*i)->getLane() != 0);
1269  result.push_back((*i)->getLane());
1270  }
1271  return result;
1272 }
1273 
1274 
1275 void
1279 }
1280 
1281 
1282 void
1286 }
1287 
1288 
1289 int
1291  for (MSLinkCont::const_iterator i = myLinks.begin(); i != myLinks.end(); ++i) {
1292  if ((*i)->getLane()->getEdge().isCrossing()) {
1293  return (int)(i - myLinks.begin());
1294  }
1295  }
1296  return -1;
1297 }
1298 
1299 // ------------ Current state retrieval
1300 SUMOReal
1302  SUMOReal fractions = myInlappingVehicle != 0 ? myLength - myInlappingVehicleEnd : 0;
1304  if (myVehicles.size() != 0) {
1305  MSVehicle* lastVeh = myVehicles.front();
1306  if (lastVeh->getPositionOnLane() < lastVeh->getVehicleType().getLength()) {
1307  fractions -= (lastVeh->getVehicleType().getLength() - lastVeh->getPositionOnLane());
1308  }
1309  }
1310  releaseVehicles();
1311  return (myBruttoVehicleLengthSum + fractions) / myLength;
1312 }
1313 
1314 
1315 SUMOReal
1317  SUMOReal fractions = myInlappingVehicle != 0 ? myLength - myInlappingVehicleEnd : 0;
1319  if (myVehicles.size() != 0) {
1320  MSVehicle* lastVeh = myVehicles.front();
1321  if (lastVeh->getPositionOnLane() < lastVeh->getVehicleType().getLength()) {
1322  fractions -= (lastVeh->getVehicleType().getLength() - lastVeh->getPositionOnLane());
1323  }
1324  }
1325  releaseVehicles();
1326  return (myNettoVehicleLengthSum + fractions) / myLength;
1327 }
1328 
1329 
1330 SUMOReal
1332  return myBruttoVehicleLengthSum;
1333 }
1334 
1335 
1336 SUMOReal
1338  if (myVehicles.size() == 0) {
1339  return 0;
1340  }
1341  SUMOReal wtime = 0;
1342  for (VehCont::const_iterator i = myVehicles.begin(); i != myVehicles.end(); ++i) {
1343  wtime += (*i)->getWaitingSeconds();
1344  }
1345  return wtime;
1346 }
1347 
1348 
1349 SUMOReal
1351  if (myVehicles.size() == 0) {
1352  return myMaxSpeed;
1353  }
1354  SUMOReal v = 0;
1355  const MSLane::VehCont& vehs = getVehiclesSecure();
1356  for (VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1357  v += (*i)->getSpeed();
1358  }
1359  SUMOReal ret = v / (SUMOReal) myVehicles.size();
1360  releaseVehicles();
1361  return ret;
1362 }
1363 
1364 
1365 SUMOReal
1367  SUMOReal ret = 0;
1368  const MSLane::VehCont& vehs = getVehiclesSecure();
1369  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1370  ret += (*i)->getCO2Emissions();
1371  }
1372  releaseVehicles();
1373  return ret;
1374 }
1375 
1376 
1377 SUMOReal
1379  SUMOReal ret = 0;
1380  const MSLane::VehCont& vehs = getVehiclesSecure();
1381  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1382  ret += (*i)->getCOEmissions();
1383  }
1384  releaseVehicles();
1385  return ret;
1386 }
1387 
1388 
1389 SUMOReal
1391  SUMOReal ret = 0;
1392  const MSLane::VehCont& vehs = getVehiclesSecure();
1393  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1394  ret += (*i)->getPMxEmissions();
1395  }
1396  releaseVehicles();
1397  return ret;
1398 }
1399 
1400 
1401 SUMOReal
1403  SUMOReal ret = 0;
1404  const MSLane::VehCont& vehs = getVehiclesSecure();
1405  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1406  ret += (*i)->getNOxEmissions();
1407  }
1408  releaseVehicles();
1409  return ret;
1410 }
1411 
1412 
1413 SUMOReal
1415  SUMOReal ret = 0;
1416  const MSLane::VehCont& vehs = getVehiclesSecure();
1417  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1418  ret += (*i)->getHCEmissions();
1419  }
1420  releaseVehicles();
1421  return ret;
1422 }
1423 
1424 
1425 SUMOReal
1427  SUMOReal ret = 0;
1428  const MSLane::VehCont& vehs = getVehiclesSecure();
1429  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1430  ret += (*i)->getFuelConsumption();
1431  }
1432  releaseVehicles();
1433  return ret;
1434 }
1435 
1436 
1437 SUMOReal
1439  SUMOReal ret = 0;
1440  const MSLane::VehCont& vehs = getVehiclesSecure();
1441  if (vehs.size() == 0) {
1442  releaseVehicles();
1443  return 0;
1444  }
1445  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1446  SUMOReal sv = (*i)->getHarmonoise_NoiseEmissions();
1447  ret += (SUMOReal) pow(10., (sv / 10.));
1448  }
1449  releaseVehicles();
1450  return HelpersHarmonoise::sum(ret);
1451 }
1452 
1453 
1454 bool
1456  return cmp->getPositionOnLane() >= pos;
1457 }
1458 
1459 
1460 int
1462  return v1->getPositionOnLane() > v2->getPositionOnLane();
1463 }
1464 
1466  myEdge(e),
1467  myLaneDir(e->getLanes()[0]->getShape().getBegLine().atan2PositiveAngle())
1468 { }
1469 
1470 
1471 int
1472 MSLane::by_connections_to_sorter::operator()(const MSEdge* const e1, const MSEdge* const e2) const {
1473  const std::vector<MSLane*>* ae1 = e1->allowedLanes(*myEdge);
1474  const std::vector<MSLane*>* ae2 = e2->allowedLanes(*myEdge);
1475  SUMOReal s1 = 0;
1476  if (ae1 != 0 && ae1->size() != 0) {
1477  s1 = (SUMOReal) ae1->size() + GeomHelper::getMinAngleDiff((*ae1)[0]->getShape().getBegLine().atan2PositiveAngle(), myLaneDir) / M_PI / 2.;
1478  }
1479  SUMOReal s2 = 0;
1480  if (ae2 != 0 && ae2->size() != 0) {
1481  s2 = (SUMOReal) ae2->size() + GeomHelper::getMinAngleDiff((*ae2)[0]->getShape().getBegLine().atan2PositiveAngle(), myLaneDir) / M_PI / 2.;
1482  }
1483  return s1 < s2;
1484 }
1485 
1486 
1487 void
1489  out.openTag(SUMO_TAG_LANE);
1492  out.closeTag();
1493  out.closeTag();
1494 }
1495 
1496 
1497 void
1498 MSLane::loadState(std::vector<std::string>& vehIds, MSVehicleControl& vc) {
1499  for (std::vector<std::string>::const_iterator it = vehIds.begin(); it != vehIds.end(); ++it) {
1500  MSVehicle* v = dynamic_cast<MSVehicle*>(vc.getVehicle(*it));
1501  assert(v != 0);
1502  v->updateBestLanes(true, this);
1505  }
1506 }
1507 
1508 
1509 
1510 /****************************************************************************/
1511