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 /****************************************************************************/
13 // Representation of a lane in the micro simulation
14 /****************************************************************************/
15 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
16 // Copyright (C) 2001-2013 DLR (http://www.dlr.de/) and contributors
17 /****************************************************************************/
18 //
19 // This file is part of SUMO.
20 // SUMO is free software: you can redistribute it and/or modify
21 // it under the terms of the GNU General Public License as published by
22 // the Free Software Foundation, either version 3 of the License, or
23 // (at your option) any later version.
24 //
25 /****************************************************************************/
26 
27 
28 // ===========================================================================
29 // included modules
30 // ===========================================================================
31 #ifdef _MSC_VER
32 #include <windows_config.h>
33 #else
34 #include <config.h>
35 #endif
36 
38 #include <utils/common/StdDefs.h>
39 #include "MSVehicle.h"
41 #include "MSNet.h"
42 #include "MSVehicleType.h"
43 #include "MSEdge.h"
44 #include "MSEdgeControl.h"
45 #include "MSJunction.h"
46 #include "MSLogicJunction.h"
47 #include "MSLink.h"
48 #include "MSLane.h"
49 #include "MSVehicleTransfer.h"
50 #include "MSGlobals.h"
51 #include "MSVehicleControl.h"
52 #include "MSInsertionControl.h"
53 #include "MSVehicleControl.h"
54 #include <cmath>
55 #include <bitset>
56 #include <iostream>
57 #include <cassert>
58 #include <functional>
59 #include <algorithm>
60 #include <iterator>
61 #include <exception>
62 #include <climits>
63 #include <set>
65 #include <utils/common/ToString.h>
68 #include <utils/geom/Line.h>
69 #include <utils/geom/GeomHelper.h>
70 
71 #ifdef CHECK_MEMORY_LEAKS
72 #include <foreign/nvwa/debug_new.h>
73 #endif // CHECK_MEMORY_LEAKS
74 
75 
76 // ===========================================================================
77 // static member definitions
78 // ===========================================================================
80 
81 
82 // ===========================================================================
83 // member method definitions
84 // ===========================================================================
85 MSLane::MSLane(const std::string& id, SUMOReal maxSpeed, SUMOReal length, MSEdge* const edge,
86  unsigned int numericalID, const PositionVector& shape, SUMOReal width,
87  SVCPermissions permissions) :
88  Named(id),
89  myShape(shape), myNumericalID(numericalID),
90  myVehicles(), myLength(length), myWidth(width), myEdge(edge), myMaxSpeed(maxSpeed),
91  myPermissions(permissions),
92  myLogicalPredecessorLane(0),
93  myBruttoVehicleLengthSum(0), myNettoVehicleLengthSum(0), myInlappingVehicleEnd(10000), myInlappingVehicle(0),
94  myLengthGeometryFactor(myShape.length() / myLength) {}
95 
96 
98  for (MSLinkCont::iterator i = myLinks.begin(); i != myLinks.end(); ++i) {
99  delete *i;
100  }
101 }
102 
103 
104 void
106  myLinks.push_back(link);
107 }
108 
109 
110 // ------ interaction with MSMoveReminder ------
111 void
113  myMoveReminders.push_back(rem);
114  for (VehCont::iterator veh = myVehicles.begin(); veh != myVehicles.end(); ++veh) {
115  (*veh)->addReminder(rem);
116  }
117 }
118 
119 
120 
121 // ------ Vehicle emission ------
122 void
123 MSLane::incorporateVehicle(MSVehicle* veh, SUMOReal pos, SUMOReal speed, const MSLane::VehCont::iterator& at, MSMoveReminder::Notification notification) {
124  assert(pos <= myLength);
125  bool wasInactive = myVehicles.size() == 0;
126  veh->enterLaneAtInsertion(this, pos, speed, notification);
127  if (at == myVehicles.end()) {
128  // vehicle will be the first on the lane
129  myVehicles.push_back(veh);
130  } else {
131  myVehicles.insert(at, veh);
132  }
135  if (wasInactive) {
137  }
138 }
139 
140 
141 bool
143  SUMOReal xIn = maxPos;
144  SUMOReal vIn = mspeed;
145  SUMOReal leaderDecel;
146  veh.getBestLanes(true, this);
147  if (myVehicles.size() != 0) {
148  MSVehicle* leader = myVehicles.front();
149  xIn = leader->getPositionOnLane() - leader->getVehicleType().getLength() - veh.getVehicleType().getMinGap();
150  vIn = leader->getSpeed();
151  leaderDecel = leader->getCarFollowModel().getMaxDecel();
152  } else {
153  SUMOReal brakeGap = veh.getCarFollowModel().brakeGap(mspeed);
154  std::pair<MSVehicle* const, SUMOReal> leader = getLeaderOnConsecutive(brakeGap, 0, mspeed, veh, veh.getBestLanesContinuation(this));
155  if (leader.first != 0) {
156  xIn = getLength() + leader.second;
157  vIn = leader.first->getSpeed();
158  leaderDecel = leader.first->getCarFollowModel().getMaxDecel();
159  } else {
160  incorporateVehicle(&veh, maxPos, mspeed, myVehicles.end());
161  return true;
162  }
163  }
164  const SUMOReal vHlp = 0.5 * (vIn + mspeed);
165  SUMOReal x2 = xIn;// have seen leader length already - skCar::lCar;
166  SUMOReal x1 = x2 - 100.0;
167  SUMOReal x = 0;
168  for (int i = 0; i <= 10; i++) {
169  x = 0.5 * (x1 + x2);
170  SUMOReal vSafe = veh.getCarFollowModel().followSpeed(&veh, vHlp, xIn - x, vIn, leaderDecel);
171  if (vSafe < vHlp) {
172  x2 = x;
173  } else {
174  x1 = x;
175  }
176  }
177  if (x < minPos) {
178  return false;
179  } else if (x > maxPos) {
180  x = maxPos;
181  }
182  incorporateVehicle(&veh, x, vHlp, myVehicles.begin());
183  return true;
184 }
185 
186 
187 bool
189  SUMOReal xIn = maxPos;
190  SUMOReal vIn = mspeed;
191  veh.getBestLanes(true, this);
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 = leaderRearPos + frontGap;
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->getBestLanes(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 / speed);
445  while (seen < dist && ri != bestLaneConts.end()) {
446  // get the next link used...
447  MSLinkCont::const_iterator link = currentLane->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() / speed);
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 = nextLane->getVehicleMaxSpeed(aVehicle);
515  if (nspeed < speed) {
516  if (patchSpeed) {
517  speed = MIN2(cfModel.freeSpeed(aVehicle, speed, seen, nspeed), speed);
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 / speed);
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(), aVehicle->getSpeed(), 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->getBestLanes(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, int 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 < -0.001) {
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=" + toString(stage) + ".");
693  MSVehicleTransfer::getInstance()->addVeh(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=" + toString(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
765  } else if (veh->getPositionOnLane() > getLength()) {
766  // for any reasons the vehicle is beyond its lane... error
767  WRITE_WARNING("Teleporting vehicle '" + veh->getID() + "'; beyond lane (2), targetLane='" + getID() + "', time=" +
768  time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
771  } else {
772  ++i;
773  continue;
774  }
775  myBruttoVehicleLengthSum -= length;
776  myNettoVehicleLengthSum -= nettoLength;
777  ++i;
778  i = VehCont::reverse_iterator(myVehicles.erase(i.base()));
779  }
780  if (myVehicles.size() > 0) {
782  MSVehicle* veh = myVehicles.back(); // the vehice at the front of the queue
783  if (!veh->isStopped()) {
784  const bool wrongLane = !veh->getLane()->appropriate(veh);
786  const bool r2 = MSGlobals::gTimeToGridlockHighways > 0 && veh->getWaitingTime() > MSGlobals::gTimeToGridlockHighways && veh->getLane()->getSpeedLimit() > 69. / 3.6 && wrongLane;
787  if (r1 || r2) {
788  const MSLinkCont::const_iterator link = succLinkSec(*veh, 1, *this, veh->getBestLanesContinuation());
789  const bool minorLink = !wrongLane && (link != myLinks.end()) && !((*link)->havePriority());
790  const std::string reason = (wrongLane ? " (wrong lane)" : (minorLink ? " (yield)" : " (jam)"));
791  MSVehicle* veh = *(myVehicles.end() - 1);
794  myVehicles.erase(myVehicles.end() - 1);
795  WRITE_WARNING("Teleporting vehicle '" + veh->getID() + "'; waited too long"
796  + reason
797  + (r2 ? " (highway)" : "")
798  + ", lane='" + getID() + "', time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
801  }
802  } // else look for a vehicle that isn't stopped?
803  }
804  }
805  return myVehicles.size() == 0;
806 }
807 
808 
809 
810 // ------ Static (sic!) container methods ------
811 bool
812 MSLane::dictionary(const std::string& id, MSLane* ptr) {
813  DictType::iterator it = myDict.find(id);
814  if (it == myDict.end()) {
815  // id not in myDict.
816  myDict.insert(DictType::value_type(id, ptr));
817  return true;
818  }
819  return false;
820 }
821 
822 
823 MSLane*
824 MSLane::dictionary(const std::string& id) {
825  DictType::iterator it = myDict.find(id);
826  if (it == myDict.end()) {
827  // id not in myDict.
828  return 0;
829  }
830  return it->second;
831 }
832 
833 
834 void
836  for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
837  delete(*i).second;
838  }
839  myDict.clear();
840 }
841 
842 
843 void
844 MSLane::insertIDs(std::vector<std::string>& into) {
845  for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
846  into.push_back((*i).first);
847  }
848 }
849 
850 
851 template<class RTREE> void
852 MSLane::fill(RTREE& into) {
853  for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
854  MSLane* l = (*i).second;
855  Boundary b = l->getShape().getBoxBoundary();
856  b.grow(3.);
857  const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
858  const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
859  into.Insert(cmin, cmax, l);
860  }
861 }
862 
863 template void MSLane::fill<NamedRTree>(NamedRTree& into);
864 #ifndef NO_TRACI
865 template void MSLane::fill<RTree<MSLane*, MSLane, float, 2, TraCIServerAPI_Lane::StoringVisitor> >(RTree<MSLane*, MSLane, float, 2, TraCIServerAPI_Lane::StoringVisitor>& into);
866 #endif
867 
868 // ------ ------
869 bool
872  return true;
873  }
874  if (veh->succEdge(1) == 0) {
875  assert(veh->getBestLanes().size() > veh->getLaneIndex());
876  if (veh->getBestLanes()[veh->getLaneIndex()].bestLaneOffset == 0) {
877  return true;
878  } else {
879  return false;
880  }
881  }
882  MSLinkCont::const_iterator link = succLinkSec(*veh, 1, *this, veh->getBestLanesContinuation());
883  return (link != myLinks.end());
884 }
885 
886 
887 bool
889  bool wasInactive = myVehicles.size() == 0;
890  sort(myVehBuffer.begin(), myVehBuffer.end(), vehicle_position_sorter());
891  for (std::vector<MSVehicle*>::const_iterator i = myVehBuffer.begin(); i != myVehBuffer.end(); ++i) {
892  MSVehicle* veh = *i;
893  myVehicles.insert(myVehicles.begin(), veh);
896  }
897  myVehBuffer.clear();
898  return wasInactive && myVehicles.size() != 0;
899 }
900 
901 
902 bool
903 MSLane::isLinkEnd(MSLinkCont::const_iterator& i) const {
904  return i == myLinks.end();
905 }
906 
907 
908 bool
909 MSLane::isLinkEnd(MSLinkCont::iterator& i) {
910  return i == myLinks.end();
911 }
912 
913 
914 MSVehicle*
916  if (myVehicles.size() == 0) {
917  return 0;
918  }
919  return *myVehicles.begin();
920 }
921 
922 
923 const MSVehicle*
925  if (myVehicles.size() == 0) {
926  return 0;
927  }
928  return *(myVehicles.end() - 1);
929 }
930 
931 
932 MSLinkCont::const_iterator
933 MSLane::succLinkSec(const SUMOVehicle& veh, unsigned int nRouteSuccs,
934  const MSLane& succLinkSource, const std::vector<MSLane*>& conts) const {
935  const MSEdge* nRouteEdge = veh.succEdge(nRouteSuccs);
936  // check whether the vehicle tried to look beyond its route
937  if (nRouteEdge == 0) {
938  // return end (no succeeding link) if so
939  return succLinkSource.myLinks.end();
940  }
941  // if we are on an internal lane there should only be one link and it must be allowed
942  if (succLinkSource.getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL) {
943  assert(succLinkSource.myLinks.size() == 1);
944  assert(succLinkSource.myLinks[0]->getLane()->allowsVehicleClass(veh.getVehicleType().getVehicleClass()));
945  return succLinkSource.myLinks.begin();
946  }
947  // a link may be used if
948  // 1) there is a destination lane ((*link)->getLane()!=0)
949  // 2) the destination lane belongs to the next edge in route ((*link)->getLane()->myEdge == nRouteEdge)
950  // 3) the destination lane allows the vehicle's class ((*link)->getLane()->allowsVehicleClass(veh.getVehicleClass()))
951 
952  // there should be a link which leads to the next desired lane our route in "conts" (built in "getBestLanes")
953  // "conts" stores the best continuations of our current lane
954  // we should never return an arbitrary link since this may cause collisions
955  MSLinkCont::const_iterator link;
956  if (nRouteSuccs < conts.size()) {
957  // we go through the links in our list and return the matching one
958  for (link = succLinkSource.myLinks.begin(); link != succLinkSource.myLinks.end(); ++link) {
959  if ((*link)->getLane() != 0 && (*link)->getLane()->myEdge == nRouteEdge && (*link)->getLane()->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
960  // we should use the link if it connects us to the best lane
961  if ((*link)->getLane() == conts[nRouteSuccs]) {
962  return link;
963  }
964  }
965  }
966  } else {
967  // the source lane is a dead end (no continuations exist)
968  return succLinkSource.myLinks.end();
969  }
970  // the only case where this should happen is for a disconnected route (deliberately ignored)
971 #ifdef _DEBUG
972  WRITE_WARNING("Could not find connection between '" + succLinkSource.getID() + "' and '" + conts[nRouteSuccs]->getID() +
973  "' for vehicle '" + veh.getID() + "' time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
974 #endif
975  return succLinkSource.myLinks.end();
976 }
977 
978 
979 
980 const MSLinkCont&
982  return myLinks;
983 }
984 
985 
986 void
989  myTmpVehicles.clear();
990 }
991 
992 
993 MSVehicle*
995  for (MSLane::VehCont::iterator it = myVehicles.begin(); it < myVehicles.end(); it++) {
996  if (remVehicle == *it) {
997  remVehicle->leaveLane(notification);
998  myVehicles.erase(it);
1001  break;
1002  }
1003  }
1004  return remVehicle;
1005 }
1006 
1007 
1008 MSLane*
1009 MSLane::getParallelLane(int offset) const {
1010  return myEdge->parallelLane(this, offset);
1011 }
1012 
1013 
1014 void
1016  IncomingLaneInfo ili;
1017  ili.lane = lane;
1018  ili.viaLink = viaLink;
1019  ili.length = lane->getLength();
1020  myIncomingLanes.push_back(ili);
1021 }
1022 
1023 
1024 void
1026  MSEdge* approachingEdge = &lane->getEdge();
1027  if (myApproachingLanes.find(approachingEdge) == myApproachingLanes.end()) {
1028  myApproachingLanes[approachingEdge] = std::vector<MSLane*>();
1029  }
1030  myApproachingLanes[approachingEdge].push_back(lane);
1031 }
1032 
1033 
1034 bool
1036  return myApproachingLanes.find(edge) != myApproachingLanes.end();
1037 }
1038 
1039 
1040 bool
1041 MSLane::isApproachedFrom(MSEdge* const edge, MSLane* const lane) {
1042  std::map<MSEdge*, std::vector<MSLane*> >::const_iterator i = myApproachingLanes.find(edge);
1043  if (i == myApproachingLanes.end()) {
1044  return false;
1045  }
1046  const std::vector<MSLane*>& lanes = (*i).second;
1047  return find(lanes.begin(), lanes.end(), lane) != lanes.end();
1048 }
1049 
1050 
1052 public:
1053  inline int operator()(const std::pair<const MSVehicle* , SUMOReal>& p1, const std::pair<const MSVehicle* , SUMOReal>& p2) const {
1054  return p1.second < p2.second;
1055  }
1056 };
1057 
1058 
1060  SUMOReal dist, SUMOReal backOffset, SUMOReal leaderSpeed, SUMOReal leaderMaxDecel) const {
1061  // this follows the same logic as getFollowerOnConsecutive. we do a tree
1062  // search until dist and check for the vehicle with the largest missing rear gap
1063  SUMOReal result = 0;
1064  std::set<MSLane*> visited;
1065  std::vector<MSLane::IncomingLaneInfo> newFound;
1066  std::vector<MSLane::IncomingLaneInfo> toExamine = myIncomingLanes;
1067  while (toExamine.size() != 0) {
1068  for (std::vector<MSLane::IncomingLaneInfo>::iterator i = toExamine.begin(); i != toExamine.end(); ++i) {
1069  MSLane* next = (*i).lane;
1070  if (next->getFirstVehicle() != 0) {
1071  MSVehicle* v = (MSVehicle*) next->getFirstVehicle();
1072  const SUMOReal agap = (*i).length - v->getPositionOnLane() + backOffset - v->getVehicleType().getMinGap();
1073  const SUMOReal missingRearGap = v->getCarFollowModel().getSecureGap(
1074  v->getCarFollowModel().maxNextSpeed(v->getSpeed(), v), leaderSpeed, leaderMaxDecel) - agap;
1075  result = MAX2(result, missingRearGap);
1076  } else {
1077  if ((*i).length < dist) {
1078  const std::vector<MSLane::IncomingLaneInfo>& followers = next->getIncomingLanes();
1079  for (std::vector<MSLane::IncomingLaneInfo>::const_iterator j = followers.begin(); j != followers.end(); ++j) {
1080  if (visited.find((*j).lane) == visited.end()) {
1081  visited.insert((*j).lane);
1083  ili.lane = (*j).lane;
1084  ili.length = (*j).length + (*i).length;
1085  ili.viaLink = (*j).viaLink;
1086  newFound.push_back(ili);
1087  }
1088  }
1089  }
1090  }
1091  }
1092  toExamine.clear();
1093  swap(newFound, toExamine);
1094  }
1095  return result;
1096 }
1097 
1098 
1099 std::pair<MSVehicle* const, SUMOReal>
1101  SUMOReal backOffset, SUMOReal predMaxDecel) const {
1102  // ok, a vehicle has not noticed the lane about itself;
1103  // iterate as long as necessary to search for an approaching one
1104  std::set<MSLane*> visited;
1105  std::vector<std::pair<MSVehicle*, SUMOReal> > possible;
1106  std::vector<MSLane::IncomingLaneInfo> newFound;
1107  std::vector<MSLane::IncomingLaneInfo> toExamine = myIncomingLanes;
1108  while (toExamine.size() != 0) {
1109  for (std::vector<MSLane::IncomingLaneInfo>::iterator i = toExamine.begin(); i != toExamine.end(); ++i) {
1110  /*
1111  if ((*i).viaLink->getState()==LINKSTATE_TL_RED) {
1112  continue;
1113  }
1114  */
1115  MSLane* next = (*i).lane;
1116  if (next->getFirstVehicle() != 0) {
1117  MSVehicle* v = (MSVehicle*) next->getFirstVehicle();
1118  SUMOReal agap = (*i).length - v->getPositionOnLane() + backOffset - v->getVehicleType().getMinGap();
1119  if (agap <= v->getCarFollowModel().getSecureGap(v->getCarFollowModel().maxNextSpeed(v->getSpeed(), v), leaderSpeed, predMaxDecel)) {
1120  possible.push_back(std::make_pair(v, agap));
1121  }
1122  } else {
1123  if ((*i).length + seen < dist) {
1124  const std::vector<MSLane::IncomingLaneInfo>& followers = next->getIncomingLanes();
1125  for (std::vector<MSLane::IncomingLaneInfo>::const_iterator j = followers.begin(); j != followers.end(); ++j) {
1126  if (visited.find((*j).lane) == visited.end()) {
1127  visited.insert((*j).lane);
1129  ili.lane = (*j).lane;
1130  ili.length = (*j).length + (*i).length;
1131  ili.viaLink = (*j).viaLink;
1132  newFound.push_back(ili);
1133  }
1134  }
1135  }
1136  }
1137  }
1138  toExamine.clear();
1139  swap(newFound, toExamine);
1140  }
1141  if (possible.size() == 0) {
1142  return std::pair<MSVehicle* const, SUMOReal>(static_cast<MSVehicle*>(0), -1);
1143  }
1144  sort(possible.begin(), possible.end(), by_second_sorter());
1145  return *(possible.begin());
1146 }
1147 
1148 
1149 std::pair<MSVehicle* const, SUMOReal>
1151  const std::vector<MSLane*>& bestLaneConts) const {
1152  if (seen > dist) {
1153  return std::pair<MSVehicle* const, SUMOReal>(static_cast<MSVehicle*>(0), -1);
1154  }
1155  unsigned int view = 1;
1156  // loop over following lanes
1157  const MSLane* targetLane = this;
1158  MSVehicle* leader = targetLane->getPartialOccupator();
1159  if (leader != 0) {
1160  return std::pair<MSVehicle* const, SUMOReal>(leader, seen - targetLane->getPartialOccupatorEnd() - veh.getVehicleType().getMinGap());
1161  }
1162  const MSLane* nextLane = targetLane;
1163  SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / speed);
1164  do {
1165  // get the next link used
1166  MSLinkCont::const_iterator link = targetLane->succLinkSec(veh, view, *nextLane, bestLaneConts);
1167  if (nextLane->isLinkEnd(link) || !(*link)->opened(arrivalTime, speed, speed, veh.getVehicleType().getLength(),
1168  veh.getImpatience(), veh.getCarFollowModel().getMaxDecel(), 0) || (*link)->getState() == LINKSTATE_TL_RED) {
1169  break;
1170  }
1171 #ifdef HAVE_INTERNAL_LANES
1172  // check for link leaders
1173  const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(seen, veh.getVehicleType().getMinGap());
1174  if (linkLeaders.size() > 0) {
1175  // XXX if there is more than one link leader we should return the most important
1176  // one (gap, decel) but this is hard to know at this point
1177  return linkLeaders[0];
1178  }
1179  bool nextInternal = (*link)->getViaLane() != 0;
1180 #endif
1181  nextLane = (*link)->getViaLaneOrLane();
1182  if (nextLane == 0) {
1183  break;
1184  }
1185  arrivalTime += TIME2STEPS(nextLane->getLength() / speed);
1186  MSVehicle* leader = nextLane->getLastVehicle();
1187  if (leader != 0) {
1188  return std::pair<MSVehicle* const, SUMOReal>(leader, seen + leader->getPositionOnLane() - leader->getVehicleType().getLength() - veh.getVehicleType().getMinGap());
1189  } else {
1190  leader = nextLane->getPartialOccupator();
1191  if (leader != 0) {
1192  return std::pair<MSVehicle* const, SUMOReal>(leader, seen + nextLane->getPartialOccupatorEnd() - veh.getVehicleType().getMinGap());
1193  }
1194  }
1195  if (nextLane->getVehicleMaxSpeed(&veh) < speed) {
1196  dist = veh.getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(&veh));
1197  }
1198  seen += nextLane->getLength();
1199 #ifdef HAVE_INTERNAL_LANES
1200  if (!nextInternal) {
1201  view++;
1202  }
1203 #else
1204  view++;
1205 #endif
1206  } while (seen <= dist);
1207  return std::pair<MSVehicle* const, SUMOReal>(static_cast<MSVehicle*>(0), -1);
1208 }
1209 
1210 
1211 MSLane*
1213  if (myLogicalPredecessorLane != 0) {
1214  return myLogicalPredecessorLane;
1215  }
1216  if (myLogicalPredecessorLane == 0) {
1217  std::vector<MSEdge*> pred = myEdge->getIncomingEdges();
1218  // get only those edges which connect to this lane
1219  for (std::vector<MSEdge*>::iterator i = pred.begin(); i != pred.end();) {
1220  std::vector<IncomingLaneInfo>::const_iterator j = find_if(myIncomingLanes.begin(), myIncomingLanes.end(), edge_finder(*i));
1221  if (j == myIncomingLanes.end()) {
1222  i = pred.erase(i);
1223  } else {
1224  ++i;
1225  }
1226  }
1227  // get the edge with the most connections to this lane's edge
1228  if (pred.size() != 0) {
1229  std::sort(pred.begin(), pred.end(), by_connections_to_sorter(&getEdge()));
1230  MSEdge* best = *pred.begin();
1231  std::vector<IncomingLaneInfo>::const_iterator j = find_if(myIncomingLanes.begin(), myIncomingLanes.end(), edge_finder(best));
1232  myLogicalPredecessorLane = (*j).lane;
1233  }
1234  }
1235  return myLogicalPredecessorLane;
1236 }
1237 
1238 
1239 void
1243 }
1244 
1245 
1246 void
1250 }
1251 
1252 
1253 // ------------ Current state retrieval
1254 SUMOReal
1256  SUMOReal fractions = myInlappingVehicle != 0 ? myLength - myInlappingVehicleEnd : 0;
1258  if (myVehicles.size() != 0) {
1259  MSVehicle* lastVeh = myVehicles.front();
1260  if (lastVeh->getPositionOnLane() < lastVeh->getVehicleType().getLength()) {
1261  fractions -= (lastVeh->getVehicleType().getLength() - lastVeh->getPositionOnLane());
1262  }
1263  }
1264  releaseVehicles();
1265  return (myBruttoVehicleLengthSum + fractions) / myLength;
1266 }
1267 
1268 
1269 SUMOReal
1271  SUMOReal fractions = myInlappingVehicle != 0 ? myLength - myInlappingVehicleEnd : 0;
1273  if (myVehicles.size() != 0) {
1274  MSVehicle* lastVeh = myVehicles.front();
1275  if (lastVeh->getPositionOnLane() < lastVeh->getVehicleType().getLength()) {
1276  fractions -= (lastVeh->getVehicleType().getLength() - lastVeh->getPositionOnLane());
1277  }
1278  }
1279  releaseVehicles();
1280  return (myBruttoVehicleLengthSum + fractions) / myLength;
1281 }
1282 
1283 
1284 SUMOReal
1286  return myBruttoVehicleLengthSum;
1287 }
1288 
1289 
1290 SUMOReal
1292  if (myVehicles.size() == 0) {
1293  return 0;
1294  }
1295  SUMOReal wtime = 0;
1296  for (VehCont::const_iterator i = myVehicles.begin(); i != myVehicles.end(); ++i) {
1297  wtime += (*i)->getWaitingSeconds();
1298  }
1299  return wtime;
1300 }
1301 
1302 
1303 SUMOReal
1305  if (myVehicles.size() == 0) {
1306  return myMaxSpeed;
1307  }
1308  SUMOReal v = 0;
1309  const MSLane::VehCont& vehs = getVehiclesSecure();
1310  for (VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1311  v += (*i)->getSpeed();
1312  }
1313  SUMOReal ret = v / (SUMOReal) myVehicles.size();
1314  releaseVehicles();
1315  return ret;
1316 }
1317 
1318 
1319 SUMOReal
1321  SUMOReal ret = 0;
1322  const MSLane::VehCont& vehs = getVehiclesSecure();
1323  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1324  ret += (*i)->getHBEFA_CO2Emissions();
1325  }
1326  releaseVehicles();
1327  return ret;
1328 }
1329 
1330 
1331 SUMOReal
1333  SUMOReal ret = 0;
1334  const MSLane::VehCont& vehs = getVehiclesSecure();
1335  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1336  ret += (*i)->getHBEFA_COEmissions();
1337  }
1338  releaseVehicles();
1339  return ret;
1340 }
1341 
1342 
1343 SUMOReal
1345  SUMOReal ret = 0;
1346  const MSLane::VehCont& vehs = getVehiclesSecure();
1347  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1348  ret += (*i)->getHBEFA_PMxEmissions();
1349  }
1350  releaseVehicles();
1351  return ret;
1352 }
1353 
1354 
1355 SUMOReal
1357  SUMOReal ret = 0;
1358  const MSLane::VehCont& vehs = getVehiclesSecure();
1359  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1360  ret += (*i)->getHBEFA_NOxEmissions();
1361  }
1362  releaseVehicles();
1363  return ret;
1364 }
1365 
1366 
1367 SUMOReal
1369  SUMOReal ret = 0;
1370  const MSLane::VehCont& vehs = getVehiclesSecure();
1371  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1372  ret += (*i)->getHBEFA_HCEmissions();
1373  }
1374  releaseVehicles();
1375  return ret;
1376 }
1377 
1378 
1379 SUMOReal
1381  SUMOReal ret = 0;
1382  const MSLane::VehCont& vehs = getVehiclesSecure();
1383  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1384  ret += (*i)->getHBEFA_FuelConsumption();
1385  }
1386  releaseVehicles();
1387  return ret;
1388 }
1389 
1390 
1391 SUMOReal
1393  SUMOReal ret = 0;
1394  const MSLane::VehCont& vehs = getVehiclesSecure();
1395  if (vehs.size() == 0) {
1396  releaseVehicles();
1397  return 0;
1398  }
1399  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1400  SUMOReal sv = (*i)->getHarmonoise_NoiseEmissions();
1401  ret += (SUMOReal) pow(10., (sv / 10.));
1402  }
1403  releaseVehicles();
1404  return HelpersHarmonoise::sum(ret);
1405 }
1406 
1407 
1408 bool
1410  return cmp->getPositionOnLane() >= pos;
1411 }
1412 
1413 
1414 int
1416  return v1->getPositionOnLane() > v2->getPositionOnLane();
1417 }
1418 
1420  myEdge(e),
1421  myLaneDir(e->getLanes()[0]->getShape().getBegLine().atan2PositiveAngle())
1422 { }
1423 
1424 
1425 int
1426 MSLane::by_connections_to_sorter::operator()(const MSEdge* const e1, const MSEdge* const e2) const {
1427  const std::vector<MSLane*>* ae1 = e1->allowedLanes(*myEdge);
1428  const std::vector<MSLane*>* ae2 = e2->allowedLanes(*myEdge);
1429  SUMOReal s1 = 0;
1430  if (ae1 != 0 && ae1->size() != 0) {
1431  s1 = (SUMOReal) ae1->size() + GeomHelper::getMinAngleDiff((*ae1)[0]->getShape().getBegLine().atan2PositiveAngle(), myLaneDir) / M_PI / 2.;
1432  }
1433  SUMOReal s2 = 0;
1434  if (ae2 != 0 && ae2->size() != 0) {
1435  s2 = (SUMOReal) ae2->size() + GeomHelper::getMinAngleDiff((*ae2)[0]->getShape().getBegLine().atan2PositiveAngle(), myLaneDir) / M_PI / 2.;
1436  }
1437  return s1 < s2;
1438 }
1439 
1440 
1441 void
1443  out.openTag(SUMO_TAG_LANE);
1446  out.closeTag();
1447  out.closeTag();
1448 }
1449 
1450 
1451 void
1452 MSLane::loadState(std::vector<std::string>& vehIds, MSVehicleControl& vc) {
1453  for (std::vector<std::string>::const_iterator it = vehIds.begin(); it != vehIds.end(); ++it) {
1454  MSVehicle* v = dynamic_cast<MSVehicle*>(vc.getVehicle(*it));
1455  assert(v != 0);
1456  v->getBestLanes(true, this);
1459  }
1460 }
1461 
1462 
1463 
1464 /****************************************************************************/
1465