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  myVehicleLengthSum(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  }
134  if (wasInactive) {
136  }
137 }
138 
139 
140 bool
142  SUMOReal xIn = maxPos;
143  SUMOReal vIn = mspeed;
144  SUMOReal leaderDecel;
145  veh.getBestLanes(true, this);
146  if (myVehicles.size() != 0) {
147  MSVehicle* leader = myVehicles.front();
148  xIn = leader->getPositionOnLane() - leader->getVehicleType().getLength() - veh.getVehicleType().getMinGap();
149  vIn = leader->getSpeed();
150  leaderDecel = leader->getCarFollowModel().getMaxDecel();
151  } else {
152  SUMOReal brakeGap = veh.getCarFollowModel().brakeGap(mspeed);
153  std::pair<MSVehicle* const, SUMOReal> leader = getLeaderOnConsecutive(brakeGap, 0, mspeed, veh, veh.getBestLanesContinuation(this));
154  if (leader.first != 0) {
155  xIn = getLength() + leader.second;
156  vIn = leader.first->getSpeed();
157  leaderDecel = leader.first->getCarFollowModel().getMaxDecel();
158  } else {
159  incorporateVehicle(&veh, maxPos, mspeed, myVehicles.end());
160  return true;
161  }
162  }
163  const SUMOReal vHlp = 0.5 * (vIn + mspeed);
164  SUMOReal x2 = xIn;// have seen leader length already - skCar::lCar;
165  SUMOReal x1 = x2 - 100.0;
166  SUMOReal x = 0;
167  for (int i = 0; i <= 10; i++) {
168  x = 0.5 * (x1 + x2);
169  SUMOReal vSafe = veh.getCarFollowModel().followSpeed(&veh, vHlp, xIn - x, vIn, leaderDecel);
170  if (vSafe < vHlp) {
171  x2 = x;
172  } else {
173  x1 = x;
174  }
175  }
176  if (x < minPos) {
177  return false;
178  } else if (x > maxPos) {
179  x = maxPos;
180  }
181  incorporateVehicle(&veh, x, vHlp, myVehicles.begin());
182  return true;
183 }
184 
185 
186 bool
188  SUMOReal xIn = maxPos;
189  SUMOReal vIn = mspeed;
190  veh.getBestLanes(true, this);
191  if (myVehicles.size() != 0) {
192  MSVehicle* leader = myVehicles.front();
193  xIn = leader->getPositionOnLane() - leader->getVehicleType().getLength() - veh.getVehicleType().getMinGap();
194  vIn = leader->getSpeed();
195  } else {
196  SUMOReal brakeGap = veh.getCarFollowModel().brakeGap(mspeed);
197  std::pair<MSVehicle* const, SUMOReal> leader = getLeaderOnConsecutive(brakeGap, 0, mspeed, veh, veh.getBestLanesContinuation(this));
198  if (leader.first != 0) {
199  xIn = getLength() + leader.second;
200  vIn = leader.first->getSpeed();
201  } else {
202  incorporateVehicle(&veh, maxPos, mspeed, myVehicles.end());
203  return true;
204  }
205  }
206  const SUMOReal vHlp = 0.5 * (mspeed + vIn);
207  xIn = xIn - vHlp * veh.getCarFollowModel().getHeadwayTime() - veh.getVehicleType().getMinGap();
208  if (xIn < minPos) {
209  return false;
210  } else if (xIn > maxPos) {
211  xIn = maxPos;
212  }
213  incorporateVehicle(&veh, xIn, vHlp, myVehicles.begin());
214  return true;
215 }
216 
217 
218 bool
220  if (myVehicles.size() == 0) {
221  return isInsertionSuccess(&veh, mspeed, myLength / 2, true);
222  }
223  // go through the lane, look for free positions (starting after the last vehicle)
224  MSLane::VehCont::iterator predIt = myVehicles.begin();
225  SUMOReal maxSpeed = 0;
226  SUMOReal maxPos = 0;
227  MSLane::VehCont::iterator maxIt = myVehicles.begin();
228  while (predIt != myVehicles.end()) {
229  // get leader (may be zero) and follower
230  const MSVehicle* leader = predIt != myVehicles.end() - 1 ? *(predIt + 1) : getPartialOccupator();
231  const MSVehicle* follower = *predIt;
232  SUMOReal leaderRearPos = getLength();
233  SUMOReal leaderSpeed = mspeed;
234  if (leader != 0) {
235  leaderRearPos = leader->getPositionOnLane() - leader->getVehicleType().getLength();
236  if (leader == getPartialOccupator()) {
237  leaderRearPos = getPartialOccupatorEnd();
238  }
239  leaderSpeed = leader->getSpeed();
240  }
241  const SUMOReal nettoGap = leaderRearPos - follower->getPositionOnLane() - veh.getVehicleType().getLengthWithGap();
242  if (nettoGap > 0) {
243  const SUMOReal tau = veh.getCarFollowModel().getHeadwayTime();
244  const SUMOReal tauDecel = tau * veh.getCarFollowModel().getMaxDecel();
245  const SUMOReal fSpeed = follower->getSpeed();
246  const SUMOReal lhs = nettoGap / tau + tauDecel - fSpeed - fSpeed * fSpeed / (2 * tauDecel) + leaderSpeed * leaderSpeed / (2 * tauDecel);
247  if (lhs >= sqrt(tauDecel * tauDecel + leaderSpeed * leaderSpeed)) {
248  const SUMOReal frontGap = (lhs * lhs - tauDecel * tauDecel - leaderSpeed * leaderSpeed) / (2 * veh.getCarFollowModel().getMaxDecel());
249  const SUMOReal currentMaxSpeed = lhs - tauDecel;
250  if (MIN2(currentMaxSpeed, mspeed) > maxSpeed) {
251  maxSpeed = currentMaxSpeed;
252  maxPos = leaderRearPos + frontGap;
253  maxIt = predIt + 1;
254  }
255  }
256  }
257  ++predIt;
258  }
259  if (maxSpeed > 0) {
260  incorporateVehicle(&veh, maxPos, maxSpeed, maxIt);
261  return true;
262  }
263  return false;
264 }
265 
266 
267 bool
269  MSMoveReminder::Notification notification) {
270  bool adaptableSpeed = true;
271  if (myVehicles.size() == 0) {
272  if (isInsertionSuccess(&veh, mspeed, 0, adaptableSpeed, notification)) {
273  return true;
274  }
275  } else {
276  // check whether the vehicle can be put behind the last one if there is such
277  MSVehicle* leader = myVehicles.back();
278  SUMOReal leaderPos = leader->getPositionOnLane() - leader->getVehicleType().getLength();
279  SUMOReal speed = mspeed;
280  if (adaptableSpeed) {
281  speed = leader->getSpeed();
282  }
283  SUMOReal frontGapNeeded = veh.getCarFollowModel().getSecureGap(speed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()) + veh.getVehicleType().getMinGap();
284  if (leaderPos - frontGapNeeded >= 0) {
285  SUMOReal tspeed = MIN2(veh.getCarFollowModel().followSpeed(&veh, mspeed, frontGapNeeded, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()), mspeed);
286  // check whether we can insert our vehicle behind the last vehicle on the lane
287  if (isInsertionSuccess(&veh, tspeed, 0, adaptableSpeed, notification)) {
288  return true;
289  }
290  }
291  }
292  // go through the lane, look for free positions (starting after the last vehicle)
293  MSLane::VehCont::iterator predIt = myVehicles.begin();
294  while (predIt != myVehicles.end()) {
295  // get leader (may be zero) and follower
296  const MSVehicle* leader = predIt != myVehicles.end() - 1 ? *(predIt + 1) : getPartialOccupator();
297  const MSVehicle* follower = *predIt;
298 
299  // patch speed if allowed
300  SUMOReal speed = mspeed;
301  if (adaptableSpeed && leader != 0) {
302  speed = MIN2(leader->getSpeed(), mspeed);
303  }
304 
305  // compute the space needed to not collide with leader
306  SUMOReal frontMax = getLength();
307  if (leader != 0) {
308  SUMOReal leaderRearPos = leader->getPositionOnLane() - leader->getVehicleType().getLength();
309  if (leader == getPartialOccupator()) {
310  leaderRearPos = getPartialOccupatorEnd();
311  }
312  SUMOReal frontGapNeeded = veh.getCarFollowModel().getSecureGap(speed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()) + veh.getVehicleType().getMinGap();
313  frontMax = leaderRearPos - frontGapNeeded;
314  }
315  // compute the space needed to not let the follower collide
316  const SUMOReal followPos = follower->getPositionOnLane() + follower->getVehicleType().getMinGap();
317  const SUMOReal backGapNeeded = follower->getCarFollowModel().getSecureGap(follower->getSpeed(), veh.getSpeed(), veh.getCarFollowModel().getMaxDecel());
318  const SUMOReal backMin = followPos + backGapNeeded + veh.getVehicleType().getLength();
319 
320  // check whether there is enough room (given some extra space for rounding errors)
321  if (frontMax > 0 && backMin + POSITION_EPS < frontMax) {
322  // try to insert vehicle (should be always ok)
323  if (isInsertionSuccess(&veh, speed, backMin + POSITION_EPS, adaptableSpeed, notification)) {
324  return true;
325  }
326  }
327  ++predIt;
328  }
329  // first check at lane's begin
330  return false;
331 }
332 
333 
334 bool
336  SUMOReal pos = 0;
337  SUMOReal speed = 0;
338  bool patchSpeed = true; // whether the speed shall be adapted to infrastructure/traffic in front
339 
340  // determine the speed
341  const SUMOVehicleParameter& pars = veh.getParameter();
342  switch (pars.departSpeedProcedure) {
343  case DEPART_SPEED_GIVEN:
344  speed = pars.departSpeed;
345  patchSpeed = false;
346  break;
347  case DEPART_SPEED_RANDOM:
348  speed = RandHelper::rand(MIN2(veh.getMaxSpeed(), getVehicleMaxSpeed(&veh)));
349  patchSpeed = true; // @todo check
350  break;
351  case DEPART_SPEED_MAX:
352  speed = MIN2(veh.getMaxSpeed(), getVehicleMaxSpeed(&veh));
353  patchSpeed = true; // @todo check
354  break;
356  default:
357  // speed = 0 was set before
358  patchSpeed = false; // @todo check
359  break;
360  }
361 
362  // determine the position
363  switch (pars.departPosProcedure) {
364  case DEPART_POS_GIVEN:
365  pos = pars.departPos;
366  if (pos < 0.) {
367  pos += myLength;
368  }
369  break;
370  case DEPART_POS_RANDOM:
371  pos = RandHelper::rand(getLength());
372  break;
373  case DEPART_POS_RANDOM_FREE: {
374  for (unsigned int i = 0; i < 10; i++) {
375  // we will try some random positions ...
376  pos = RandHelper::rand(getLength());
377  if (isInsertionSuccess(&veh, speed, pos, patchSpeed)) {
378  return true;
379  }
380  }
381  // ... and if that doesn't work, we put the vehicle to the free position
382  return freeInsertion(veh, speed);
383  }
384  break;
385  case DEPART_POS_FREE:
386  return freeInsertion(veh, speed);
388  return pWagSimpleInsertion(veh, speed, getLength(), 0.0);
390  return pWagGenericInsertion(veh, speed, getLength(), 0.0);
392  return maxSpeedGapInsertion(veh, speed);
393  case DEPART_POS_BASE:
394  case DEPART_POS_DEFAULT:
395  default:
396  pos = MIN2(static_cast<SUMOReal>(veh.getVehicleType().getLength() + POSITION_EPS), myLength);
397  break;
398  }
399  // try to insert
400  return isInsertionSuccess(&veh, speed, pos, patchSpeed);
401 }
402 
403 
404 bool
406  SUMOReal speed, SUMOReal pos, bool patchSpeed,
407  MSMoveReminder::Notification notification) {
408  if (pos < 0 || pos > myLength) {
409  // we may not start there
410  WRITE_WARNING("Invalid departPos " + toString(pos) + " given for vehicle '" +
411  aVehicle->getID() + "'. Inserting at lane end instead.");
412  pos = myLength;
413  }
414  aVehicle->getBestLanes(true, this);
415  const MSCFModel& cfModel = aVehicle->getCarFollowModel();
416  const std::vector<MSLane*>& bestLaneConts = aVehicle->getBestLanesContinuation(this);
417  std::vector<MSLane*>::const_iterator ri = bestLaneConts.begin();
418  SUMOReal seen = getLength() - pos;
419  SUMOReal dist = cfModel.brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
420  const MSRoute& r = aVehicle->getRoute();
421  MSRouteIterator ce = r.begin();
422  unsigned int nRouteSuccs = 1;
423  MSLane* currentLane = this;
424  MSLane* nextLane = this;
425  SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / speed);
426  while (seen < dist && ri != bestLaneConts.end()) {
427  // get the next link used...
428  MSLinkCont::const_iterator link = currentLane->succLinkSec(*aVehicle, nRouteSuccs, *currentLane, bestLaneConts);
429  if (currentLane->isLinkEnd(link)) {
430  if (&currentLane->getEdge() == r.getLastEdge()) {
431  // reached the end of the route
433  SUMOReal nspeed = cfModel.freeSpeed(aVehicle, speed, seen, aVehicle->getParameter().arrivalSpeed);
434  if (nspeed < speed) {
435  if (patchSpeed) {
436  speed = MIN2(nspeed, speed);
437  dist = cfModel.brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
438  } else {
439  // we may not drive with the given velocity - we cannot match the specified arrival speed
440  WRITE_ERROR("Vehicle '" + aVehicle->getID() + "' will not be able to depart using the given velocity due (arrival speed too low)!");
442  return false;
443  }
444  }
445  }
446  } else {
447  // lane does not continue
448  SUMOReal nspeed = cfModel.stopSpeed(aVehicle, speed, seen);
449  if (nspeed < speed) {
450  if (patchSpeed) {
451  speed = MIN2(nspeed, speed);
452  dist = cfModel.brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
453  } else {
454  // we may not drive with the given velocity - we cannot stop at the junction
455  WRITE_ERROR("Vehicle '" + aVehicle->getID() + "' will not be able to depart using the given velocity (junction too close)!");
457  return false;
458  }
459  }
460  }
461  break;
462  }
463  if (!(*link)->opened(arrivalTime, speed, speed, aVehicle->getVehicleType().getLength(), aVehicle->getImpatience(), cfModel.getMaxDecel(), 0)
464  || !(*link)->havePriority()) {
465  // have to stop at junction
466  SUMOReal nspeed = cfModel.stopSpeed(aVehicle, speed, seen);
467  if (nspeed < speed) {
468  if (patchSpeed) {
469  speed = MIN2(nspeed, speed);
470  dist = cfModel.brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
471  } else {
472  // we may not drive with the given velocity - we cannot stop at the junction in time
473  const LinkState state = (*link)->getState();
474  if (state == LINKSTATE_MINOR
475  || state == LINKSTATE_EQUAL
476  || state == LINKSTATE_STOP
477  || state == LINKSTATE_ALLWAY_STOP) {
478  // no sense in trying later
479  WRITE_ERROR("Vehicle '" + aVehicle->getID() + "' will not be able to depart using the given velocity (unpriorised junction too close)!");
481  }
482  return false;
483  }
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 (nspeed < speed) {
509  if (patchSpeed) {
510  speed = MIN2(nspeed, speed);
511  dist = cfModel.brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
512  } else {
513  // we may not drive with the given velocity - we crash into the leader
514  return false;
515  }
516  }
517  }
518  // check next lane's maximum velocity
519  const SUMOReal nspeed = nextLane->getVehicleMaxSpeed(aVehicle);
520  if (nspeed < speed) {
521  // patch speed if needed
522  if (patchSpeed) {
523  speed = MIN2(cfModel.freeSpeed(aVehicle, speed, seen, nspeed), speed);
524  dist = cfModel.brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
525  } else {
526  // we may not drive with the given velocity - we would be too fast on the next lane
527  WRITE_ERROR("Vehicle '" + aVehicle->getID() + "' will not be able to depart using the given velocity (slow lane ahead)!");
529  return false;
530  }
531  }
532  // check traffic on next junction
533  // we cannot use (*link)->opened because a vehicle without priority
534  // may already be comitted to blocking the link and unable to stop
535  const SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / speed);
536  const SUMOTime leaveTime = arrivalTime + TIME2STEPS((*link)->getLength() * speed);
537  if ((*link)->hasApproachingFoe(arrivalTime, leaveTime, speed, cfModel.getMaxDecel())) {
538  SUMOReal nspeed = cfModel.followSpeed(aVehicle, speed, seen, 0, 0);
539  if (nspeed < speed) {
540  if (patchSpeed) {
541  speed = MIN2(nspeed, speed);
542  dist = cfModel.brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
543  } else {
544  // we may not drive with the given velocity - we crash at the junction
545  return false;
546  }
547  }
548  }
549  seen += nextLane->getLength();
550  currentLane = nextLane;
551 #ifdef HAVE_INTERNAL_LANES
552  if ((*link)->getViaLane() == 0) {
553 #else
554  if (true) {
555 #endif
556  nRouteSuccs++;
557  ++ce;
558  ++ri;
559  }
560  }
561  }
562 
563  // get the pointer to the vehicle next in front of the given position
564  MSLane::VehCont::iterator predIt = find_if(myVehicles.begin(), myVehicles.end(), bind2nd(VehPosition(), pos));
565  if (predIt != myVehicles.end()) {
566  // ok, there is one (a leader)
567  MSVehicle* leader = *predIt;
568  SUMOReal frontGapNeeded = cfModel.getSecureGap(speed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
569  SUMOReal gap = MSVehicle::gap(leader->getPositionOnLane(), leader->getVehicleType().getLength(), pos + aVehicle->getVehicleType().getMinGap());
570  if (gap < frontGapNeeded) {
571  // too close to the leader on this lane
572  return false;
573  }
574  }
575 
576  // check back vehicle
577  if (predIt != myVehicles.begin()) {
578  // there is direct follower on this lane
579  MSVehicle* follower = *(predIt - 1);
580  SUMOReal backGapNeeded = follower->getCarFollowModel().getSecureGap(follower->getSpeed(), aVehicle->getSpeed(), cfModel.getMaxDecel());
581  SUMOReal gap = MSVehicle::gap(pos, aVehicle->getVehicleType().getLength(), follower->getPositionOnLane() + follower->getVehicleType().getMinGap());
582  if (gap < backGapNeeded) {
583  // too close to the follower on this lane
584  return false;
585  }
586  } else {
587  // check approaching vehicles to prevent rear-end collisions
588  // to compute an uper bound on the look-back distance we need
589  // the chosenSpeedFactor, minGap and maxDeceleration of approaching vehicles
590  // since we do not know these we use the values from the vehicle to be inserted
591  // and add a safety factor
592  const SUMOReal dist = 2 * (aVehicle->getCarFollowModel().brakeGap(myMaxSpeed) + aVehicle->getVehicleType().getMinGap());
593  const SUMOReal backOffset = pos - aVehicle->getVehicleType().getLength();
594  const SUMOReal missingRearGap = getMissingRearGap(dist, backOffset, speed, aVehicle->getCarFollowModel().getMaxDecel());
595  if (missingRearGap > 0) {
596  // too close to a follower
597  const SUMOReal neededStartPos = pos + missingRearGap;
598  if (myVehicles.size() == 0 && notification == MSMoveReminder::NOTIFICATION_TELEPORT && neededStartPos <= myLength) {
599  // shift starting positiong as needed entering from teleport
600  pos = neededStartPos;
601  } else {
602  return false;
603  }
604  }
605  }
606  // may got negative while adaptation
607  if (speed < 0) {
608  return false;
609  }
610  // enter
611  incorporateVehicle(aVehicle, pos, speed, predIt, notification);
612  return true;
613 }
614 
615 
616 void
618  incorporateVehicle(veh, pos, veh->getSpeed(), find_if(myVehicles.begin(), myVehicles.end(), bind2nd(VehPosition(), pos)));
619 }
620 
621 
622 // ------ Handling vehicles lapping into lanes ------
623 SUMOReal
625  myInlappingVehicle = v;
626  if (leftVehicleLength > myLength) {
628  } else {
629  myInlappingVehicleEnd = myLength - leftVehicleLength;
630  }
631  return myLength;
632 }
633 
634 
635 void
637  if (v == myInlappingVehicle) {
638  myInlappingVehicleEnd = 10000;
639  }
640  myInlappingVehicle = 0;
641 }
642 
643 
644 std::pair<MSVehicle*, SUMOReal>
646  if (myVehicles.size() != 0) {
647  // the last vehicle is the one in scheduled by this lane
648  MSVehicle* last = *myVehicles.begin();
649  const SUMOReal pos = last->getPositionOnLane() - last->getVehicleType().getLength();
650  return std::make_pair(last, pos);
651  }
652  if (myInlappingVehicle != 0) {
653  // the last one is a vehicle extending into this lane
654  return std::make_pair(myInlappingVehicle, myInlappingVehicleEnd);
655  }
656  return std::make_pair<MSVehicle*, SUMOReal>(0, 0);
657 }
658 
659 
660 // ------ ------
661 void
663  assert(myVehicles.size() != 0);
664  SUMOReal cumulatedVehLength = 0.;
665  const MSVehicle* pred = getPartialOccupator();
666  for (VehCont::reverse_iterator veh = myVehicles.rbegin(); veh != myVehicles.rend(); ++veh) {
667  if ((*veh)->getLane() == this) {
668  (*veh)->planMove(t, pred, cumulatedVehLength);
669  }
670  pred = *veh;
671  cumulatedVehLength += pred->getVehicleType().getLengthWithGap();
672  }
673 }
674 
675 
676 void
677 MSLane::detectCollisions(SUMOTime timestep, int stage) {
678  if (myVehicles.size() < 2) {
679  return;
680  }
681 
682  VehCont::iterator lastVeh = myVehicles.end() - 1;
683  for (VehCont::iterator veh = myVehicles.begin(); veh != lastVeh;) {
684  VehCont::iterator pred = veh + 1;
685  if ((*veh)->hasInfluencer() && (*veh)->getInfluencer().isVTDControlled()) {
686  ++veh;
687  continue;
688  }
689  if ((*pred)->hasInfluencer() && (*pred)->getInfluencer().isVTDControlled()) {
690  ++veh;
691  continue;
692  }
693  SUMOReal gap = (*pred)->getPositionOnLane() - (*pred)->getVehicleType().getLength() - (*veh)->getPositionOnLane() - (*veh)->getVehicleType().getMinGap();
694  if (gap < -0.001) {
695  MSVehicle* vehV = *veh;
696  if (vehV->getLane() == this) {
697  WRITE_WARNING("Teleporting vehicle '" + vehV->getID() + "'; collision with '"
698  + (*pred)->getID() + "', lane='" + getID() + "', gap=" + toString(gap)
699  + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + " stage=" + toString(stage) + ".");
702  MSVehicleTransfer::getInstance()->addVeh(timestep, vehV);
703  veh = myVehicles.erase(veh); // remove current vehicle
704  lastVeh = myVehicles.end() - 1;
705  if (veh == myVehicles.end()) {
706  break;
707  }
708  } else {
709  WRITE_WARNING("Shadow of vehicle '" + vehV->getID() + "'; collision with '"
710  + (*pred)->getID() + "', lane='" + getID() + "', gap=" + toString(gap)
711  + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + " stage=" + toString(stage) + ".");
712  veh = myVehicles.erase(veh); // remove current vehicle
713  lastVeh = myVehicles.end() - 1;
715  if (veh == myVehicles.end()) {
716  break;
717  }
718  }
719  } else {
720  ++veh;
721  }
722  }
723 }
724 
725 
726 bool
727 MSLane::executeMovements(SUMOTime t, std::vector<MSLane*>& into) {
728  for (VehCont::iterator i = myVehicles.begin(); i != myVehicles.end();) {
729  MSVehicle* veh = *i;
730  if (veh->getLane() != this || veh->getLaneChangeModel().alreadyMoved()) {
731  // this is the shadow during a continuous lane change
732  ++i;
733  continue;
734  }
735  // length is needed later when the vehicle may not exist anymore
736  const SUMOReal length = veh->getVehicleType().getLengthWithGap();
737  bool moved = veh->executeMove();
738  MSLane* target = veh->getLane();
739 #ifndef NO_TRACI
740  bool vtdControlled = veh->hasInfluencer() && veh->getInfluencer().isVTDControlled();
741  if (veh->hasArrived() && !vtdControlled) {
742 #else
743  if (veh->hasArrived()) {
744 #endif
745  // vehicle has reached its arrival position
748  } else if (target != 0 && moved) {
749  if (target->getEdge().isVaporizing()) {
750  // vehicle has reached a vaporizing edge
753  } else {
754  // vehicle has entered a new lane (leaveLane was already called in MSVehicle::executeMove)
755  target->myVehBuffer.push_back(veh);
756  SUMOReal pspeed = veh->getSpeed();
757  SUMOReal oldPos = veh->getPositionOnLane() - SPEED2DIST(veh->getSpeed());
758  veh->workOnMoveReminders(oldPos, veh->getPositionOnLane(), pspeed);
759  into.push_back(target);
760  if (veh->getLaneChangeModel().isChangingLanes()) {
761  MSLane* shadowLane = veh->getLaneChangeModel().getShadowLane();
762  if (shadowLane != 0) {
763  into.push_back(shadowLane);
764  shadowLane->myVehBuffer.push_back(veh);
765  }
766  }
767  }
768  } else if (veh->isParking()) {
769  // vehicle started to park
772  } else if (veh->getPositionOnLane() > getLength()) {
773  // for any reasons the vehicle is beyond its lane... error
774  WRITE_WARNING("Teleporting vehicle '" + veh->getID() + "'; beyond lane (2), targetLane='" + getID() + "', time=" +
775  time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
778  } else {
779  ++i;
780  continue;
781  }
782  myVehicleLengthSum -= length;
783  i = myVehicles.erase(i);
784  }
785  if (myVehicles.size() > 0) {
787  MSVehicle* last = myVehicles.back();
788  bool r1 = MSGlobals::gTimeToGridlock > 0 && !last->isStopped() && last->getWaitingTime() > MSGlobals::gTimeToGridlock;
789  bool r2 = MSGlobals::gTimeToGridlockHighways > 0 && !last->isStopped() && last->getWaitingTime() > MSGlobals::gTimeToGridlockHighways && last->getLane()->getSpeedLimit() > 69. / 3.6 && !last->getLane()->appropriate(last);
790  if (r1 || r2) {
791  MSVehicle* veh = *(myVehicles.end() - 1);
793  myVehicles.erase(myVehicles.end() - 1);
794  WRITE_WARNING("Teleporting vehicle '" + veh->getID() + "'; waited too long"
795  + (r2 ? " on highway" : "")
796  + ", lane='" + getID() + "', time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
799  }
800  }
801  }
802  return myVehicles.size() == 0;
803 }
804 
805 
806 bool
807 MSLane::dictionary(std::string id, MSLane* ptr) {
808  DictType::iterator it = myDict.find(id);
809  if (it == myDict.end()) {
810  // id not in myDict.
811  myDict.insert(DictType::value_type(id, ptr));
812  return true;
813  }
814  return false;
815 }
816 
817 
818 MSLane*
819 MSLane::dictionary(std::string id) {
820  DictType::iterator it = myDict.find(id);
821  if (it == myDict.end()) {
822  // id not in myDict.
823  return 0;
824  }
825  return it->second;
826 }
827 
828 
829 void
831  for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
832  delete(*i).second;
833  }
834  myDict.clear();
835 }
836 
837 
838 void
839 MSLane::insertIDs(std::vector<std::string>& into) {
840  for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
841  into.push_back((*i).first);
842  }
843 }
844 
845 
846 bool
849  return true;
850  }
851  MSLinkCont::const_iterator link = succLinkSec(*veh, 1, *this, veh->getBestLanesContinuation());
852  return (link != myLinks.end());
853 }
854 
855 
856 bool
858  bool wasInactive = myVehicles.size() == 0;
859  sort(myVehBuffer.begin(), myVehBuffer.end(), vehicle_position_sorter());
860  for (std::vector<MSVehicle*>::const_iterator i = myVehBuffer.begin(); i != myVehBuffer.end(); ++i) {
861  MSVehicle* veh = *i;
862  myVehicles.insert(myVehicles.begin(), veh);
864  }
865  myVehBuffer.clear();
866  return wasInactive && myVehicles.size() != 0;
867 }
868 
869 
870 bool
871 MSLane::isLinkEnd(MSLinkCont::const_iterator& i) const {
872  return i == myLinks.end();
873 }
874 
875 
876 bool
877 MSLane::isLinkEnd(MSLinkCont::iterator& i) {
878  return i == myLinks.end();
879 }
880 
881 
882 MSVehicle*
884  if (myVehicles.size() == 0) {
885  return 0;
886  }
887  return *myVehicles.begin();
888 }
889 
890 
891 const MSVehicle*
893  if (myVehicles.size() == 0) {
894  return 0;
895  }
896  return *(myVehicles.end() - 1);
897 }
898 
899 
900 MSLinkCont::const_iterator
901 MSLane::succLinkSec(const SUMOVehicle& veh, unsigned int nRouteSuccs,
902  const MSLane& succLinkSource, const std::vector<MSLane*>& conts) const {
903  const MSEdge* nRouteEdge = veh.succEdge(nRouteSuccs);
904  // check whether the vehicle tried to look beyond its route
905  if (nRouteEdge == 0) {
906  // return end (no succeeding link) if so
907  return succLinkSource.myLinks.end();
908  }
909  // if we are on an internal lane there should only be one link and it must be allowed
910  if (succLinkSource.getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL) {
911  assert(succLinkSource.myLinks.size() == 1);
912  assert(succLinkSource.myLinks[0]->getLane()->allowsVehicleClass(veh.getVehicleType().getVehicleClass()));
913  return succLinkSource.myLinks.begin();
914  }
915  // a link may be used if
916  // 1) there is a destination lane ((*link)->getLane()!=0)
917  // 2) the destination lane belongs to the next edge in route ((*link)->getLane()->myEdge == nRouteEdge)
918  // 3) the destination lane allows the vehicle's class ((*link)->getLane()->allowsVehicleClass(veh.getVehicleClass()))
919 
920  // there should be a link which leads to the next desired lane our route in "conts" (built in "getBestLanes")
921  // "conts" stores the best continuations of our current lane
922  // we should never return an arbitrary link since this may cause collisions
923  MSLinkCont::const_iterator link;
924  if (nRouteSuccs < conts.size()) {
925  // we go through the links in our list and return the matching one
926  for (link = succLinkSource.myLinks.begin(); link != succLinkSource.myLinks.end(); ++link) {
927  if ((*link)->getLane() != 0 && (*link)->getLane()->myEdge == nRouteEdge && (*link)->getLane()->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
928  // we should use the link if it connects us to the best lane
929  if ((*link)->getLane() == conts[nRouteSuccs]) {
930  return link;
931  }
932  }
933  }
934  } else {
935  // the source lane is a dead end (no continuations exist)
936  return succLinkSource.myLinks.end();
937  }
938  // the only case where this should happen is for a disconnected route (deliberately ignored)
939  return succLinkSource.myLinks.end();
940 }
941 
942 
943 
944 const MSLinkCont&
946  return myLinks;
947 }
948 
949 
950 void
953  myTmpVehicles.clear();
954 }
955 
956 
957 MSVehicle*
959  for (MSLane::VehCont::iterator it = myVehicles.begin(); it < myVehicles.end(); it++) {
960  if (remVehicle == *it) {
961  remVehicle->leaveLane(notification);
962  myVehicles.erase(it);
964  break;
965  }
966  }
967  return remVehicle;
968 }
969 
970 
971 MSLane*
972 MSLane::getParallelLane(int offset) const {
973  return myEdge->parallelLane(this, offset);
974 }
975 
976 
977 void
979  IncomingLaneInfo ili;
980  ili.lane = lane;
981  ili.viaLink = viaLink;
982  ili.length = lane->getLength();
983  myIncomingLanes.push_back(ili);
984 }
985 
986 
987 void
989  MSEdge* approachingEdge = &lane->getEdge();
990  if (myApproachingLanes.find(approachingEdge) == myApproachingLanes.end()) {
991  myApproachingLanes[approachingEdge] = std::vector<MSLane*>();
992  }
993  myApproachingLanes[approachingEdge].push_back(lane);
994 }
995 
996 
997 bool
999  return myApproachingLanes.find(edge) != myApproachingLanes.end();
1000 }
1001 
1002 
1003 bool
1004 MSLane::isApproachedFrom(MSEdge* const edge, MSLane* const lane) {
1005  std::map<MSEdge*, std::vector<MSLane*> >::const_iterator i = myApproachingLanes.find(edge);
1006  if (i == myApproachingLanes.end()) {
1007  return false;
1008  }
1009  const std::vector<MSLane*>& lanes = (*i).second;
1010  return find(lanes.begin(), lanes.end(), lane) != lanes.end();
1011 }
1012 
1013 
1015 public:
1016  inline int operator()(const std::pair<const MSVehicle* , SUMOReal>& p1, const std::pair<const MSVehicle* , SUMOReal>& p2) const {
1017  return p1.second < p2.second;
1018  }
1019 };
1020 
1021 
1023  SUMOReal dist, SUMOReal backOffset, SUMOReal leaderSpeed, SUMOReal leaderMaxDecel) const {
1024  // this follows the same logic as getFollowerOnConsecutive. we do a tree
1025  // search until dist and check for the vehicle with the largest missing rear gap
1026  SUMOReal result = 0;
1027  std::set<MSLane*> visited;
1028  std::vector<MSLane::IncomingLaneInfo> newFound;
1029  std::vector<MSLane::IncomingLaneInfo> toExamine = myIncomingLanes;
1030  while (toExamine.size() != 0) {
1031  for (std::vector<MSLane::IncomingLaneInfo>::iterator i = toExamine.begin(); i != toExamine.end(); ++i) {
1032  MSLane* next = (*i).lane;
1033  if (next->getFirstVehicle() != 0) {
1034  MSVehicle* v = (MSVehicle*) next->getFirstVehicle();
1035  const SUMOReal agap = (*i).length - v->getPositionOnLane() + backOffset - v->getVehicleType().getMinGap();
1036  const SUMOReal missingRearGap = v->getCarFollowModel().getSecureGap(
1037  v->getCarFollowModel().maxNextSpeed(v->getSpeed(), v), leaderSpeed, leaderMaxDecel) - agap;
1038  result = MAX2(result, missingRearGap);
1039  } else {
1040  if ((*i).length < dist) {
1041  const std::vector<MSLane::IncomingLaneInfo>& followers = next->getIncomingLanes();
1042  for (std::vector<MSLane::IncomingLaneInfo>::const_iterator j = followers.begin(); j != followers.end(); ++j) {
1043  if (visited.find((*j).lane) == visited.end()) {
1044  visited.insert((*j).lane);
1046  ili.lane = (*j).lane;
1047  ili.length = (*j).length + (*i).length;
1048  ili.viaLink = (*j).viaLink;
1049  newFound.push_back(ili);
1050  }
1051  }
1052  }
1053  }
1054  }
1055  toExamine.clear();
1056  swap(newFound, toExamine);
1057  }
1058  return result;
1059 }
1060 
1061 
1062 std::pair<MSVehicle* const, SUMOReal>
1064  SUMOReal backOffset, SUMOReal predMaxDecel) const {
1065  // ok, a vehicle has not noticed the lane about itself;
1066  // iterate as long as necessary to search for an approaching one
1067  std::set<MSLane*> visited;
1068  std::vector<std::pair<MSVehicle*, SUMOReal> > possible;
1069  std::vector<MSLane::IncomingLaneInfo> newFound;
1070  std::vector<MSLane::IncomingLaneInfo> toExamine = myIncomingLanes;
1071  while (toExamine.size() != 0) {
1072  for (std::vector<MSLane::IncomingLaneInfo>::iterator i = toExamine.begin(); i != toExamine.end(); ++i) {
1073  /*
1074  if ((*i).viaLink->getState()==LINKSTATE_TL_RED) {
1075  continue;
1076  }
1077  */
1078  MSLane* next = (*i).lane;
1079  if (next->getFirstVehicle() != 0) {
1080  MSVehicle* v = (MSVehicle*) next->getFirstVehicle();
1081  SUMOReal agap = (*i).length - v->getPositionOnLane() + backOffset - v->getVehicleType().getMinGap();
1082  if (agap <= v->getCarFollowModel().getSecureGap(v->getCarFollowModel().maxNextSpeed(v->getSpeed(), v), leaderSpeed, predMaxDecel)) {
1083  possible.push_back(std::make_pair(v, agap));
1084  }
1085  } else {
1086  if ((*i).length + seen < dist) {
1087  const std::vector<MSLane::IncomingLaneInfo>& followers = next->getIncomingLanes();
1088  for (std::vector<MSLane::IncomingLaneInfo>::const_iterator j = followers.begin(); j != followers.end(); ++j) {
1089  if (visited.find((*j).lane) == visited.end()) {
1090  visited.insert((*j).lane);
1092  ili.lane = (*j).lane;
1093  ili.length = (*j).length + (*i).length;
1094  ili.viaLink = (*j).viaLink;
1095  newFound.push_back(ili);
1096  }
1097  }
1098  }
1099  }
1100  }
1101  toExamine.clear();
1102  swap(newFound, toExamine);
1103  }
1104  if (possible.size() == 0) {
1105  return std::pair<MSVehicle* const, SUMOReal>(static_cast<MSVehicle*>(0), -1);
1106  }
1107  sort(possible.begin(), possible.end(), by_second_sorter());
1108  return *(possible.begin());
1109 }
1110 
1111 
1112 std::pair<MSVehicle* const, SUMOReal>
1114  const std::vector<MSLane*>& bestLaneConts) const {
1115  if (seen > dist) {
1116  return std::pair<MSVehicle* const, SUMOReal>(static_cast<MSVehicle*>(0), -1);
1117  }
1118  unsigned int view = 1;
1119  // loop over following lanes
1120  const MSLane* targetLane = this;
1121  MSVehicle* leader = targetLane->getPartialOccupator();
1122  if (leader != 0) {
1123  return std::pair<MSVehicle* const, SUMOReal>(leader, seen - targetLane->getPartialOccupatorEnd() - veh.getVehicleType().getMinGap());
1124  }
1125  const MSLane* nextLane = targetLane;
1126  SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / speed);
1127  do {
1128  // get the next link used
1129  MSLinkCont::const_iterator link = targetLane->succLinkSec(veh, view, *nextLane, bestLaneConts);
1130  if (nextLane->isLinkEnd(link) || !(*link)->opened(arrivalTime, speed, speed, veh.getVehicleType().getLength(),
1131  veh.getImpatience(), veh.getCarFollowModel().getMaxDecel(), 0) || (*link)->getState() == LINKSTATE_TL_RED) {
1132  break;
1133  }
1134 #ifdef HAVE_INTERNAL_LANES
1135  // check for link leaders
1136  const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(seen - veh.getVehicleType().getMinGap());
1137  if (linkLeaders.size() > 0) {
1138  // XXX if there is more than one link leader we should return the most important
1139  // one (gap, decel) but this is hard to know at this point
1140  return linkLeaders[0];
1141  }
1142  bool nextInternal = (*link)->getViaLane() != 0;
1143 #endif
1144  nextLane = (*link)->getViaLaneOrLane();
1145  if (nextLane == 0) {
1146  break;
1147  }
1148  arrivalTime += TIME2STEPS(nextLane->getLength() / speed);
1149  MSVehicle* leader = nextLane->getLastVehicle();
1150  if (leader != 0) {
1151  return std::pair<MSVehicle* const, SUMOReal>(leader, seen + leader->getPositionOnLane() - leader->getVehicleType().getLength() - veh.getVehicleType().getMinGap());
1152  } else {
1153  leader = nextLane->getPartialOccupator();
1154  if (leader != 0) {
1155  return std::pair<MSVehicle* const, SUMOReal>(leader, seen + nextLane->getPartialOccupatorEnd() - veh.getVehicleType().getMinGap());
1156  }
1157  }
1158  if (nextLane->getVehicleMaxSpeed(&veh) < speed) {
1159  dist = veh.getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(&veh));
1160  }
1161  seen += nextLane->getLength();
1162 #ifdef HAVE_INTERNAL_LANES
1163  if (!nextInternal) {
1164  view++;
1165  }
1166 #else
1167  view++;
1168 #endif
1169  } while (seen <= dist);
1170  return std::pair<MSVehicle* const, SUMOReal>(static_cast<MSVehicle*>(0), -1);
1171 }
1172 
1173 
1174 MSLane*
1176  if (myLogicalPredecessorLane != 0) {
1177  return myLogicalPredecessorLane;
1178  }
1179  if (myLogicalPredecessorLane == 0) {
1180  std::vector<MSEdge*> pred = myEdge->getIncomingEdges();
1181  // get only those edges which connect to this lane
1182  for (std::vector<MSEdge*>::iterator i = pred.begin(); i != pred.end();) {
1183  std::vector<IncomingLaneInfo>::const_iterator j = find_if(myIncomingLanes.begin(), myIncomingLanes.end(), edge_finder(*i));
1184  if (j == myIncomingLanes.end()) {
1185  i = pred.erase(i);
1186  } else {
1187  ++i;
1188  }
1189  }
1190  // get the edge with the most connections to this lane's edge
1191  if (pred.size() != 0) {
1192  std::sort(pred.begin(), pred.end(), by_connections_to_sorter(&getEdge()));
1193  MSEdge* best = *pred.begin();
1194  std::vector<IncomingLaneInfo>::const_iterator j = find_if(myIncomingLanes.begin(), myIncomingLanes.end(), edge_finder(best));
1195  myLogicalPredecessorLane = (*j).lane;
1196  }
1197  }
1198  return myLogicalPredecessorLane;
1199 }
1200 
1201 
1202 void
1205 }
1206 
1207 
1208 void
1211 }
1212 
1213 
1214 // ------------ Current state retrieval
1215 SUMOReal
1217  return myVehicleLengthSum / myLength;
1218 }
1219 
1220 
1221 SUMOReal
1223  return myVehicleLengthSum;
1224 }
1225 
1226 
1227 SUMOReal
1229  if (myVehicles.size() == 0) {
1230  return myMaxSpeed;
1231  }
1232  SUMOReal v = 0;
1233  const MSLane::VehCont& vehs = getVehiclesSecure();
1234  for (VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1235  v += (*i)->getSpeed();
1236  }
1237  SUMOReal ret = v / (SUMOReal) myVehicles.size();
1238  releaseVehicles();
1239  return ret;
1240 }
1241 
1242 
1243 SUMOReal
1245  SUMOReal ret = 0;
1246  const MSLane::VehCont& vehs = getVehiclesSecure();
1247  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1248  ret += (*i)->getHBEFA_CO2Emissions();
1249  }
1250  releaseVehicles();
1251  return ret;
1252 }
1253 
1254 
1255 SUMOReal
1257  SUMOReal ret = 0;
1258  const MSLane::VehCont& vehs = getVehiclesSecure();
1259  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1260  ret += (*i)->getHBEFA_COEmissions();
1261  }
1262  releaseVehicles();
1263  return ret;
1264 }
1265 
1266 
1267 SUMOReal
1269  SUMOReal ret = 0;
1270  const MSLane::VehCont& vehs = getVehiclesSecure();
1271  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1272  ret += (*i)->getHBEFA_PMxEmissions();
1273  }
1274  releaseVehicles();
1275  return ret;
1276 }
1277 
1278 
1279 SUMOReal
1281  SUMOReal ret = 0;
1282  const MSLane::VehCont& vehs = getVehiclesSecure();
1283  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1284  ret += (*i)->getHBEFA_NOxEmissions();
1285  }
1286  releaseVehicles();
1287  return ret;
1288 }
1289 
1290 
1291 SUMOReal
1293  SUMOReal ret = 0;
1294  const MSLane::VehCont& vehs = getVehiclesSecure();
1295  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1296  ret += (*i)->getHBEFA_HCEmissions();
1297  }
1298  releaseVehicles();
1299  return ret;
1300 }
1301 
1302 
1303 SUMOReal
1305  SUMOReal ret = 0;
1306  const MSLane::VehCont& vehs = getVehiclesSecure();
1307  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1308  ret += (*i)->getHBEFA_FuelConsumption();
1309  }
1310  releaseVehicles();
1311  return ret;
1312 }
1313 
1314 
1315 SUMOReal
1317  SUMOReal ret = 0;
1318  const MSLane::VehCont& vehs = getVehiclesSecure();
1319  if (vehs.size() == 0) {
1320  releaseVehicles();
1321  return 0;
1322  }
1323  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1324  SUMOReal sv = (*i)->getHarmonoise_NoiseEmissions();
1325  ret += (SUMOReal) pow(10., (sv / 10.));
1326  }
1327  releaseVehicles();
1328  return HelpersHarmonoise::sum(ret);
1329 }
1330 
1331 
1332 bool
1334  return cmp->getPositionOnLane() >= pos;
1335 }
1336 
1337 
1338 int
1340  return v1->getPositionOnLane() > v2->getPositionOnLane();
1341 }
1342 
1344  myEdge(e),
1345  myLaneDir(e->getLanes()[0]->getShape().getBegLine().atan2PositiveAngle())
1346 { }
1347 
1348 
1349 int
1350 MSLane::by_connections_to_sorter::operator()(const MSEdge* const e1, const MSEdge* const e2) const {
1351  const std::vector<MSLane*>* ae1 = e1->allowedLanes(*myEdge);
1352  const std::vector<MSLane*>* ae2 = e2->allowedLanes(*myEdge);
1353  SUMOReal s1 = 0;
1354  if (ae1 != 0 && ae1->size() != 0) {
1355  s1 = (SUMOReal) ae1->size() + GeomHelper::getMinAngleDiff((*ae1)[0]->getShape().getBegLine().atan2PositiveAngle(), myLaneDir) / M_PI / 2.;
1356  }
1357  SUMOReal s2 = 0;
1358  if (ae2 != 0 && ae2->size() != 0) {
1359  s2 = (SUMOReal) ae2->size() + GeomHelper::getMinAngleDiff((*ae2)[0]->getShape().getBegLine().atan2PositiveAngle(), myLaneDir) / M_PI / 2.;
1360  }
1361  return s1 < s2;
1362 }
1363 
1364 
1365 void
1367  out.openTag(SUMO_TAG_LANE);
1370  out.closeTag();
1371  out.closeTag();
1372 }
1373 
1374 
1375 void
1376 MSLane::loadState(std::vector<std::string>& vehIds, MSVehicleControl& vc) {
1377  for (std::vector<std::string>::const_iterator it = vehIds.begin(); it != vehIds.end(); ++it) {
1378  MSVehicle* v = dynamic_cast<MSVehicle*>(vc.getVehicle(*it));
1379  assert(v != 0);
1380  v->getBestLanes(true, this);
1383  }
1384 }
1385 
1386 
1387 
1388 /****************************************************************************/
1389