SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MSVehicle.cpp
Go to the documentation of this file.
1 /****************************************************************************/
17 // Representation of a vehicle in the micro simulation
18 /****************************************************************************/
19 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
20 // Copyright (C) 2001-2013 DLR (http://www.dlr.de/) and contributors
21 /****************************************************************************/
22 //
23 // This file is part of SUMO.
24 // SUMO is free software: you can redistribute it and/or modify
25 // it under the terms of the GNU General Public License as published by
26 // the Free Software Foundation, either version 3 of the License, or
27 // (at your option) any later version.
28 //
29 /****************************************************************************/
30 
31 // ===========================================================================
32 // included modules
33 // ===========================================================================
34 #ifdef _MSC_VER
35 #include <windows_config.h>
36 #else
37 #include <config.h>
38 #endif
39 
40 #include "MSLane.h"
41 #include "MSVehicle.h"
42 #include "MSEdge.h"
43 #include "MSVehicleType.h"
44 #include "MSNet.h"
45 #include "MSRoute.h"
46 #include "MSLinkCont.h"
48 #include <utils/common/StdDefs.h>
50 #include <microsim/MSGlobals.h>
51 #include <iostream>
52 #include <cassert>
53 #include <cmath>
54 #include <cstdlib>
55 #include <algorithm>
56 #include <map>
57 #include "MSMoveReminder.h"
59 #include "MSLCM_DK2004.h"
60 #include <utils/common/ToString.h>
64 #include "trigger/MSBusStop.h"
66 #include "MSPerson.h"
67 #include "MSPersonControl.h"
70 #include "MSEdgeWeightsStorage.h"
73 
74 #ifdef _MESSAGES
75 #include "MSMessageEmitter.h"
76 #endif
77 
78 #ifdef HAVE_INTERNAL
79 #include <mesosim/MESegment.h>
80 #include <mesosim/MELoop.h>
81 #include "MSGlobals.h"
82 #endif
83 
84 #ifdef CHECK_MEMORY_LEAKS
85 #include <foreign/nvwa/debug_new.h>
86 #endif // CHECK_MEMORY_LEAKS
87 
88 //#define DEBUG_VEHICLE_GUI_SELECTION 1
89 #ifdef DEBUG_VEHICLE_GUI_SELECTION
90 #undef ID_LIST
92 #include <guisim/GUIVehicle.h>
93 #include <guisim/GUILane.h>
94 #endif
95 
96 #define BUS_STOP_OFFSET 0.5
97 
98 
99 // ===========================================================================
100 // static value definitions
101 // ===========================================================================
102 std::vector<MSLane*> MSVehicle::myEmptyLaneVector;
103 
104 
105 // ===========================================================================
106 // method definitions
107 // ===========================================================================
108 /* -------------------------------------------------------------------------
109  * methods of MSVehicle::State
110  * ----------------------------------------------------------------------- */
112  myPos = state.myPos;
113  mySpeed = state.mySpeed;
114 }
115 
116 
119  myPos = state.myPos;
120  mySpeed = state.mySpeed;
121  return *this;
122 }
123 
124 
125 bool
127  return (myPos != state.myPos ||
128  mySpeed != state.mySpeed);
129 }
130 
131 
132 SUMOReal
134  return myPos;
135 }
136 
137 
139  myPos(pos), mySpeed(speed) {}
140 
141 
142 /* -------------------------------------------------------------------------
143  * methods of MSVehicle::Influencer
144  * ----------------------------------------------------------------------- */
145 #ifndef NO_TRACI
147  : mySpeedAdaptationStarted(true), myConsiderSafeVelocity(true),
148  myConsiderMaxAcceleration(true), myConsiderMaxDeceleration(true),
149  myAmVTDControlled(false) {}
150 
151 
153 
154 
155 void
156 MSVehicle::Influencer::setSpeedTimeLine(const std::vector<std::pair<SUMOTime, SUMOReal> >& speedTimeLine) {
157  mySpeedAdaptationStarted = true;
158  mySpeedTimeLine = speedTimeLine;
159 }
160 
161 
162 void
163 MSVehicle::Influencer::setLaneTimeLine(const std::vector<std::pair<SUMOTime, unsigned int> >& laneTimeLine) {
164  myLaneTimeLine = laneTimeLine;
165 }
166 
167 
168 SUMOReal
170  // keep original speed
171  myOriginalSpeed = speed;
172  // remove leading commands which are no longer valid
173  while (mySpeedTimeLine.size() == 1 || (mySpeedTimeLine.size() > 1 && currentTime > mySpeedTimeLine[1].first)) {
174  mySpeedTimeLine.erase(mySpeedTimeLine.begin());
175  }
176  // do nothing if the time line does not apply for the current time
177  if (mySpeedTimeLine.size() < 2 || currentTime < mySpeedTimeLine[0].first) {
178  return speed;
179  }
180  // compute and set new speed
181  if (!mySpeedAdaptationStarted) {
182  mySpeedTimeLine[0].second = speed;
183  mySpeedAdaptationStarted = true;
184  }
185  currentTime += DELTA_T;
186  const SUMOReal td = STEPS2TIME(currentTime - mySpeedTimeLine[0].first) / STEPS2TIME(mySpeedTimeLine[1].first + DELTA_T - mySpeedTimeLine[0].first);
187  speed = mySpeedTimeLine[0].second - (mySpeedTimeLine[0].second - mySpeedTimeLine[1].second) * td;
188  if (myConsiderSafeVelocity) {
189  speed = MIN2(speed, vSafe);
190  }
191  if (myConsiderMaxAcceleration) {
192  speed = MIN2(speed, vMax);
193  }
194  if (myConsiderMaxDeceleration) {
195  speed = MAX2(speed, vMin);
196  }
197  return speed;
198 }
199 
200 
202 MSVehicle::Influencer::checkForLaneChanges(SUMOTime currentTime, const MSEdge& currentEdge, unsigned int currentLaneIndex) {
203  // remove leading commands which are no longer valid
204  while (myLaneTimeLine.size() == 1 || (myLaneTimeLine.size() > 1 && currentTime > myLaneTimeLine[1].first)) {
205  myLaneTimeLine.erase(myLaneTimeLine.begin());
206  }
207  // do nothing if the time line does not apply for the current time
208  if (myLaneTimeLine.size() < 2 || currentTime < myLaneTimeLine[0].first) {
209  return REQUEST_NONE;
210  }
211  unsigned int destinationLaneIndex = myLaneTimeLine[1].second;
212  if ((unsigned int)currentEdge.getLanes().size() <= destinationLaneIndex) {
213  return REQUEST_NONE;
214  }
215  if (currentLaneIndex > destinationLaneIndex) {
216  return REQUEST_RIGHT;
217  } else if (currentLaneIndex < destinationLaneIndex) {
218  return REQUEST_LEFT;
219  } else {
220  return REQUEST_HOLD;
221  }
222 }
223 
224 
225 void
227  myConsiderSafeVelocity = value;
228 }
229 
230 
231 void
233  myConsiderMaxAcceleration = value;
234 }
235 
236 
237 void
239  myConsiderMaxDeceleration = value;
240 }
241 
242 
243 void
246  v->getLane()->removeVehicle(v);
247  if (myVTDRoute.size() != 0) {
248  v->replaceRouteEdges(myVTDRoute, true);
249  }
250  v->myCurrEdge += myVTDEdgeOffset;
251  if (myVTDPos > myVTDLane->getLength()) {
252  myVTDPos = myVTDLane->getLength();
253  }
254  myVTDLane->forceVehicleInsertion(v, myVTDPos);
255  v->getBestLanes();
256  myAmVTDControlled = false;
257 }
258 
259 #endif
260 
261 
262 /* -------------------------------------------------------------------------
263  * MSVehicle-methods
264  * ----------------------------------------------------------------------- */
266  delete myLaneChangeModel;
267  // other
268  delete myEdgeWeights;
269  for (std::vector<MSLane*>::iterator i = myFurtherLanes.begin(); i != myFurtherLanes.end(); ++i) {
270  (*i)->resetPartialOccupation(this);
271  }
272  myFurtherLanes.clear();
273  for (DriveItemVector::iterator i = myLFLinkLanes.begin(); i != myLFLinkLanes.end(); ++i) {
274  if ((*i).myLink != 0) {
275  (*i).myLink->removeApproaching(this);
276  }
277  }
278  //
279  if (myType->amVehicleSpecific()) {
280  delete myType;
281  }
282 #ifndef NO_TRACI
283  delete myInfluencer;
284 #endif
285 }
286 
287 
289  const MSRoute* route,
290  const MSVehicleType* type,
291  SUMOReal speedFactor,
292  int /*vehicleIndex*/) :
293  MSBaseVehicle(pars, route, type, speedFactor),
295  myWaitingTime(0),
296  myState(0, 0), //
297  myLane(0),
299  myPersonDevice(0),
300  myAcceleration(0),
301  mySignals(0),
302  myAmOnNet(false),
304  myHaveToWaitOnNextLink(false),
305  myEdgeWeights(0)
306 #ifndef NO_TRACI
307  , myInfluencer(0)
308 #endif
309 {
310  for (std::vector<SUMOVehicleParameter::Stop>::iterator i = pars->stops.begin(); i != pars->stops.end(); ++i) {
311  if (!addStop(*i)) {
312  throw ProcessError("Stop for vehicle '" + pars->id +
313  "' on lane '" + i->lane + "' is not downstream the current route.");
314  }
315  }
316  for (std::vector<SUMOVehicleParameter::Stop>::const_iterator i = route->getStops().begin(); i != route->getStops().end(); ++i) {
317  if (!addStop(*i)) {
318  throw ProcessError("Stop for vehicle '" + pars->id +
319  "' on lane '" + i->lane + "' is not downstream the current route.");
320  }
321  }
322  const MSLane* const depLane = (*myCurrEdge)->getDepartLane(*this);
323  if (depLane == 0) {
324  throw ProcessError("Invalid departlane definition for vehicle '" + pars->id + "'.");
325  }
326  if (pars->departSpeedProcedure == DEPART_SPEED_GIVEN && pars->departSpeed > depLane->getSpeedLimit()) {
327  throw ProcessError("Departure speed for vehicle '" + pars->id +
328  "' is too high for the departure lane '" + depLane->getID() + "'.");
329  }
330  if (pars->departSpeedProcedure == DEPART_SPEED_GIVEN && pars->departSpeed > type->getMaxSpeed()) {
331  throw ProcessError("Departure speed for vehicle '" + pars->id +
332  "' is too high for the vehicle type '" + type->getID() + "'.");
333  }
334 #ifdef _MESSAGES
335  myLCMsgEmitter = MSNet::getInstance()->getMsgEmitter("lanechange");
336  myBMsgEmitter = MSNet::getInstance()->getMsgEmitter("break");
337  myHBMsgEmitter = MSNet::getInstance()->getMsgEmitter("heartbeat");
338 #endif
339  myLaneChangeModel = new MSLCM_DK2004(*this);
341 }
342 
343 
344 void
347  for (DriveItemVector::iterator i = myLFLinkLanes.begin(); i != myLFLinkLanes.end(); ++i) {
348  if ((*i).myLink != 0) {
349  (*i).myLink->removeApproaching(this);
350  }
351  }
352  leaveLane(reason);
353 }
354 
355 
356 // ------------ interaction with the route
357 bool
359  return myCurrEdge == myRoute->end() - 1 && myState.myPos > myArrivalPos - POSITION_EPS;
360 }
361 
362 
363 bool
364 MSVehicle::replaceRoute(const MSRoute* newRoute, bool onInit) {
365  const MSEdgeVector& edges = newRoute->getEdges();
366  // assert the vehicle may continue (must not be "teleported" or whatever to another position)
367  if (!onInit && !newRoute->contains(*myCurrEdge)) {
368  return false;
369  }
370 
371  // rebuild in-vehicle route information
372  if (onInit) {
373  myCurrEdge = newRoute->begin();
374  } else {
375  myCurrEdge = find(edges.begin(), edges.end(), *myCurrEdge);
376  }
377  // check whether the old route may be deleted (is not used by anyone else)
378  newRoute->addReference();
379  myRoute->release();
380  // assign new route
381  myRoute = newRoute;
383  if (!onInit) {
384  getBestLanes(true);
385  }
386  // update arrival definition
388  // save information that the vehicle was rerouted
391  // recheck stops
392  for (std::list<Stop>::iterator iter = myStops.begin(); iter != myStops.end();) {
393  if (find(edges.begin(), edges.end(), &iter->lane->getEdge()) == edges.end()) {
394  iter = myStops.erase(iter);
395  } else {
396  iter->edge = find(edges.begin(), edges.end(), &iter->lane->getEdge());
397  ++iter;
398  }
399  }
400  return true;
401 }
402 
403 
404 bool
405 MSVehicle::willPass(const MSEdge* const edge) const {
406  return find(myCurrEdge, myRoute->end(), edge) != myRoute->end();
407 }
408 
409 
410 unsigned int
412  return (unsigned int) std::distance(myRoute->begin(), myCurrEdge);
413 }
414 
415 
416 void
417 MSVehicle::resetRoutePosition(unsigned int index) {
418  myCurrEdge = myRoute->begin() + index;
419  // !!! hack
420  myArrivalPos = (*(myRoute->end() - 1))->getLanes()[0]->getLength();
421 }
422 
423 
424 
427  return _getWeightsStorage();
428 }
429 
430 
433  return _getWeightsStorage();
434 }
435 
436 
439  if (myEdgeWeights == 0) {
441  }
442  return *myEdgeWeights;
443 }
444 
445 
446 // ------------ Interaction with move reminders
447 void
449  // This erasure-idiom works for all stl-sequence-containers
450  // See Meyers: Effective STL, Item 9
451  for (MoveReminderCont::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end();) {
452  if (!rem->first->notifyMove(*this, oldPos + rem->second, newPos + rem->second, newSpeed)) {
453  rem = myMoveReminders.erase(rem);
454  } else {
455  ++rem;
456  }
457  }
458 }
459 
460 
461 void
463  // save the old work reminders, patching the position information
464  // add the information about the new offset to the old lane reminders
465  const SUMOReal oldLaneLength = myLane->getLength();
466  for (MoveReminderCont::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end(); ++rem) {
467  rem->second += oldLaneLength;
468  }
469  for (std::vector< MSMoveReminder* >::const_iterator rem = enteredLane.getMoveReminders().begin(); rem != enteredLane.getMoveReminders().end(); ++rem) {
470  addReminder(*rem);
471  }
472 }
473 
474 
475 // ------------ Other getter methods
476 Position
478  if (myLane == 0) {
479  return Position::INVALID;
480  }
482 }
483 
484 
485 SUMOReal
488  Position p2 = myFurtherLanes.size() > 0
489  ? myFurtherLanes.back()->getShape().positionAtOffset(myFurtherLanes.back()->getPartialOccupatorEnd())
491  if (p1 != p2) {
492  return atan2(p1.x() - p2.x(), p2.y() - p1.y()) * 180. / PI;
493  } else {
495  }
496 }
497 
498 
499 // ------------
500 bool
502  Stop stop;
503  stop.lane = MSLane::dictionary(stopPar.lane);
504  stop.busstop = MSNet::getInstance()->getBusStop(stopPar.busstop);
505  stop.startPos = stopPar.startPos;
506  stop.endPos = stopPar.endPos;
507  stop.duration = stopPar.duration;
508  stop.until = stopPar.until;
509  if (stop.until != -1) {
510  stop.until += untilOffset;
511  }
512  stop.triggered = stopPar.triggered;
513  stop.parking = stopPar.parking;
514  stop.reached = false;
515  if (stop.startPos < 0 || stop.endPos > stop.lane->getLength()) {
516  return false;
517  }
518  stop.edge = find(myCurrEdge, myRoute->end(), &stop.lane->getEdge());
519  MSRouteIterator prevStopEdge = myCurrEdge;
520  SUMOReal prevStopPos = myState.myPos;
521  // where to insert the stop
522  std::list<Stop>::iterator iter = myStops.begin();
523  if (stopPar.index == STOP_INDEX_END || stopPar.index >= static_cast<int>(myStops.size())) {
524  if (myStops.size() > 0) {
525  prevStopEdge = myStops.back().edge;
526  prevStopPos = myStops.back().endPos;
527  iter = myStops.end();
528  stop.edge = find(prevStopEdge, myRoute->end(), &stop.lane->getEdge());
529  }
530  } else {
531  if (stopPar.index == STOP_INDEX_FIT) {
532  while (iter != myStops.end() && (iter->edge < stop.edge ||
533  (iter->endPos < stop.endPos && iter->edge == stop.edge))) {
534  prevStopEdge = iter->edge;
535  prevStopPos = iter->endPos;
536  ++iter;
537  }
538  } else {
539  int index = stopPar.index;
540  while (index > 0) {
541  prevStopEdge = iter->edge;
542  prevStopPos = iter->endPos;
543  ++iter;
544  --index;
545  }
546  stop.edge = find(prevStopEdge, myRoute->end(), &stop.lane->getEdge());
547  }
548  }
549  if (stop.edge == myRoute->end() || prevStopEdge > stop.edge ||
550  (prevStopEdge == stop.edge && prevStopPos > stop.endPos)) {
551  return false;
552  }
554  return false;
555  }
556  myStops.insert(iter, stop);
557  return true;
558 }
559 
560 
561 bool
563  return !myStops.empty() && myStops.begin()->reached;
564 }
565 
566 
567 bool
569  return isStopped() && myStops.begin()->parking;
570 }
571 
572 
573 SUMOReal
575  if (myStops.empty()) {
576  // no stops; pass
577  return currentVelocity;
578  }
579  Stop& stop = myStops.front();
580  if (stop.reached) {
581  // ok, we have already reached the next stop
582  // any waiting persons may board now
583  bool boarded = MSNet::getInstance()->getPersonControl().boardAnyWaiting(&myLane->getEdge(), this);
584  if (boarded) {
585  if (stop.busstop != 0) {
586  const std::vector<MSPerson*>& persons = myPersonDevice->getPersons();
587  for (std::vector<MSPerson*>::const_iterator i = persons.begin(); i != persons.end(); ++i) {
588  stop.busstop->removePerson(*i);
589  }
590  }
591  // the triggering condition has been fulfilled. Maybe we want to wait a bit longer for additional riders (car pooling)
592  stop.triggered = false;
596  }
597  }
598  if (stop.duration <= 0 && !stop.triggered) {
599  // we have waited long enough and fulfilled any passenger-requirements
600  if (stop.busstop != 0) {
601  // inform bus stop about leaving it
602  stop.busstop->leaveFrom(this);
603  }
604  // the current stop is no longer valid
606  myStops.pop_front();
607  // do not count the stopping time towards gridlock time.
608  // Other outputs use an independent counter and are not affected.
609  myWaitingTime = 0;
610  // maybe the next stop is on the same edge; let's rebuild best lanes
611  getBestLanes(true);
612  // continue as wished...
613  } else {
614  // we have to wait some more time
616  // we can only register after waiting for one step. otherwise we might falsely signal a deadlock
619  }
620  stop.duration -= DELTA_T;
621  return 0;
622  }
623  } else {
624  // is the next stop on the current lane?
625  if (stop.edge == myCurrEdge) {
626  // get the stopping position
627  SUMOReal endPos = stop.endPos;
628  bool busStopsMustHaveSpace = true;
629  if (stop.busstop != 0) {
630  // on bus stops, we have to wait for free place if they are in use...
631  endPos = stop.busstop->getLastFreePos(*this);
632  if (endPos - 5. < stop.busstop->getBeginLanePosition()) { // !!! explicit offset
633  busStopsMustHaveSpace = false;
634  }
635  }
636  if (myState.pos() + getVehicleType().getMinGap() >= endPos - BUS_STOP_OFFSET && busStopsMustHaveSpace) {
637  // ok, we may stop (have reached the stop)
638  stop.reached = true;
640  // compute stopping time
641  if (stop.until >= 0) {
642  if (stop.duration == -1) {
644  } else {
646  }
647  }
648  if (stop.busstop != 0) {
649  // let the bus stop know the vehicle
651  }
652  }
653  // decelerate
654  return getCarFollowModel().stopSpeed(this, endPos - myState.pos());
655  }
656  }
657  return currentVelocity;
658 }
659 
660 
661 void
662 MSVehicle::planMove(SUMOTime t, MSVehicle* pred, MSVehicle* neigh, SUMOReal lengthsInFront) {
663 #ifdef _MESSAGES
664  if (myHBMsgEmitter != 0) {
665  if (isOnRoad()) {
667  myHBMsgEmitter->writeHeartBeatEvent(myParameter->id, timeStep, myLane, myState.pos(), myState.speed(), getPosition().x(), getPosition().y());
668  }
669  }
670 #endif
671 #ifdef DEBUG_VEHICLE_GUI_SELECTION
672  if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(this)->getGlID())) {
673  int bla = 0;
674  }
675 #endif
676  // remove information about approaching links, will be reset later in this step
677  for (DriveItemVector::iterator i = myLFLinkLanes.begin(); i != myLFLinkLanes.end(); ++i) {
678  if ((*i).myLink != 0) {
679  (*i).myLink->removeApproaching(this);
680  }
681  }
682  myLFLinkLanes.clear();
683  //
684  const MSCFModel& cfModel = getCarFollowModel();
685  // vBeg is the initial maximum velocity of this vehicle in this step
686  SUMOReal v = MIN2(cfModel.maxNextSpeed(myState.mySpeed, this), myLane->getVehicleMaxSpeed(this));
687 #ifndef NO_TRACI
688  if (myInfluencer != 0) {
689  SUMOReal vMin = MAX2(SUMOReal(0), getVehicleType().getCarFollowModel().getSpeedAfterMaxDecel(myState.mySpeed));
691  v = myInfluencer->influenceSpeed(MSNet::getInstance()->getCurrentTimeStep(), v, v, vMin, vMax);
692  // !!! recheck - why is it done, here?
693  if (myInfluencer->isVTDControlled()) {
694  return; // !!! temporary
695  }
696  }
697 #endif
698 
699  SUMOReal vehicleLength = getVehicleType().getLength();
700  SUMOReal maxV = cfModel.maxNextSpeed(myState.mySpeed, this);
701  SUMOReal dist = SPEED2DIST(maxV) + cfModel.brakeGap(maxV);
702  const std::vector<MSLane*>& bestLaneConts = getBestLanesContinuation();
703  assert(bestLaneConts.size() > 0);
704 #ifdef HAVE_INTERNAL_LANES
705  bool hadNonInternal = false;
706 #else
707  bool hadNonInternal = true;
708 #endif
709  SUMOReal seen = myLane->getLength() - myState.myPos; // the distance already "seen"; in the following always up to the end of the current "lane"
710  SUMOReal seenNonInternal = 0;
711  cfModel.leftVehicleVsafe(this, neigh, v);
712  SUMOReal vLinkPass = MIN2(estimateSpeedAfterDistance(seen, v), myLane->getVehicleMaxSpeed(this)); // upper bound
713  unsigned int view = 0;
714  bool firstLane = true;
715  int lastLink = -1;
716  std::pair<MSVehicle*, SUMOReal> leaderInfo = pred != 0 ? std::pair<MSVehicle*, SUMOReal>(pred, gap2pred(*pred)) : std::pair<MSVehicle*, SUMOReal>((MSVehicle*) 0, 0);
717  // iterator over subsequent lanes and fill myLFLinkLanes until stopping distance or stopped
718  MSLane* lane = myLane;
719  while (true) {
720  SUMOReal laneStopOffset = lane->getLength() > getVehicleType().getMinGap() ? getVehicleType().getMinGap() : POSITION_EPS;
721  SUMOReal stopDist = MAX2(SUMOReal(0), seen - laneStopOffset);
722  // check leader on lane
723  // leader is given for the first edge only
724  if (!firstLane) {
725  leaderInfo = lane->getLastVehicleInformation();
726  leaderInfo.second = leaderInfo.second + seen - lane->getLength() - getVehicleType().getMinGap();
727  vLinkPass = MIN2(estimateSpeedAfterDistance(lane->getLength(), v), lane->getVehicleMaxSpeed(this)); // upper bound
728  } else if (leaderInfo.first == 0) {
729  // we still have to account vehicles lapping into the lane we are currently at
730  if (myLane->getPartialOccupator() != 0) {
731  leaderInfo = std::pair<MSVehicle*, SUMOReal>(myLane->getPartialOccupator(), myLane->getPartialOccupatorEnd() - myState.myPos - getVehicleType().getMinGap());
732  }
733  }
734  adaptToLeader(leaderInfo, seen, lastLink, lane, v, vLinkPass);
735 
736  // process stops
737  if (!myStops.empty() && &myStops.begin()->lane->getEdge() == &lane->getEdge()) {
738  // we are approaching a stop on the edge; must not drive further
739  const Stop& stop = *myStops.begin();
740  SUMOReal stopDist = stop.busstop == 0 ? seen + stop.endPos - lane->getLength() : seen + stop.busstop->getLastFreePos(*this) - POSITION_EPS - lane->getLength();
741  SUMOReal stopSpeed = cfModel.stopSpeed(this, stopDist);
742  if (lastLink > 0) {
743  myLFLinkLanes[lastLink].adaptLeaveSpeed(stopSpeed);
744  }
745  v = MIN2(v, stopSpeed);
746  myLFLinkLanes.push_back(DriveProcessItem(0, v, v, false, 0, 0, stopDist));
747  break;
748  }
749 
750  // move to next lane
751  // get the next link used
752  MSLinkCont::const_iterator link = myLane->succLinkSec(*this, view + 1, *lane, bestLaneConts);
753  // check whether the vehicle is on its final edge
754  bool onAppropriateLane = !lane->isLinkEnd(link); // !!! wird "appropriate" noch benutzt?
755  bool routeEnds = myCurrEdge + view + 1 == myRoute->end();
756  if (routeEnds) {
758  myParameter->arrivalSpeed : lane->getVehicleMaxSpeed(this));
759  // subtract the arrival speed from the remaining distance so we get one additional driving step with arrival speed
760  const SUMOReal distToArrival = seen + myArrivalPos - lane->getLength() - SPEED2DIST(arrivalSpeed);
761  const SUMOReal va = cfModel.freeSpeed(this, getSpeed(), distToArrival, arrivalSpeed);
762  v = MIN2(v, va);
763  if (lastLink > 0) {
764  myLFLinkLanes[lastLink].adaptLeaveSpeed(va);
765  }
766  myLFLinkLanes.push_back(DriveProcessItem(0, v, v, false, 0, 0, seen));
767  break;
768  }
769  // check whether the lane is a dead end
770  if (!onAppropriateLane) {
771  if (!routeEnds) {
772  SUMOReal va = MIN2(cfModel.stopSpeed(this, stopDist), lane->getVehicleMaxSpeed(this));
773  if (lastLink > 0) {
774  myLFLinkLanes[lastLink].adaptLeaveSpeed(va);
775  }
776  v = MIN2(va, v);
777  }
778  myLFLinkLanes.push_back(DriveProcessItem(0, v, v, false, 0, 0, seen));
779  break;
780  }
781 
782  const bool yellow = (*link)->getState() == LINKSTATE_TL_YELLOW_MAJOR || (*link)->getState() == LINKSTATE_TL_YELLOW_MINOR;
783  const bool red = (*link)->getState() == LINKSTATE_TL_RED;
784  const bool setRequest = v > 0; // even if red, if we cannot break we should issue a request
785  const SUMOReal vLinkWait = MIN2(v, cfModel.stopSpeed(this, stopDist));
786  if ((yellow || red) && seen > cfModel.brakeGap(myState.mySpeed) - myState.mySpeed * cfModel.getHeadwayTime()) {
787  // the vehicle is able to brake in front of a yellow/red traffic light
788  myLFLinkLanes.push_back(DriveProcessItem(*link, vLinkWait, vLinkWait, false, t + TIME2STEPS(seen / vLinkWait), vLinkWait, stopDist));
789  break;
790  }
791 
792 #ifdef HAVE_INTERNAL_LANES
793  // we want to pass the link but need to check for foes on internal lanes
794  std::pair<MSVehicle*, SUMOReal> linkLeaderInfo = (*link)->getLeaderInfo(myLeaderForLink, seen - getVehicleType().getMinGap());
795  if (linkLeaderInfo.first != 0) {
796  // the vehicle to enter the junction first has priority
797  if (!linkLeaderInfo.first->hasLinkLeader(this)) {
798  myLeaderForLink[*link] = linkLeaderInfo.first->getID();
799  myLinkLeaders.insert(linkLeaderInfo.first->getID());
800  adaptToLeader(linkLeaderInfo, seen, lastLink, lane, v, vLinkPass);
801  }
802  }
803 #endif
804 
805  SUMOReal va = firstLane ? v : lane->getVehicleMaxSpeed(this);
806  if (lastLink > 0) {
807  myLFLinkLanes[lastLink].adaptLeaveSpeed(va);
808  } //if(!myLFLinkLanes.empty()) { myLFLinkLanes.back().accelV = va; }
809  lastLink = (int)myLFLinkLanes.size();
810  // vehicles should decelerate when approaching a minor link
811  if (!(*link)->havePriority() && stopDist > getCarFollowModel().getMaxDecel()) {
812  // vehicle decelerates just enough to be able to stop if necessary and then accelerates
813  const SUMOReal arrivalSpeed = getCarFollowModel().getMaxDecel() + getCarFollowModel().getMaxAccel();
814  const SUMOReal v1 = MAX2(vLinkWait, arrivalSpeed);
815  // now + time spent decelerating + time spent at full speed
816  const SUMOTime arrivalTime = t + TIME2STEPS((v1 - arrivalSpeed) / getCarFollowModel().getMaxDecel()
817  + (seen - (v1 * v1 - arrivalSpeed * arrivalSpeed) * 0.5 / getCarFollowModel().getMaxDecel()) / vLinkWait);
818  myLFLinkLanes.push_back(DriveProcessItem(*link, vLinkWait, vLinkWait, setRequest, arrivalTime, arrivalSpeed, stopDist));
819  } else {
820  if (vLinkPass >= v) {
821  const SUMOReal accelTime = (vLinkPass - v) / getCarFollowModel().getMaxAccel();
822  const SUMOReal accelWay = accelTime * (vLinkPass + v) * 0.5;
823  const SUMOTime arrivalTime = t + TIME2STEPS(accelTime + MAX2(SUMOReal(0), seen - accelWay) / vLinkPass);
824  myLFLinkLanes.push_back(DriveProcessItem(*link, v, vLinkWait, setRequest, arrivalTime, vLinkPass, stopDist));
825  } else {
826  const SUMOReal decelTime = (v - vLinkPass) / getCarFollowModel().getMaxDecel();
827  const SUMOReal decelWay = decelTime * (vLinkPass + v) * 0.5;
828  const SUMOTime arrivalTime = t + TIME2STEPS(decelTime + MAX2(SUMOReal(0), seen - decelWay) / vLinkPass);
829  myLFLinkLanes.push_back(DriveProcessItem(*link, v, vLinkWait, setRequest, arrivalTime, vLinkPass, stopDist));
830  }
831  }
832  // get the following lane
833  lane = (*link)->getViaLaneOrLane();
834 #ifdef HAVE_INTERNAL_LANES
835  if ((*link)->getViaLane() == 0) {
836  hadNonInternal = true;
837  ++view;
838  }
839 #else
840  ++view;
841 #endif
842  const SUMOReal leaveSpeed = estimateLeaveSpeed(*link, vLinkPass);
843  myLFLinkLanes[lastLink].adaptLeaveSpeed(leaveSpeed);
844 
845  firstLane = false;
846  if (!setRequest || ((v <= 0 || seen > dist) && hadNonInternal && seenNonInternal > vehicleLength * 2)) {
847  break;
848  }
849  // the link was passed
850  // compute the velocity to use when the link is not blocked by other vehicles
851  // the vehicle shall be not faster when reaching the next lane than allowed
852  va = MAX2(lane->getVehicleMaxSpeed(this), cfModel.freeSpeed(this, getSpeed(), seen, lane->getVehicleMaxSpeed(this)));
853  v = MIN2(va, v);
854  seenNonInternal += lane->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL ? 0 : lane->getLength();
855  seen += lane->getLength();
856  }
857  checkRewindLinkLanes(lengthsInFront);
858 }
859 
860 
861 void
862 MSVehicle::adaptToLeader(std::pair<MSVehicle*, SUMOReal> leaderInfo, SUMOReal seen, int lastLink, MSLane* lane, SUMOReal& v, SUMOReal& vLinkPass) {
863  if (leaderInfo.first != 0) {
864  const MSCFModel& cfModel = getCarFollowModel();
865  SUMOReal vsafeLeader = 0;
866  if (leaderInfo.second >= 0) {
867  vsafeLeader = cfModel.followSpeed(this, getSpeed(), leaderInfo.second, leaderInfo.first->getSpeed(), leaderInfo.first->getCarFollowModel().getMaxDecel());
868  } else {
869  // the leading, in-lapping vehicle is occupying the complete next lane
870  // stop before entering this lane
871  vsafeLeader = cfModel.stopSpeed(this, seen - lane->getLength() - POSITION_EPS);
872  }
873  if (lastLink > 0) {
874  myLFLinkLanes[lastLink].adaptLeaveSpeed(vsafeLeader);
875  }
876  v = MIN2(v, vsafeLeader);
877  vLinkPass = MIN2(vLinkPass, vsafeLeader);
878  }
879 }
880 
881 
882 
883 SUMOReal
885  // estimate leave speed for passing time computation
886  // l=linkLength, a=accel, t=continuousTime, v=vLeave
887  // l=v*t + 0.5*a*t^2, solve for t and multiply with a, then add v
888  return MIN2(link->getViaLaneOrLane()->getVehicleMaxSpeed(this),
889  estimateSpeedAfterDistance(link->getLength(), vLinkPass));
890 }
891 
892 
893 SUMOReal
895  // dist=v*t + 0.5*accel*t^2, solve for t and multiply with accel, then add v
896  return MIN2(getVehicleType().getMaxSpeed(),
897  (SUMOReal)sqrt(2 * dist * getVehicleType().getCarFollowModel().getMaxAccel() + v * v));
898 }
899 
900 bool
902 #ifdef DEBUG_VEHICLE_GUI_SELECTION
903  if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(this)->getGlID())) {
904  int bla = 0;
905  }
906 #endif
907  // get vsafe
908  SUMOReal vSafe = 0;
909  myHaveToWaitOnNextLink = false;
910 #ifndef NO_TRACI
911  if (myInfluencer != 0) {
912  if (myInfluencer->isVTDControlled()) {
913  return false;
914  }
915  }
916 #endif
917 
918  assert(myLFLinkLanes.size() != 0 || (myInfluencer != 0 && myInfluencer->isVTDControlled()));
919  DriveItemVector::iterator i;
920  bool braking = false;
921  bool lastWasGreenCont = false;
922  for (i = myLFLinkLanes.begin(); i != myLFLinkLanes.end(); ++i) {
923  MSLink* link = (*i).myLink;
924  // the vehicle must change the lane on one of the next lanes
925  if (link != 0 && (*i).mySetRequest) {
926  const LinkState ls = link->getState();
927  // vehicles should brake when running onto a yellow light if the distance allows to halt in front
928  const bool yellow = ls == LINKSTATE_TL_YELLOW_MAJOR || ls == LINKSTATE_TL_YELLOW_MINOR;
930  if (yellow && ((*i).myDistance > brakeGap || myState.mySpeed < ACCEL2SPEED(getCarFollowModel().getMaxDecel()))) {
931  vSafe = (*i).myVLinkWait;
932  braking = true;
933  lastWasGreenCont = false;
934  link->removeApproaching(this);
935  break;
936  }
937  //
938  const bool opened = yellow || link->opened((*i).myArrivalTime, (*i).myArrivalSpeed, (*i).getLeaveSpeed(), getVehicleType().getLengthWithGap());
939  // vehicles should decelerate when approaching a minor link
940  // XXX check if this is still necessary
941  if (opened && !lastWasGreenCont && !link->havePriority() && (*i).myDistance > getCarFollowModel().getMaxDecel()) {
942  vSafe = (*i).myVLinkWait;
943  braking = true;
944  lastWasGreenCont = false;
945  if (ls == LINKSTATE_EQUAL) {
946  link->removeApproaching(this);
947  }
948  break; // could be revalidated
949  }
950  // have waited; may pass if opened...
951  if (opened) {
952  vSafe = (*i).myVLinkPass;
953  lastWasGreenCont = link->isCont() && (ls == LINKSTATE_TL_GREEN_MAJOR);
954  } else {
955  lastWasGreenCont = false;
956  vSafe = (*i).myVLinkWait;
957  braking = true;
958  if (ls == LINKSTATE_EQUAL) {
959  link->removeApproaching(this);
960  }
961  break;
962  }
963  } else {
964  vSafe = (*i).myVLinkWait;
965  braking = true;
966  break;
967  }
968  }
969  if (braking) {
970  myHaveToWaitOnNextLink = true;
971  }
972 
973  SUMOReal vNext = getCarFollowModel().moveHelper(this, vSafe);
974  //if (vNext > vSafe) {
975  // WRITE_WARNING("vehicle '" + getID() + "' cannot brake hard enough to reach safe speed "
976  // + toString(vSafe) + ", moving at " + toString(vNext) + " instead. time="
977  // + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
978  //}
979  vNext = MAX2(vNext, (SUMOReal) 0.);
980 #ifndef NO_TRACI
981  if (myInfluencer != 0) {
983  const SUMOReal vMin = MAX2(SUMOReal(0), getVehicleType().getCarFollowModel().getSpeedAfterMaxDecel(myState.mySpeed));
984  vNext = myInfluencer->influenceSpeed(MSNet::getInstance()->getCurrentTimeStep(), vNext, vSafe, vMin, vMax);
985  if (myInfluencer->isVTDControlled()) {
986  vNext = 0;
987  }
988  }
989 #endif
990  // visit waiting time
991  if (vNext <= 0.1) {
993  braking = true;
994  } else {
995  myWaitingTime = 0;
996  }
997  if (myState.mySpeed < vNext) {
998  braking = false;
999  }
1000  if (braking) {
1002  } else {
1004  }
1005  // call reminders after vNext is set
1006  const SUMOReal pos = myState.myPos;
1007 
1008 #ifdef _MESSAGES
1009  if (myHBMsgEmitter != 0) {
1010  if (isOnRoad()) {
1012  myHBMsgEmitter->writeHeartBeatEvent(myParameter->id, timeStep, myLane, myState.pos(), myState.speed(), getPosition().x(), getPosition().y());
1013  }
1014  }
1015  if (myBMsgEmitter != 0) {
1016  if (vNext < myState.mySpeed) {
1018  myBMsgEmitter->writeBreakEvent(myParameter->id, timeStep, myLane, myState.pos(), myState.speed(), getPosition().x(), getPosition().y());
1019  }
1020  }
1021 #endif
1022  // update position and speed
1023  myAcceleration = vNext - myState.mySpeed;
1024  myState.myPos += SPEED2DIST(vNext);
1025  myState.mySpeed = vNext;
1026  std::vector<MSLane*> passedLanes;
1027  for (std::vector<MSLane*>::reverse_iterator i = myFurtherLanes.rbegin(); i != myFurtherLanes.rend(); ++i) {
1028  passedLanes.push_back(*i);
1029  }
1030  if (passedLanes.size() == 0 || passedLanes.back() != myLane) {
1031  passedLanes.push_back(myLane);
1032  }
1033  bool moved = false;
1034  // move on lane(s)
1035  if (myState.myPos <= myLane->getLength()) {
1036  // we are staying at our lane
1037  // there is no need to go over succeeding lanes
1038  workOnMoveReminders(pos, pos + SPEED2DIST(vNext), vNext);
1039  } else {
1040  // we are moving at least to the next lane (maybe pass even more than one)
1041  if (myCurrEdge != myRoute->end() - 1) {
1042  MSLane* approachedLane = myLane;
1043  // move the vehicle forward
1044  for (i = myLFLinkLanes.begin(); i != myLFLinkLanes.end() && approachedLane != 0 && myState.myPos > approachedLane->getLength(); ++i) {
1046  MSLink* link = (*i).myLink;
1047  // check whether the vehicle was allowed to enter lane
1048  // otherwise it is decelareted and we do not need to test for it's
1049  // approach on the following lanes when a lane changing is performed
1050  // proceed to the next lane
1051  if (link != 0) {
1052  approachedLane = link->getViaLaneOrLane();
1053  } else {
1054  approachedLane = 0;
1055  }
1056  if (approachedLane != myLane && approachedLane != 0) {
1057  myState.myPos -= myLane->getLength();
1058  assert(myState.myPos > 0);
1059  enterLaneAtMove(approachedLane);
1060  myLane = approachedLane;
1061 #ifdef HAVE_INTERNAL_LANES
1062  // erase leader for the past link
1063  if (myLeaderForLink.find(link) != myLeaderForLink.end()) {
1064  myLinkLeaders.erase(myLeaderForLink[link]);
1065  myLeaderForLink.erase(link);
1066  }
1067 #endif
1068  moved = true;
1069  if (approachedLane->getEdge().isVaporizing()) {
1070  break;
1071  }
1072  }
1073  passedLanes.push_back(approachedLane);
1074  }
1075  }
1076  }
1077  // clear previously set information
1078  for (std::vector<MSLane*>::iterator i = myFurtherLanes.begin(); i != myFurtherLanes.end(); ++i) {
1079  (*i)->resetPartialOccupation(this);
1080  }
1081  myFurtherLanes.clear();
1082 
1083  if (myInfluencer != 0 && myInfluencer->isVTDControlled()) {
1084  myWaitingTime = 0;
1085 // myInfluencer->setVTDControlled(false);
1086  return false;
1087  }
1088 
1089  if (!hasArrived() && !myLane->getEdge().isVaporizing()) {
1090  if (myState.myPos > myLane->getLength()) {
1091  WRITE_WARNING("Vehicle '" + getID() + "' performs emergency stop on lane '" + myLane->getID() + " at position " +
1092  toString(myState.myPos) + " (decel=" + toString(myAcceleration - myState.mySpeed) + "), time="
1093  + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
1095  myState.mySpeed = 0;
1096  }
1097  if (myState.myPos - getVehicleType().getLength() < 0 && passedLanes.size() > 0) {
1098  SUMOReal leftLength = getVehicleType().getLength() - myState.myPos;
1099  std::vector<MSLane*>::reverse_iterator i = passedLanes.rbegin() + 1;
1100  while (leftLength > 0 && i != passedLanes.rend()) {
1101  myFurtherLanes.push_back(*i);
1102  leftLength -= (*i)->setPartialOccupation(this, leftLength);
1103  ++i;
1104  }
1105  }
1107  }
1108  return moved;
1109 }
1110 
1111 
1112 SUMOReal
1114  SUMOReal lengths = 0;
1115  const MSLane::VehCont& vehs = l->getVehiclesSecure();
1116  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1117  if ((*i)->getSpeed() < .1) {
1118  foundStopped = true;
1119  SUMOReal ret = (*i)->getPositionOnLane() - (*i)->getVehicleType().getLengthWithGap() - lengths;
1120  l->releaseVehicles();
1121  return ret;
1122  }
1123  lengths += (*i)->getVehicleType().getLengthWithGap();
1124  }
1125  l->releaseVehicles();
1126  return l->getLength() - lengths;
1127 }
1128 
1129 
1130 void
1132 #ifdef DEBUG_VEHICLE_GUI_SELECTION
1133  if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(this)->getGlID())) {
1134  int bla = 0;
1135  if (MSNet::getInstance()->getCurrentTimeStep() == 152000) {
1136  bla = 0;
1137  }
1138  }
1139 #endif
1140 #ifdef HAVE_INTERNAL_LANES
1142  int removalBegin = -1;
1143  bool hadVehicle = false;
1144  SUMOReal seenSpace = -lengthsInFront;
1145 
1146  std::vector<SUMOReal> availableSpace;
1147  std::vector<bool> hadVehicles;
1148  bool foundStopped = false;
1149 
1150  for (unsigned int i = 0; i < myLFLinkLanes.size(); ++i) {
1151  // skip unset links
1152  DriveProcessItem& item = myLFLinkLanes[i];
1153  if (item.myLink == 0 || foundStopped) {
1154  availableSpace.push_back(seenSpace);
1155  hadVehicles.push_back(hadVehicle);
1156  continue;
1157  }
1158  // get the next lane, determine whether it is an internal lane
1159  MSLane* approachedLane = item.myLink->getViaLane();
1160  if (approachedLane != 0) {
1161  if (item.myLink->isCrossing()/* && item.myLink->willHaveBlockedFoe()*/) {
1162  seenSpace = seenSpace - approachedLane->getVehLenSum();
1163  hadVehicle |= approachedLane->getVehicleNumber() != 0;
1164  } else {
1165  seenSpace = seenSpace + getSpaceTillLastStanding(approachedLane, foundStopped);// - approachedLane->getVehLenSum() + approachedLane->getLength();
1166  hadVehicle |= approachedLane->getVehicleNumber() != 0;
1167  }
1168  availableSpace.push_back(seenSpace);
1169  hadVehicles.push_back(hadVehicle);
1170  continue;
1171  }
1172  approachedLane = item.myLink->getLane();
1173  MSVehicle* last = approachedLane->getLastVehicle();
1174  if (last == 0) {
1175  last = approachedLane->getPartialOccupator();
1176  if (last != 0) {
1177  SUMOReal m = MAX2(seenSpace, seenSpace + approachedLane->getPartialOccupatorEnd() + last->getCarFollowModel().brakeGap(last->getSpeed()));
1178  availableSpace.push_back(m);
1179  hadVehicle = true;
1180  seenSpace = seenSpace + getSpaceTillLastStanding(approachedLane, foundStopped);// - approachedLane->getVehLenSum() + approachedLane->getLength();
1181  if (last->myHaveToWaitOnNextLink) {
1182  foundStopped = true;
1183  }
1184  } else {
1185 // seenSpace = seenSpace - approachedLane->getVehLenSum() + approachedLane->getLength();
1186 // availableSpace.push_back(seenSpace);
1187  availableSpace.push_back(seenSpace + getSpaceTillLastStanding(approachedLane, foundStopped));
1188  if (!foundStopped) {
1189  seenSpace = seenSpace - approachedLane->getVehLenSum() + approachedLane->getLength();
1190  } else {
1191  seenSpace = availableSpace.back();
1192  }
1193  }
1194  } else {
1195  if (last->signalSet(VEH_SIGNAL_BRAKELIGHT)) {
1196  SUMOReal lastBrakeGap = last->getCarFollowModel().brakeGap(approachedLane->getLastVehicle()->getSpeed());
1197  SUMOReal lastGap = last->getPositionOnLane() - last->getVehicleType().getLengthWithGap() + lastBrakeGap - last->getSpeed() * last->getCarFollowModel().getHeadwayTime();
1198  SUMOReal m = MAX2(seenSpace, seenSpace + lastGap);
1199  availableSpace.push_back(m);
1200  seenSpace = seenSpace + getSpaceTillLastStanding(approachedLane, foundStopped);// - approachedLane->getVehLenSum() + approachedLane->getLength();
1201  } else {
1202 // seenSpace = seenSpace - approachedLane->getVehLenSum() + approachedLane->getLength();
1203 // availableSpace.push_back(seenSpace);
1204  availableSpace.push_back(seenSpace + getSpaceTillLastStanding(approachedLane, foundStopped));
1205  if (!foundStopped) {
1206  seenSpace = seenSpace - approachedLane->getVehLenSum() + approachedLane->getLength();
1207  } else {
1208  seenSpace = availableSpace.back();
1209  }
1210  }
1211  if (last->myHaveToWaitOnNextLink) {
1212  foundStopped = true;
1213  }
1214  hadVehicle = true;
1215  }
1216  hadVehicles.push_back(hadVehicle);
1217  }
1218 #ifdef DEBUG_VEHICLE_GUI_SELECTION
1219  if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(this)->getGlID())) {
1220  int bla = 0;
1221  }
1222 #endif
1223  for (int i = (int)(myLFLinkLanes.size() - 1); i > 0; --i) {
1224  DriveProcessItem& item = myLFLinkLanes[i - 1];
1225  const bool opened = item.myLink != 0 && (item.myLink->havePriority() ||
1226  item.myLink->opened(item.myArrivalTime, item.myArrivalSpeed,
1228  bool allowsContinuation = item.myLink == 0 || item.myLink->isCont() || !hadVehicles[i] || opened;
1229  if (!opened && item.myLink != 0) {
1230  if (i > 1) {
1231  DriveProcessItem& item2 = myLFLinkLanes[i - 2];
1232  if (item2.myLink != 0 && item2.myLink->isCont()) {
1233  allowsContinuation = true;
1234  }
1235  }
1236  }
1237  if (allowsContinuation) {
1238  availableSpace[i - 1] = availableSpace[i];
1239  }
1240  }
1241 
1242  for (unsigned int i = 0; hadVehicle && i < myLFLinkLanes.size() && removalBegin < 0; ++i) {
1243  // skip unset links
1244  DriveProcessItem& item = myLFLinkLanes[i];
1245  if (item.myLink == 0) {
1246  continue;
1247  }
1248  /*
1249  SUMOReal impatienceCorrection = MAX2(SUMOReal(0), SUMOReal(SUMOReal(myWaitingTime)));
1250  if (seenSpace<getVehicleType().getLengthWithGap()-impatienceCorrection/10.&&nextSeenNonInternal!=0) {
1251  removalBegin = lastLinkToInternal;
1252  }
1253  */
1254 
1255  SUMOReal leftSpace = availableSpace[i] - getVehicleType().getLengthWithGap();
1256  if (leftSpace < 0/* && item.myLink->willHaveBlockedFoe()*/) {
1257  SUMOReal impatienceCorrection = 0;
1258  /*
1259  if(item.myLink->getState()==LINKSTATE_MINOR) {
1260  impatienceCorrection = MAX2(SUMOReal(0), STEPS2TIME(myWaitingTime));
1261  }
1262  */
1263  if (leftSpace < -impatienceCorrection / 10.) {
1264  removalBegin = i;
1265  }
1266  //removalBegin = i;
1267  }
1268  }
1269  if (removalBegin != -1 && !(removalBegin == 0 && myLane->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL)) {
1270  while (removalBegin < (int)(myLFLinkLanes.size())) {
1272  myLFLinkLanes[removalBegin].myVLinkPass = myLFLinkLanes[removalBegin].myVLinkWait;
1273  if (myLFLinkLanes[removalBegin].myDistance >= brakeGap || (myLFLinkLanes[removalBegin].myDistance > 0 && myState.mySpeed < ACCEL2SPEED(getCarFollowModel().getMaxDecel()))) {
1274  myLFLinkLanes[removalBegin].mySetRequest = false;
1275  }
1276  ++removalBegin;
1277  }
1278  }
1279  }
1280 #else
1281  UNUSED_PARAMETER(lengthsInFront);
1282 #endif
1283  for (DriveItemVector::iterator i = myLFLinkLanes.begin(); i != myLFLinkLanes.end(); ++i) {
1284  if ((*i).myLink != 0) {
1285  const SUMOReal leaveSpeed = estimateLeaveSpeed((*i).myLink, (*i).myArrivalSpeed);
1286  (*i).myLink->setApproaching(this, (*i).myArrivalTime, (*i).myArrivalSpeed, leaveSpeed, (*i).mySetRequest);
1287  }
1288  }
1289 }
1290 
1291 
1292 void
1294  for (MoveReminderCont::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end();) {
1295  if (rem->first->getLane() != 0 && rem->first->getLane() != getLane()) {
1296  ++rem;
1297  } else {
1298  if (rem->first->notifyEnter(*this, reason)) {
1299  ++rem;
1300  } else {
1301  rem = myMoveReminders.erase(rem);
1302  }
1303  }
1304  }
1305 }
1306 
1307 
1308 bool
1309 MSVehicle::enterLaneAtMove(MSLane* enteredLane, bool onTeleporting) {
1310  myAmOnNet = !onTeleporting;
1311  // vaporizing edge?
1312  /*
1313  if (enteredLane->getEdge().isVaporizing()) {
1314  // yep, let's do the vaporization...
1315  myLane = enteredLane;
1316  return true;
1317  }
1318  */
1319  // move mover reminder one lane further
1320  adaptLaneEntering2MoveReminder(*enteredLane);
1321  // set the entered lane as the current lane
1322  myLane = enteredLane;
1323 
1324  // internal edges are not a part of the route...
1325  if (enteredLane->getEdge().getPurpose() != MSEdge::EDGEFUNCTION_INTERNAL) {
1326  ++myCurrEdge;
1327  }
1328  if (!onTeleporting) {
1329  // may be optimized: compute only, if the current or the next have more than one lane...!!!
1330  getBestLanes(true);
1332 #ifndef NO_TRACI
1333  if (myInfluencer != 0) {
1335  }
1336 #endif
1337  } else {
1339  // normal move() isn't called so reset position here
1340  myState.myPos = 0;
1341  }
1342  return hasArrived();
1343 }
1344 
1345 
1346 void
1348  myAmOnNet = true;
1349 #ifdef _MESSAGES
1350  if (myLCMsgEmitter != 0) {
1352  myLCMsgEmitter->writeLaneChangeEvent(myParameter->id, timeStep, myLane, myState.pos(), myState.speed(), enteredLane, getPosition().x(), getPosition().y());
1353  }
1354 #endif
1355  myLane = enteredLane;
1356  // need to update myCurrentLaneInBestLanes
1357  getBestLanes();
1358  // switch to and activate the new lane's reminders
1359  // keep OldLaneReminders
1360  for (std::vector< MSMoveReminder* >::const_iterator rem = enteredLane->getMoveReminders().begin(); rem != enteredLane->getMoveReminders().end(); ++rem) {
1361  addReminder(*rem);
1362  }
1364  /*
1365  for (std::vector<MSLane*>::iterator i = myFurtherLanes.begin(); i != myFurtherLanes.end(); ++i) {
1366  (*i)->resetPartialOccupation(this);
1367  }
1368  myFurtherLanes.clear();
1369  */
1370  if (myState.myPos - getVehicleType().getLength() < 0) {
1371  // we have to rebuild "further lanes"
1372  const MSRoute& route = getRoute();
1374  MSLane* lane = myLane;
1375  SUMOReal leftLength = getVehicleType().getLength() - myState.myPos;
1376  while (i != route.begin() && leftLength > 0) {
1377  /* const MSEdge* const prev = */ *(--i);
1378  lane = lane->getLogicalPredecessorLane();
1379  if (lane == 0) {
1380  break;
1381  }
1382  myFurtherLanes.push_back(lane);
1383  leftLength -= (lane)->setPartialOccupation(this, leftLength);
1384  /*
1385  const std::vector<MSLane::IncomingLaneInfo> &incomingLanes = lane->getIncomingLanes();
1386  for (std::vector<MSLane::IncomingLaneInfo>::const_iterator j = incomingLanes.begin(); j != incomingLanes.end(); ++j) {
1387  if (&(*j).lane->getEdge() == prev) {
1388  #ifdef HAVE_INTERNAL_LANES
1389  (*j).lane->setPartialOccupation(this, leftLength);
1390  #else
1391  leftLength -= (*j).length;
1392  (*j).lane->setPartialOccupation(this, leftLength);
1393  #endif
1394  leftLength -= (*j).lane->getLength();
1395  break;
1396  }
1397  }
1398  */
1399  }
1400  }
1401 #ifndef NO_TRACI
1402  // check if further changes are necessary
1403  if (myInfluencer != 0) {
1405  }
1406 #endif
1407 }
1408 
1409 
1410 void
1412  myState = State(pos, speed);
1413  assert(myState.myPos >= 0);
1414  assert(myState.mySpeed >= 0);
1415  myWaitingTime = 0;
1416  myLane = enteredLane;
1417  // set and activate the new lane's reminders
1418  for (std::vector< MSMoveReminder* >::const_iterator rem = enteredLane->getMoveReminders().begin(); rem != enteredLane->getMoveReminders().end(); ++rem) {
1419  addReminder(*rem);
1420  }
1421  activateReminders(notification);
1422  std::string msg;
1423  if (MSGlobals::gCheckRoutes && !hasValidRoute(msg)) {
1424  throw ProcessError("Vehicle '" + getID() + "' has no valid route. " + msg);
1425  }
1426  myAmOnNet = true;
1427  // build the list of lanes the vehicle is lapping into
1428  SUMOReal leftLength = myType->getLength() - pos;
1429  MSLane* clane = enteredLane;
1430  while (leftLength > 0) {
1431  clane = clane->getLogicalPredecessorLane();
1432  if (clane == 0) {
1433  break;
1434  }
1435  myFurtherLanes.push_back(clane);
1436  leftLength -= (clane)->setPartialOccupation(this, leftLength);
1437  }
1438 }
1439 
1440 
1441 void
1443  for (MoveReminderCont::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end();) {
1444  if (rem->first->notifyLeave(*this, myState.myPos + rem->second, reason)) {
1445  ++rem;
1446  } else {
1447  rem = myMoveReminders.erase(rem);
1448  }
1449  }
1450  if (reason != MSMoveReminder::NOTIFICATION_JUNCTION) {
1451  for (std::vector<MSLane*>::iterator i = myFurtherLanes.begin(); i != myFurtherLanes.end(); ++i) {
1452  (*i)->resetPartialOccupation(this);
1453  }
1454  myFurtherLanes.clear();
1455  }
1456  if (reason >= MSMoveReminder::NOTIFICATION_TELEPORT) {
1457  myAmOnNet = false;
1458  }
1459 }
1460 
1461 
1464  return *myLaneChangeModel;
1465 }
1466 
1467 
1470  return *myLaneChangeModel;
1471 }
1472 
1473 
1474 const std::vector<MSVehicle::LaneQ>&
1475 MSVehicle::getBestLanes(bool forceRebuild, MSLane* startLane) const {
1476 #ifdef DEBUG_VEHICLE_GUI_SELECTION
1477  if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(this)->getGlID())) {
1478  int bla = 0;
1479  myLastBestLanesEdge = 0;
1480  }
1481 #endif
1482 
1483  if (startLane == 0) {
1484  startLane = myLane;
1485  }
1486  assert(startLane != 0);
1487  // update occupancy and current lane index, only, if the vehicle has not moved to a new lane
1488  // (never for internal lanes)
1489  if ((myLastBestLanesEdge == &startLane->getEdge() && !forceRebuild) ||
1490  (startLane->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL && myBestLanes.size() > 0)) {
1491  std::vector<LaneQ>& lanes = *myBestLanes.begin();
1492  std::vector<LaneQ>::iterator i;
1493  for (i = lanes.begin(); i != lanes.end(); ++i) {
1494  SUMOReal nextOccupation = 0;
1495  for (std::vector<MSLane*>::const_iterator j = (*i).bestContinuations.begin() + 1; j != (*i).bestContinuations.end(); ++j) {
1496  nextOccupation += (*j)->getVehLenSum();
1497  }
1498  (*i).nextOccupation = nextOccupation;
1499  if ((*i).lane == startLane) {
1501  }
1502  }
1503  return *myBestLanes.begin();
1504  }
1505  // start rebuilding
1506  myLastBestLanesEdge = &startLane->getEdge();
1507  myBestLanes.clear();
1508 
1509  // get information about the next stop
1510  const MSEdge* nextStopEdge = 0;
1511  const MSLane* nextStopLane = 0;
1512  SUMOReal nextStopPos = 0;
1513  if (!myStops.empty()) {
1514  const Stop& nextStop = myStops.front();
1515  nextStopLane = nextStop.lane;
1516  nextStopEdge = &nextStopLane->getEdge();
1517  nextStopPos = nextStop.startPos;
1518  }
1519  if (myParameter->arrivalLaneProcedure == ARRIVAL_LANE_GIVEN && nextStopEdge == 0) {
1520  nextStopEdge = *(myRoute->end() - 1);
1521  nextStopLane = nextStopEdge->getLanes()[myParameter->arrivalLane];
1522  nextStopPos = myArrivalPos;
1523  }
1524  if (nextStopEdge != 0) {
1525  // make sure that the "wrong" lanes get a penalty. (penalty needs to be
1526  // large enough to overcome a magic threshold in MSLCM_DK2004.cpp:383)
1527  nextStopPos = MIN2((SUMOReal)nextStopPos, (SUMOReal)(nextStopEdge->getLength() - 2 * POSITION_EPS));
1528  }
1529 
1530  // go forward along the next lanes;
1531  int seen = 0;
1532  SUMOReal seenLength = 0;
1533  bool progress = true;
1534  for (MSRouteIterator ce = myCurrEdge; progress;) {
1535  std::vector<LaneQ> currentLanes;
1536  const std::vector<MSLane*>* allowed = 0;
1537  const MSEdge* nextEdge = 0;
1538  if (ce != myRoute->end() && ce + 1 != myRoute->end()) {
1539  nextEdge = *(ce + 1);
1540  allowed = (*ce)->allowedLanes(*nextEdge, myType->getVehicleClass());
1541  }
1542  const std::vector<MSLane*>& lanes = (*ce)->getLanes();
1543  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
1544  LaneQ q;
1545  MSLane* cl = *i;
1546  q.lane = cl;
1547  q.bestContinuations.push_back(cl);
1548  q.bestLaneOffset = 0;
1549  q.length = cl->getLength();
1550  q.allowsContinuation = allowed == 0 || find(allowed->begin(), allowed->end(), cl) != allowed->end();
1551  currentLanes.push_back(q);
1552  }
1553  //
1554  if (nextStopEdge == *ce) {
1555  progress = false;
1556  for (std::vector<LaneQ>::iterator q = currentLanes.begin(); q != currentLanes.end(); ++q) {
1557  if (nextStopLane != 0 && nextStopLane != (*q).lane) {
1558  (*q).allowsContinuation = false;
1559  (*q).length = nextStopPos;
1560  }
1561  }
1562  }
1563 
1564  myBestLanes.push_back(currentLanes);
1565  ++seen;
1566  seenLength += currentLanes[0].lane->getLength();
1567  ++ce;
1568  progress &= (seen <= 4 || seenLength < 3000);
1569  progress &= seen <= 8;
1570  progress &= ce != myRoute->end();
1571  /*
1572  if(progress) {
1573  progress &= (currentLanes.size()!=1||(*ce)->getLanes().size()!=1);
1574  }
1575  */
1576  }
1577 
1578  // we are examining the last lane explicitly
1579  if (myBestLanes.size() != 0) {
1580  SUMOReal bestLength = -1;
1581  int bestThisIndex = 0;
1582  int index = 0;
1583  std::vector<LaneQ>& last = myBestLanes.back();
1584  for (std::vector<LaneQ>::iterator j = last.begin(); j != last.end(); ++j, ++index) {
1585  if ((*j).length > bestLength) {
1586  bestLength = (*j).length;
1587  bestThisIndex = index;
1588  }
1589  }
1590  index = 0;
1591  for (std::vector<LaneQ>::iterator j = last.begin(); j != last.end(); ++j, ++index) {
1592  if ((*j).length < bestLength) {
1593  (*j).bestLaneOffset = bestThisIndex - index;
1594  }
1595  }
1596  }
1597 
1598  // go backward through the lanes
1599  // track back best lane and compute the best prior lane(s)
1600  for (std::vector<std::vector<LaneQ> >::reverse_iterator i = myBestLanes.rbegin() + 1; i != myBestLanes.rend(); ++i) {
1601  std::vector<LaneQ>& nextLanes = (*(i - 1));
1602  std::vector<LaneQ>& clanes = (*i);
1603  MSEdge& cE = clanes[0].lane->getEdge();
1604  int index = 0;
1605  SUMOReal bestConnectedLength = -1;
1606  SUMOReal bestLength = -1;
1607  for (std::vector<LaneQ>::iterator j = nextLanes.begin(); j != nextLanes.end(); ++j, ++index) {
1608  if ((*j).lane->isApproachedFrom(&cE) && bestConnectedLength < (*j).length) {
1609  bestConnectedLength = (*j).length;
1610  }
1611  if (bestLength < (*j).length) {
1612  bestLength = (*j).length;
1613  }
1614  }
1615  if (bestConnectedLength > 0) {
1616  int bestThisIndex = 0;
1617  index = 0;
1618  for (std::vector<LaneQ>::iterator j = clanes.begin(); j != clanes.end(); ++j, ++index) {
1619  LaneQ bestConnectedNext;
1620  bestConnectedNext.length = -1;
1621  if ((*j).allowsContinuation) {
1622  for (std::vector<LaneQ>::const_iterator m = nextLanes.begin(); m != nextLanes.end(); ++m) {
1623  if ((*m).lane->isApproachedFrom(&cE, (*j).lane)) {
1624  if (bestConnectedNext.length < (*m).length || (bestConnectedNext.length == (*m).length && abs(bestConnectedNext.bestLaneOffset) > abs((*m).bestLaneOffset))) {
1625  bestConnectedNext = *m;
1626  }
1627  }
1628  }
1629  if (bestConnectedNext.length == bestConnectedLength && abs(bestConnectedNext.bestLaneOffset) < 2) {
1630  (*j).length += bestLength;
1631  } else {
1632  (*j).length += bestConnectedNext.length;
1633  }
1634  }
1635  if (clanes[bestThisIndex].length < (*j).length || (clanes[bestThisIndex].length == (*j).length && abs(abs(clanes[bestThisIndex].bestLaneOffset > (*j).bestLaneOffset)))) {
1636  bestThisIndex = index;
1637  }
1638  copy(bestConnectedNext.bestContinuations.begin(), bestConnectedNext.bestContinuations.end(), back_inserter((*j).bestContinuations));
1639  }
1640 
1641  index = 0;
1642  for (std::vector<LaneQ>::iterator j = clanes.begin(); j != clanes.end(); ++j, ++index) {
1643  if ((*j).length < clanes[bestThisIndex].length || ((*j).length == clanes[bestThisIndex].length && abs((*j).bestLaneOffset) < abs(clanes[bestThisIndex].bestLaneOffset))) {
1644  (*j).bestLaneOffset = bestThisIndex - index;
1645  } else {
1646  (*j).bestLaneOffset = 0;
1647  }
1648  }
1649 
1650  } else {
1651 
1652  int bestThisIndex = 0;
1653  int bestNextIndex = 0;
1654  int bestDistToNeeded = (int) clanes.size();
1655  index = 0;
1656  for (std::vector<LaneQ>::iterator j = clanes.begin(); j != clanes.end(); ++j, ++index) {
1657  if ((*j).allowsContinuation) {
1658  int nextIndex = 0;
1659  for (std::vector<LaneQ>::const_iterator m = nextLanes.begin(); m != nextLanes.end(); ++m, ++nextIndex) {
1660  if ((*m).lane->isApproachedFrom(&cE, (*j).lane)) {
1661  if (bestDistToNeeded > abs((*m).bestLaneOffset)) {
1662  bestDistToNeeded = abs((*m).bestLaneOffset);
1663  bestThisIndex = index;
1664  bestNextIndex = nextIndex;
1665  }
1666  }
1667  }
1668  }
1669  }
1670  clanes[bestThisIndex].length += nextLanes[bestNextIndex].length;
1671  copy(nextLanes[bestNextIndex].bestContinuations.begin(), nextLanes[bestNextIndex].bestContinuations.end(), back_inserter(clanes[bestThisIndex].bestContinuations));
1672  index = 0;
1673  for (std::vector<LaneQ>::iterator j = clanes.begin(); j != clanes.end(); ++j, ++index) {
1674  if ((*j).length < clanes[bestThisIndex].length || ((*j).length == clanes[bestThisIndex].length && abs((*j).bestLaneOffset) < abs(clanes[bestThisIndex].bestLaneOffset))) {
1675  (*j).bestLaneOffset = bestThisIndex - index;
1676  } else {
1677  (*j).bestLaneOffset = 0;
1678  }
1679  }
1680 
1681  }
1682 
1683  }
1684 
1685  // update occupancy and current lane index
1686  std::vector<LaneQ>& currLanes = *myBestLanes.begin();
1687  std::vector<LaneQ>::iterator i;
1688  for (i = currLanes.begin(); i != currLanes.end(); ++i) {
1689  SUMOReal nextOccupation = 0;
1690  for (std::vector<MSLane*>::const_iterator j = (*i).bestContinuations.begin() + 1; j != (*i).bestContinuations.end(); ++j) {
1691  nextOccupation += (*j)->getVehLenSum();
1692  }
1693  (*i).nextOccupation = nextOccupation;
1694  if ((*i).lane == startLane) {
1696  }
1697  }
1698  return *myBestLanes.begin();
1699 }
1700 
1701 
1702 const std::vector<MSLane*>&
1704  if (myBestLanes.empty() || myBestLanes[0].empty()) {
1705  return myEmptyLaneVector;
1706  }
1707  return (*myCurrentLaneInBestLanes).bestContinuations;
1708 }
1709 
1710 
1711 const std::vector<MSLane*>&
1713  if (myBestLanes.size() == 0) {
1714  return myEmptyLaneVector;
1715  }
1716  for (std::vector<LaneQ>::const_iterator i = myBestLanes[0].begin(); i != myBestLanes[0].end(); ++i) {
1717  if ((*i).lane == l) {
1718  return (*i).bestContinuations;
1719  }
1720  }
1721  return myEmptyLaneVector;
1722 }
1723 
1724 
1725 
1726 SUMOReal
1728 #ifdef DEBUG_VEHICLE_GUI_SELECTION
1729  SUMOReal distance = 1000000.;
1730 #else
1732 #endif
1733  if (isOnRoad() && destEdge != NULL) {
1734  if (&myLane->getEdge() == *myCurrEdge) {
1735  // vehicle is on a normal edge
1736  distance = myRoute->getDistanceBetween(getPositionOnLane(), destPos, *myCurrEdge, destEdge);
1737  } else {
1738  // vehicle is on inner junction edge
1739  distance = myLane->getLength() - getPositionOnLane();
1740  distance += myRoute->getDistanceBetween(0, destPos, *(myCurrEdge + 1), destEdge);
1741  }
1742  }
1743  return distance;
1744 }
1745 
1746 
1747 SUMOReal
1750 }
1751 
1752 
1753 SUMOReal
1756 }
1757 
1758 
1759 SUMOReal
1762 }
1763 
1764 
1765 SUMOReal
1768 }
1769 
1770 
1771 SUMOReal
1774 }
1775 
1776 
1777 SUMOReal
1780 }
1781 
1782 
1783 SUMOReal
1786 }
1787 
1788 
1789 void
1791  if (myPersonDevice == 0) {
1793  myMoveReminders.push_back(std::make_pair(myPersonDevice, 0.));
1794  }
1795  myPersonDevice->addPerson(person);
1796  if (myStops.size() > 0 && myStops.front().reached && myStops.front().triggered) {
1797  myStops.front().duration = 0;
1798  }
1799 }
1800 
1801 
1802 unsigned int
1804  unsigned int boarded = myPersonDevice == 0 ? 0 : myPersonDevice->size();
1805  return boarded + myParameter->personNumber;
1806 }
1807 
1808 
1809 void
1812  int state = getLaneChangeModel().getOwnState();
1813  if ((state & LCA_LEFT) != 0) {
1815  } else if ((state & LCA_RIGHT) != 0) {
1817  } else {
1818  const MSLane* lane = getLane();
1819  MSLinkCont::const_iterator link = lane->succLinkSec(*this, 1, *lane, getBestLanesContinuation());
1820  if (link != lane->getLinkCont().end() && lane->getLength() - getPositionOnLane() < lane->getVehicleMaxSpeed(this) * (SUMOReal) 7.) {
1821  switch ((*link)->getDirection()) {
1822  case LINKDIR_TURN:
1823  case LINKDIR_LEFT:
1824  case LINKDIR_PARTLEFT:
1826  break;
1827  case LINKDIR_RIGHT:
1828  case LINKDIR_PARTRIGHT:
1830  break;
1831  default:
1832  break;
1833  }
1834  }
1835  }
1836 
1837 }
1838 
1839 
1840 void
1842  if (myType->amVehicleSpecific()) {
1843  delete myType;
1844  }
1845  myType = type;
1846 }
1847 
1848 unsigned int
1850  std::vector<MSLane*>::const_iterator laneP = std::find((*myCurrEdge)->getLanes().begin(), (*myCurrEdge)->getLanes().end(), myLane);
1851  return (unsigned int) std::distance((*myCurrEdge)->getLanes().begin(), laneP);
1852 }
1853 
1854 
1855 #ifndef NO_TRACI
1856 bool
1857 MSVehicle::addTraciStop(MSLane* lane, SUMOReal pos, SUMOReal /*radius*/, SUMOTime duration) {
1858  //if the stop exists update the duration
1859  for (std::list<Stop>::iterator iter = myStops.begin(); iter != myStops.end(); iter++) {
1860  if (iter->lane == lane && fabs(iter->endPos - pos) < POSITION_EPS) {
1861  if (duration == 0 && !iter->reached) {
1862  myStops.erase(iter);
1863  } else {
1864  iter->duration = duration;
1865  }
1866  return true;
1867  }
1868  }
1869 
1871  newStop.lane = lane->getID();
1872  newStop.busstop = MSNet::getInstance()->getBusStopID(lane, pos);
1873  newStop.startPos = pos - POSITION_EPS;
1874  newStop.endPos = pos;
1875  newStop.duration = duration;
1876  newStop.until = -1;
1877  newStop.triggered = false;
1878  newStop.parking = false;
1879  newStop.index = STOP_INDEX_END;
1880  return addStop(newStop);
1881 }
1882 
1883 
1886  if (myInfluencer == 0) {
1887  myInfluencer = new Influencer();
1888  }
1889  return *myInfluencer;
1890 }
1891 
1892 
1893 SUMOReal
1895  if (myInfluencer != 0) {
1896  return myInfluencer->getOriginalSpeed();
1897  }
1898  return myState.mySpeed;
1899 }
1900 
1901 
1902 #endif
1903 
1904 
1905 /****************************************************************************/