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-sim.org/
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 <iostream>
41 #include <cassert>
42 #include <cmath>
43 #include <cstdlib>
44 #include <algorithm>
45 #include <map>
47 #include <utils/common/ToString.h>
54 #include <utils/common/StdDefs.h>
55 #include <utils/geom/Line.h>
60 #include <microsim/MSGlobals.h>
61 #include "trigger/MSBusStop.h"
63 #include "MSEdgeWeightsStorage.h"
64 #include "MSLCM_DK2004.h"
65 #include "MSMoveReminder.h"
66 #include "MSPerson.h"
67 #include "MSPersonControl.h"
68 #include "MSLane.h"
69 #include "MSVehicle.h"
70 #include "MSEdge.h"
71 #include "MSVehicleType.h"
72 #include "MSNet.h"
73 #include "MSRoute.h"
74 #include "MSLinkCont.h"
75 
76 #ifdef HAVE_INTERNAL
77 #include <mesosim/MESegment.h>
78 #include <mesosim/MELoop.h>
79 #include "MSGlobals.h"
80 #endif
81 
82 #ifdef CHECK_MEMORY_LEAKS
83 #include <foreign/nvwa/debug_new.h>
84 #endif // CHECK_MEMORY_LEAKS
85 
86 //#define DEBUG_VEHICLE_GUI_SELECTION 1
87 #ifdef DEBUG_VEHICLE_GUI_SELECTION
88 #undef ID_LIST
90 #include <guisim/GUIVehicle.h>
91 #include <guisim/GUILane.h>
92 #endif
93 
94 #define BUS_STOP_OFFSET 0.5
95 
96 
97 // ===========================================================================
98 // static value definitions
99 // ===========================================================================
100 std::vector<MSLane*> MSVehicle::myEmptyLaneVector;
101 
102 
103 // ===========================================================================
104 // method definitions
105 // ===========================================================================
106 /* -------------------------------------------------------------------------
107  * methods of MSVehicle::State
108  * ----------------------------------------------------------------------- */
110  myPos = state.myPos;
111  mySpeed = state.mySpeed;
112 }
113 
114 
117  myPos = state.myPos;
118  mySpeed = state.mySpeed;
119  return *this;
120 }
121 
122 
123 bool
125  return (myPos != state.myPos ||
126  mySpeed != state.mySpeed);
127 }
128 
129 
130 SUMOReal
132  return myPos;
133 }
134 
135 
137  myPos(pos), mySpeed(speed) {}
138 
139 
140 /* -------------------------------------------------------------------------
141  * methods of MSVehicle::Influencer
142  * ----------------------------------------------------------------------- */
143 #ifndef NO_TRACI
145  : mySpeedAdaptationStarted(true), myConsiderSafeVelocity(true),
146  myConsiderMaxAcceleration(true), myConsiderMaxDeceleration(true),
147  myAmVTDControlled(false) {}
148 
149 
151 
152 
153 void
154 MSVehicle::Influencer::setSpeedTimeLine(const std::vector<std::pair<SUMOTime, SUMOReal> >& speedTimeLine) {
155  mySpeedAdaptationStarted = true;
156  mySpeedTimeLine = speedTimeLine;
157 }
158 
159 
160 void
161 MSVehicle::Influencer::setLaneTimeLine(const std::vector<std::pair<SUMOTime, unsigned int> >& laneTimeLine) {
162  myLaneTimeLine = laneTimeLine;
163 }
164 
165 
166 SUMOReal
168  // keep original speed
169  myOriginalSpeed = speed;
170  // remove leading commands which are no longer valid
171  while (mySpeedTimeLine.size() == 1 || (mySpeedTimeLine.size() > 1 && currentTime > mySpeedTimeLine[1].first)) {
172  mySpeedTimeLine.erase(mySpeedTimeLine.begin());
173  }
174  // do nothing if the time line does not apply for the current time
175  if (mySpeedTimeLine.size() < 2 || currentTime < mySpeedTimeLine[0].first) {
176  return speed;
177  }
178  // compute and set new speed
179  if (!mySpeedAdaptationStarted) {
180  mySpeedTimeLine[0].second = speed;
181  mySpeedAdaptationStarted = true;
182  }
183  currentTime += DELTA_T;
184  const SUMOReal td = STEPS2TIME(currentTime - mySpeedTimeLine[0].first) / STEPS2TIME(mySpeedTimeLine[1].first + DELTA_T - mySpeedTimeLine[0].first);
185  speed = mySpeedTimeLine[0].second - (mySpeedTimeLine[0].second - mySpeedTimeLine[1].second) * td;
186  if (myConsiderSafeVelocity) {
187  speed = MIN2(speed, vSafe);
188  }
189  if (myConsiderMaxAcceleration) {
190  speed = MIN2(speed, vMax);
191  }
192  if (myConsiderMaxDeceleration) {
193  speed = MAX2(speed, vMin);
194  }
195  return speed;
196 }
197 
198 
200 MSVehicle::Influencer::checkForLaneChanges(SUMOTime currentTime, const MSEdge& currentEdge, unsigned int currentLaneIndex) {
201  // remove leading commands which are no longer valid
202  while (myLaneTimeLine.size() == 1 || (myLaneTimeLine.size() > 1 && currentTime > myLaneTimeLine[1].first)) {
203  myLaneTimeLine.erase(myLaneTimeLine.begin());
204  }
205  // do nothing if the time line does not apply for the current time
206  if (myLaneTimeLine.size() < 2 || currentTime < myLaneTimeLine[0].first) {
207  return REQUEST_NONE;
208  }
209  unsigned int destinationLaneIndex = myLaneTimeLine[1].second;
210  if ((unsigned int)currentEdge.getLanes().size() <= destinationLaneIndex) {
211  return REQUEST_NONE;
212  }
213  if (currentLaneIndex > destinationLaneIndex) {
214  return REQUEST_RIGHT;
215  } else if (currentLaneIndex < destinationLaneIndex) {
216  return REQUEST_LEFT;
217  } else {
218  return REQUEST_HOLD;
219  }
220 }
221 
222 
223 void
225  myConsiderSafeVelocity = value;
226 }
227 
228 
229 void
231  myConsiderMaxAcceleration = value;
232 }
233 
234 
235 void
237  myConsiderMaxDeceleration = value;
238 }
239 
240 
241 void
245  if (myVTDRoute.size() != 0) {
246  v->replaceRouteEdges(myVTDRoute, true);
247  }
248  v->myCurrEdge += myVTDEdgeOffset;
249  if (myVTDPos > myVTDLane->getLength()) {
250  myVTDPos = myVTDLane->getLength();
251  }
252  myVTDLane->forceVehicleInsertion(v, myVTDPos);
253  v->getBestLanes();
254  myAmVTDControlled = false;
255 }
256 
257 #endif
258 
259 
260 /* -------------------------------------------------------------------------
261  * MSVehicle-methods
262  * ----------------------------------------------------------------------- */
264  delete myLaneChangeModel;
265  // other
266  delete myEdgeWeights;
267  for (std::vector<MSLane*>::iterator i = myFurtherLanes.begin(); i != myFurtherLanes.end(); ++i) {
268  (*i)->resetPartialOccupation(this);
269  }
270  myFurtherLanes.clear();
271  for (DriveItemVector::iterator i = myLFLinkLanes.begin(); i != myLFLinkLanes.end(); ++i) {
272  if ((*i).myLink != 0) {
273  (*i).myLink->removeApproaching(this);
274  }
275  }
276  //
277  if (myType->amVehicleSpecific()) {
278  delete myType;
279  }
280 #ifndef NO_TRACI
281  delete myInfluencer;
282 #endif
283 }
284 
285 
287  const MSRoute* route,
288  const MSVehicleType* type,
289  SUMOReal speedFactor,
290  int /*vehicleIndex*/) :
291  MSBaseVehicle(pars, route, type, speedFactor),
292  myWaitingTime(0),
293  myState(0, 0), //
294  myLane(0),
296  myPersonDevice(0),
297  myAcceleration(0),
298  mySignals(0),
299  myAmOnNet(false),
301  myHaveToWaitOnNextLink(false),
302  myEdgeWeights(0)
303 #ifndef NO_TRACI
304  , myInfluencer(0)
305 #endif
306 {
307  for (std::vector<SUMOVehicleParameter::Stop>::iterator i = pars->stops.begin(); i != pars->stops.end(); ++i) {
308  if (!addStop(*i)) {
309  throw ProcessError("Stop for vehicle '" + pars->id +
310  "' on lane '" + i->lane + "' is not downstream the current route.");
311  }
312  }
313  for (std::vector<SUMOVehicleParameter::Stop>::const_iterator i = route->getStops().begin(); i != route->getStops().end(); ++i) {
314  if (!addStop(*i)) {
315  throw ProcessError("Stop for vehicle '" + pars->id +
316  "' on lane '" + i->lane + "' is not downstream the current route.");
317  }
318  }
319  const MSLane* const depLane = (*myCurrEdge)->getDepartLane(*this);
320  if (depLane == 0) {
321  throw ProcessError("Invalid departlane definition for vehicle '" + pars->id + "'.");
322  }
323  if (pars->departSpeedProcedure == DEPART_SPEED_GIVEN && pars->departSpeed > depLane->getSpeedLimit()) {
324  throw ProcessError("Departure speed for vehicle '" + pars->id +
325  "' is too high for the departure lane '" + depLane->getID() + "'.");
326  }
327  if (pars->departSpeedProcedure == DEPART_SPEED_GIVEN && pars->departSpeed > type->getMaxSpeed()) {
328  throw ProcessError("Departure speed for vehicle '" + pars->id +
329  "' is too high for the vehicle type '" + type->getID() + "'.");
330  }
331  myLaneChangeModel = new MSLCM_DK2004(*this);
333 }
334 
335 
336 void
339  for (DriveItemVector::iterator i = myLFLinkLanes.begin(); i != myLFLinkLanes.end(); ++i) {
340  if ((*i).myLink != 0) {
341  (*i).myLink->removeApproaching(this);
342  }
343  }
344  leaveLane(reason);
345 }
346 
347 
348 // ------------ interaction with the route
349 bool
351  return myCurrEdge == myRoute->end() - 1 && myState.myPos > myArrivalPos - POSITION_EPS;
352 }
353 
354 
355 bool
356 MSVehicle::replaceRoute(const MSRoute* newRoute, bool onInit) {
357  const MSEdgeVector& edges = newRoute->getEdges();
358  // assert the vehicle may continue (must not be "teleported" or whatever to another position)
359  if (!onInit && !newRoute->contains(*myCurrEdge)) {
360  return false;
361  }
362 
363  // rebuild in-vehicle route information
364  if (onInit) {
365  myCurrEdge = newRoute->begin();
366  } else {
367  myCurrEdge = find(edges.begin(), edges.end(), *myCurrEdge);
368  }
369  // check whether the old route may be deleted (is not used by anyone else)
370  newRoute->addReference();
371  myRoute->release();
372  // assign new route
373  myRoute = newRoute;
375  if (!onInit) {
376  getBestLanes(true);
377  }
378  // update arrival definition
380  // save information that the vehicle was rerouted
383  // recheck stops
384  for (std::list<Stop>::iterator iter = myStops.begin(); iter != myStops.end();) {
385  if (find(edges.begin(), edges.end(), &iter->lane->getEdge()) == edges.end()) {
386  iter = myStops.erase(iter);
387  } else {
388  iter->edge = find(edges.begin(), edges.end(), &iter->lane->getEdge());
389  ++iter;
390  }
391  }
392  return true;
393 }
394 
395 
396 bool
397 MSVehicle::willPass(const MSEdge* const edge) const {
398  return find(myCurrEdge, myRoute->end(), edge) != myRoute->end();
399 }
400 
401 
402 unsigned int
404  return (unsigned int) std::distance(myRoute->begin(), myCurrEdge);
405 }
406 
407 
408 void
409 MSVehicle::resetRoutePosition(unsigned int index) {
410  myCurrEdge = myRoute->begin() + index;
411  // !!! hack
412  myArrivalPos = (*(myRoute->end() - 1))->getLanes()[0]->getLength();
413 }
414 
415 
416 
419  return _getWeightsStorage();
420 }
421 
422 
425  return _getWeightsStorage();
426 }
427 
428 
431  if (myEdgeWeights == 0) {
433  }
434  return *myEdgeWeights;
435 }
436 
437 
438 // ------------ Interaction with move reminders
439 void
441  // This erasure-idiom works for all stl-sequence-containers
442  // See Meyers: Effective STL, Item 9
443  for (MoveReminderCont::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end();) {
444  if (!rem->first->notifyMove(*this, oldPos + rem->second, newPos + rem->second, newSpeed)) {
445 #ifdef _DEBUG
446  if (myTraceMoveReminders) {
447  traceMoveReminder("notifyMove", rem->first, rem->second, false);
448  }
449 #endif
450  rem = myMoveReminders.erase(rem);
451  } else {
452 #ifdef _DEBUG
453  if (myTraceMoveReminders) {
454  traceMoveReminder("notifyMove", rem->first, rem->second, true);
455  }
456 #endif
457  ++rem;
458  }
459  }
460 }
461 
462 
463 void
465  // save the old work reminders, patching the position information
466  // add the information about the new offset to the old lane reminders
467  const SUMOReal oldLaneLength = myLane->getLength();
468  for (MoveReminderCont::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end(); ++rem) {
469  rem->second += oldLaneLength;
470 #ifdef _DEBUG
471  if (myTraceMoveReminders) {
472  traceMoveReminder("adaptedPos", rem->first, rem->second, true);
473  }
474 #endif
475  }
476  for (std::vector< MSMoveReminder* >::const_iterator rem = enteredLane.getMoveReminders().begin(); rem != enteredLane.getMoveReminders().end(); ++rem) {
477  addReminder(*rem);
478  }
479 }
480 
481 
482 // ------------ Other getter methods
483 Position
485  if (myLane == 0) {
486  return Position::INVALID;
487  }
488  if (isParking()) {
489  PositionVector shp = myLane->getEdge().getLanes()[0]->getShape();
492  }
494  if (getLaneChangeModel().isChangingLanes()) {
496  Line line = getLaneChangeModel().isLaneChangeMidpointPassed() ? Line(other, result) : Line(result, other);
497  return line.getPositionAtDistance(getLaneChangeModel().getLaneChangeCompletion() * line.length());
498  }
499  return result;
500 }
501 
502 
503 SUMOReal
506  Position p2 = myFurtherLanes.size() > 0
507  ? myFurtherLanes.back()->getShape().positionAtOffset(myFurtherLanes.back()->getPartialOccupatorEnd())
509  SUMOReal result = (p1 != p2 ?
510  atan2(p1.x() - p2.x(), p2.y() - p1.y()) * 180. / PI :
514  result += getLaneChangeModel().getLaneChangeDirection() * angleOffset;
515  }
516  return result;
517 }
518 
519 
520 // ------------
521 bool
523  Stop stop;
524  stop.lane = MSLane::dictionary(stopPar.lane);
525  stop.busstop = MSNet::getInstance()->getBusStop(stopPar.busstop);
526  stop.startPos = stopPar.startPos;
527  stop.endPos = stopPar.endPos;
528  stop.duration = stopPar.duration;
529  stop.until = stopPar.until;
530  stop.awaitedPersons = stopPar.awaitedPersons;
531  if (stop.until != -1) {
532  stop.until += untilOffset;
533  }
534  stop.triggered = stopPar.triggered;
535  stop.parking = stopPar.parking;
536  stop.reached = false;
537  if (stop.startPos < 0 || stop.endPos > stop.lane->getLength()) {
538  return false;
539  }
540  stop.edge = find(myCurrEdge, myRoute->end(), &stop.lane->getEdge());
541  MSRouteIterator prevStopEdge = myCurrEdge;
542  SUMOReal prevStopPos = myState.myPos;
543  // where to insert the stop
544  std::list<Stop>::iterator iter = myStops.begin();
545  if (stopPar.index == STOP_INDEX_END || stopPar.index >= static_cast<int>(myStops.size())) {
546  if (myStops.size() > 0) {
547  prevStopEdge = myStops.back().edge;
548  prevStopPos = myStops.back().endPos;
549  iter = myStops.end();
550  stop.edge = find(prevStopEdge, myRoute->end(), &stop.lane->getEdge());
551  }
552  } else {
553  if (stopPar.index == STOP_INDEX_FIT) {
554  while (iter != myStops.end() && (iter->edge < stop.edge ||
555  (iter->endPos < stop.endPos && iter->edge == stop.edge))) {
556  prevStopEdge = iter->edge;
557  prevStopPos = iter->endPos;
558  ++iter;
559  }
560  } else {
561  int index = stopPar.index;
562  while (index > 0) {
563  prevStopEdge = iter->edge;
564  prevStopPos = iter->endPos;
565  ++iter;
566  --index;
567  }
568  stop.edge = find(prevStopEdge, myRoute->end(), &stop.lane->getEdge());
569  }
570  }
571  if (stop.edge == myRoute->end() || prevStopEdge > stop.edge ||
572  (prevStopEdge == stop.edge && prevStopPos > stop.endPos)) {
573  return false;
574  }
575  // David.C:
576  //if (!stop.parking && (myCurrEdge == stop.edge && myState.myPos > stop.endPos - getCarFollowModel().brakeGap(myState.mySpeed))) {
578  return false;
579  }
580  myStops.insert(iter, stop);
581  return true;
582 }
583 
584 
585 bool
587  return !myStops.empty() && myStops.begin()->reached;
588 }
589 
590 
591 bool
593  return isStopped() && myStops.begin()->parking;
594 }
595 
596 
597 bool
599  return isStopped() && myStops.begin()->triggered;
600 }
601 
602 
603 SUMOReal
605  if (myStops.empty()) {
606  // no stops; pass
607  return currentVelocity;
608  }
609  Stop& stop = myStops.front();
610  if (stop.reached) {
611  // ok, we have already reached the next stop
612  // any waiting persons may board now
613  bool boarded = MSNet::getInstance()->getPersonControl().boardAnyWaiting(&myLane->getEdge(), this);
614  boarded &= stop.awaitedPersons.size() == 0;
615  if (boarded) {
616  if (stop.busstop != 0) {
617  const std::vector<MSPerson*>& persons = myPersonDevice->getPersons();
618  for (std::vector<MSPerson*>::const_iterator i = persons.begin(); i != persons.end(); ++i) {
619  stop.busstop->removePerson(*i);
620  }
621  }
622  // the triggering condition has been fulfilled. Maybe we want to wait a bit longer for additional riders (car pooling)
623  stop.triggered = false;
627  }
628  }
629  if (stop.duration <= 0 && !stop.triggered) {
630  // we have waited long enough and fulfilled any passenger-requirements
631  if (stop.busstop != 0) {
632  // inform bus stop about leaving it
633  stop.busstop->leaveFrom(this);
634  }
635  // the current stop is no longer valid
637  myStops.pop_front();
638  // do not count the stopping time towards gridlock time.
639  // Other outputs use an independent counter and are not affected.
640  myWaitingTime = 0;
641  // maybe the next stop is on the same edge; let's rebuild best lanes
642  getBestLanes(true);
643  // continue as wished...
644  } else {
645  // we have to wait some more time
647  // we can only register after waiting for one step. otherwise we might falsely signal a deadlock
650  }
651  stop.duration -= DELTA_T;
652  return 0;
653  }
654  } else {
655  // is the next stop on the current lane?
656  if (stop.edge == myCurrEdge) {
657  // get the stopping position
658  SUMOReal endPos = stop.endPos;
659  bool busStopsMustHaveSpace = true;
660  if (stop.busstop != 0) {
661  // on bus stops, we have to wait for free place if they are in use...
662  endPos = stop.busstop->getLastFreePos(*this);
663  if (endPos - 5. < stop.busstop->getBeginLanePosition()) { // !!! explicit offset
664  busStopsMustHaveSpace = false;
665  }
666  }
667  if (myState.pos() + getVehicleType().getMinGap() >= endPos - BUS_STOP_OFFSET && busStopsMustHaveSpace) {
668  // ok, we may stop (have reached the stop)
669  stop.reached = true;
671  // compute stopping time
672  if (stop.until >= 0) {
673  if (stop.duration == -1) {
675  } else {
677  }
678  }
679  if (stop.busstop != 0) {
680  // let the bus stop know the vehicle
682  }
683  }
684  // decelerate
685  return getCarFollowModel().stopSpeed(this, getSpeed(), endPos - myState.pos());
686  }
687  }
688  return currentVelocity;
689 }
690 
691 
692 void
693 MSVehicle::planMove(const SUMOTime t, const MSVehicle* pred, const SUMOReal lengthsInFront) {
695  checkRewindLinkLanes(lengthsInFront, myLFLinkLanes);
697 }
698 
699 
700 void
701 MSVehicle::planMoveInternal(const SUMOTime t, const MSVehicle* pred, DriveItemVector& lfLinks) const {
702 #ifdef DEBUG_VEHICLE_GUI_SELECTION
703  if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(this)->getGlID())) {
704  int bla = 0;
705  }
706 #endif
707  // remove information about approaching links, will be reset later in this step
708  for (DriveItemVector::iterator i = lfLinks.begin(); i != lfLinks.end(); ++i) {
709  if ((*i).myLink != 0) {
710  (*i).myLink->removeApproaching(this);
711  }
712  }
713  lfLinks.clear();
714  //
715  const MSCFModel& cfModel = getCarFollowModel();
716  const SUMOReal vehicleLength = getVehicleType().getLength();
717  const SUMOReal maxV = cfModel.maxNextSpeed(myState.mySpeed, this);
718  SUMOReal laneMaxV = myLane->getVehicleMaxSpeed(this);
719  // vBeg is the initial maximum velocity of this vehicle in this step
720  SUMOReal v = MIN2(maxV, laneMaxV);
721 #ifndef NO_TRACI
722  if (myInfluencer != 0) {
723  const SUMOReal vMin = MAX2(SUMOReal(0), cfModel.getSpeedAfterMaxDecel(myState.mySpeed));
724  v = myInfluencer->influenceSpeed(MSNet::getInstance()->getCurrentTimeStep(), v, v, vMin, maxV);
725  // !!! recheck - why is it done, here?
726  if (myInfluencer->isVTDControlled()) {
727  return; // !!! temporary
728  }
729  }
730 #endif
731 
732  const SUMOReal dist = SPEED2DIST(maxV) + cfModel.brakeGap(maxV);
733  const std::vector<MSLane*>& bestLaneConts = getBestLanesContinuation();
734  assert(bestLaneConts.size() > 0);
735 #ifdef HAVE_INTERNAL_LANES
736  bool hadNonInternal = false;
737 #else
738  bool hadNonInternal = true;
739 #endif
740  SUMOReal seen = myLane->getLength() - myState.myPos; // the distance already "seen"; in the following always up to the end of the current "lane"
741  SUMOReal seenNonInternal = 0;
742  SUMOReal vLinkPass = MIN2(estimateSpeedAfterDistance(seen, v, getVehicleType().getCarFollowModel().getMaxAccel()), laneMaxV); // upper bound
743  unsigned int view = 0;
744  DriveProcessItem* lastLink = 0;
745  SUMOReal gap = 0;
746  if (pred != 0) {
747  if (pred == myLane->getPartialOccupator()) {
749  } else {
751  }
752  }
753  std::pair<const MSVehicle*, SUMOReal> leaderInfo = std::make_pair(pred, gap);
754  // iterator over subsequent lanes and fill lfLinks until stopping distance or stopped
755  const MSLane* lane = myLane;
756  while (true) {
757  // check leader on lane
758  // leader is given for the first edge only
759  adaptToLeader(leaderInfo, seen, lastLink, lane, v, vLinkPass);
760 
761  // process stops
762  if (!myStops.empty() && &myStops.begin()->lane->getEdge() == &lane->getEdge()) {
763  // we are approaching a stop on the edge; must not drive further
764  const Stop& stop = *myStops.begin();
765  SUMOReal stopDist = stop.busstop == 0 ? seen + stop.endPos - lane->getLength() : seen + stop.busstop->getLastFreePos(*this) - POSITION_EPS - lane->getLength();
766  SUMOReal stopSpeed = cfModel.stopSpeed(this, getSpeed(), stopDist);
767  if (lastLink != 0) {
768  lastLink->adaptLeaveSpeed(stopSpeed);
769  }
770  v = MIN2(v, stopSpeed);
771  lfLinks.push_back(DriveProcessItem(v, stopDist));
772  break;
773  }
774 
775  // move to next lane
776  // get the next link used
777  MSLinkCont::const_iterator link = myLane->succLinkSec(*this, view + 1, *lane, bestLaneConts);
778  // check whether the vehicle is on its final edge
779  if (myCurrEdge + view + 1 == myRoute->end()) {
781  myParameter->arrivalSpeed : laneMaxV);
782  // subtract the arrival speed from the remaining distance so we get one additional driving step with arrival speed
783  const SUMOReal distToArrival = seen + myArrivalPos - lane->getLength() - SPEED2DIST(arrivalSpeed);
784  const SUMOReal va = cfModel.freeSpeed(this, getSpeed(), distToArrival, arrivalSpeed);
785  v = MIN2(v, va);
786  if (lastLink != 0) {
787  lastLink->adaptLeaveSpeed(va);
788  }
789  lfLinks.push_back(DriveProcessItem(v, seen));
790  break;
791  }
792  // check whether the lane is a dead end
793  // @todo: recheck propper value for laneStopOffset based on real-world
794  // measurements.
795  // For links that require stopping it is important that vehicles stop close to the stopping line
796  const SUMOReal laneStopOffset = ((lane->getLength() <= getVehicleType().getMinGap()
797  || (!lane->isLinkEnd(link) && (
798  (*link)->getState() == LINKSTATE_ALLWAY_STOP || (*link)->getState() == LINKSTATE_STOP)))
800  const SUMOReal stopDist = MAX2(SUMOReal(0), seen - laneStopOffset);
801  if (lane->isLinkEnd(link)) {
802  SUMOReal va = MIN2(cfModel.stopSpeed(this, getSpeed(), stopDist), laneMaxV);
803  if (lastLink != 0) {
804  lastLink->adaptLeaveSpeed(va);
805  }
806  v = MIN2(va, v);
807  lfLinks.push_back(DriveProcessItem(v, seen));
808  break;
809  }
810  // check whether we need to slow down in order to finish a continuous lane change
811  if (getLaneChangeModel().isChangingLanes()) {
812  if ( // slow down to finish lane change before a turn lane
813  ((*link)->getDirection() == LINKDIR_LEFT || (*link)->getDirection() == LINKDIR_RIGHT) ||
814  // slow down to finish lane change before the shadow lane ends
816  (*link)->getViaLaneOrLane()->getParallelLane(-getLaneChangeModel().getLaneChangeDirection()) == 0)) {
817  const SUMOReal timeRemaining = STEPS2TIME((1 - getLaneChangeModel().getLaneChangeCompletion()) * MSGlobals::gLaneChangeDuration);
818  const SUMOReal va = seen / timeRemaining;
819  v = MIN2(va, v);
820  }
821  }
822 
823  const bool yellowOrRed = (*link)->getState() == LINKSTATE_TL_RED ||
824  (*link)->getState() == LINKSTATE_TL_YELLOW_MAJOR ||
825  (*link)->getState() == LINKSTATE_TL_YELLOW_MINOR;
826  const bool setRequest = v > 0; // even if red, if we cannot break we should issue a request
827  const SUMOReal vLinkWait = MIN2(v, cfModel.stopSpeed(this, getSpeed(), stopDist));
828  if (yellowOrRed && seen > cfModel.brakeGap(myState.mySpeed) - myState.mySpeed * cfModel.getHeadwayTime()) {
829  // the vehicle is able to brake in front of a yellow/red traffic light
830  lfLinks.push_back(DriveProcessItem(*link, vLinkWait, vLinkWait, false, t + TIME2STEPS(seen / vLinkWait), vLinkWait, 0, SUMOTime_MAX, stopDist));
831  // XXX division by 0 (vLinkWait) should be avoided
832  //lfLinks.push_back(DriveProcessItem(0, vLinkWait, vLinkWait, false, 0, 0, stopDist));
833  break;
834  }
835 
836 #ifdef HAVE_INTERNAL_LANES
837  // we want to pass the link but need to check for foes on internal lanes
838  const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(seen - getVehicleType().getMinGap());
839  for (MSLink::LinkLeaders::const_iterator it = linkLeaders.begin(); it != linkLeaders.end(); ++it) {
840  // the vehicle to enter the junction first has priority
841  const MSVehicle* leader = it->first;
842  if (leader->myLinkLeaders.count(getID()) == 0) {
843  // leader isn't already following us, now we follow it
844  myLeaderForLink[*link] = leader->getID();
845  myLinkLeaders.insert(leader->getID());
846  adaptToLeader(*it, seen, lastLink, lane, v, vLinkPass);
847  if (view > 0) {
848  // we are not yet on the junction with this linkLeader.
849  // at least we can drive up to the junction and stop there
850  v = MAX2(v, vLinkWait);
851  }
852  }
853  }
854 #endif
855 
856  if (lastLink != 0) {
857  lastLink->adaptLeaveSpeed(laneMaxV);
858  }
859  SUMOReal arrivalSpeed = vLinkPass;
860  SUMOTime arrivalTime;
861  // vehicles should decelerate when approaching a minor link
862  if (!(*link)->havePriority() && stopDist > cfModel.getMaxDecel()) {
863  // vehicle decelerates just enough to be able to stop if necessary and then accelerates
864  arrivalSpeed = cfModel.getMaxDecel() + cfModel.getMaxAccel();
865  const SUMOReal v1 = MAX2(vLinkWait, arrivalSpeed);
866  // now + time spent decelerating + time spent at full speed
867  arrivalTime = t + TIME2STEPS((v1 - arrivalSpeed) / cfModel.getMaxDecel()
868  + (seen - (v1 * v1 - arrivalSpeed * arrivalSpeed) * 0.5 / cfModel.getMaxDecel()) / vLinkWait);
869  } else {
870  const SUMOReal accel = (vLinkPass >= v) ? cfModel.getMaxAccel() : -cfModel.getMaxDecel();
871  const SUMOReal accelTime = (vLinkPass - v) / accel;
872  const SUMOReal accelWay = accelTime * (vLinkPass + v) * 0.5;
873  arrivalTime = t + TIME2STEPS(accelTime + MAX2(SUMOReal(0), seen - accelWay) / vLinkPass);
874  }
875  // compute speed, time if vehicle starts braking now
876  // if stopping is possible, arrivalTime can be arbitrarily large. A small value keeps fractional times (impatience) meaningful
877  SUMOReal arrivalSpeedBraking = 0;
878  SUMOTime arrivalTimeBraking = arrivalTime + TIME2STEPS(30);
879  if (seen < cfModel.brakeGap(v)) {
880  // vehicle cannot come to a complete stop in time
881  // Because we use a continuous formula for computiing the possible slow-down
882  // we need to handle the mismatch with the discrete dynamics
883  if (seen < v) {
884  arrivalSpeedBraking = arrivalSpeed; // no time left for braking after this step
885  } else if (2 * seen * -getVehicleType().getCarFollowModel().getMaxDecel() + v * v >= 0) {
886  arrivalSpeedBraking = estimateSpeedAfterDistance(seen, v, -getVehicleType().getCarFollowModel().getMaxDecel());
887  }
888  // due to discrecte/continuous mismatch we have to ensure that braking actually helps
889  arrivalSpeedBraking = MIN2(arrivalSpeedBraking, arrivalSpeed);
890  arrivalTimeBraking = MAX2(arrivalTime, t + TIME2STEPS(seen / ((v + arrivalSpeedBraking) * 0.5)));
891  }
892  lfLinks.push_back(DriveProcessItem(*link, v, vLinkWait, setRequest,
893  arrivalTime, arrivalSpeed,
894  arrivalTimeBraking, arrivalSpeedBraking,
895  stopDist,
896  estimateLeaveSpeed(*link, vLinkPass)));
897 #ifdef HAVE_INTERNAL_LANES
898  if ((*link)->getViaLane() == 0) {
899  hadNonInternal = true;
900  ++view;
901  }
902 #else
903  ++view;
904 #endif
905  if (!setRequest || ((v <= 0 || seen > dist) && hadNonInternal && seenNonInternal > vehicleLength * 2)) {
906  break;
907  }
908  // get the following lane
909  lane = (*link)->getViaLaneOrLane();
910  laneMaxV = lane->getVehicleMaxSpeed(this);
911  // the link was passed
912  // compute the velocity to use when the link is not blocked by other vehicles
913  // the vehicle shall be not faster when reaching the next lane than allowed
914  const SUMOReal va = MAX2(laneMaxV, cfModel.freeSpeed(this, getSpeed(), seen, laneMaxV));
915  v = MIN2(va, v);
916  seenNonInternal += lane->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL ? 0 : lane->getLength();
917  seen += lane->getLength();
918  leaderInfo = lane->getLastVehicleInformation();
919  leaderInfo.second = leaderInfo.second + seen - lane->getLength() - getVehicleType().getMinGap();
920  vLinkPass = MIN2(estimateSpeedAfterDistance(lane->getLength(), v, getVehicleType().getCarFollowModel().getMaxAccel()), laneMaxV); // upper bound
921  lastLink = &lfLinks.back();
922  }
923 }
924 
925 
926 void
927 MSVehicle::adaptToLeader(const std::pair<const MSVehicle*, SUMOReal> leaderInfo,
928  const SUMOReal seen, DriveProcessItem* const lastLink,
929  const MSLane* const lane, SUMOReal& v, SUMOReal& vLinkPass) const {
930  if (leaderInfo.first != 0) {
931  const MSCFModel& cfModel = getCarFollowModel();
932  SUMOReal vsafeLeader = 0;
933  if (leaderInfo.second >= 0) {
934  vsafeLeader = cfModel.followSpeed(this, getSpeed(), leaderInfo.second, leaderInfo.first->getSpeed(), leaderInfo.first->getCarFollowModel().getMaxDecel());
935  } else {
936  // the leading, in-lapping vehicle is occupying the complete next lane
937  // stop before entering this lane
938  vsafeLeader = cfModel.stopSpeed(this, getSpeed(), seen - lane->getLength() - POSITION_EPS);
939  }
940  if (lastLink != 0) {
941  lastLink->adaptLeaveSpeed(vsafeLeader);
942  }
943  v = MIN2(v, vsafeLeader);
944  vLinkPass = MIN2(vLinkPass, vsafeLeader);
945  }
946 }
947 
948 
949 bool
951 #ifdef DEBUG_VEHICLE_GUI_SELECTION
952  if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(this)->getGlID())) {
953  int bla = 0;
954  }
955 #endif
956  // get vsafe
957  SUMOReal vSafe = 0;
958  myHaveToWaitOnNextLink = false;
959 #ifndef NO_TRACI
960  if (myInfluencer != 0) {
961  if (myInfluencer->isVTDControlled()) {
962  return false;
963  }
964  }
965 #endif
966 
967  assert(myLFLinkLanes.size() != 0 || (myInfluencer != 0 && myInfluencer->isVTDControlled()));
968  DriveItemVector::iterator i;
969  bool braking = false;
970  bool lastWasGreenCont = false;
971  for (i = myLFLinkLanes.begin(); i != myLFLinkLanes.end(); ++i) {
972  MSLink* link = (*i).myLink;
973  // the vehicle must change the lane on one of the next lanes
974  if (link != 0 && (*i).mySetRequest) {
975  const LinkState ls = link->getState();
976  // vehicles should brake when running onto a yellow light if the distance allows to halt in front
977  const bool yellow = ls == LINKSTATE_TL_YELLOW_MAJOR || ls == LINKSTATE_TL_YELLOW_MINOR;
979  if (yellow && ((*i).myDistance > brakeGap || myState.mySpeed < ACCEL2SPEED(getCarFollowModel().getMaxDecel()))) {
980  vSafe = (*i).myVLinkWait;
981  braking = true;
982  lastWasGreenCont = false;
983  link->removeApproaching(this);
984  break;
985  }
986  //
987  const bool opened = yellow || link->opened((*i).myArrivalTime, (*i).myArrivalSpeed, (*i).getLeaveSpeed(),
989  // vehicles should decelerate when approaching a minor link
990  // XXX check if this is still necessary
991  if (opened && !lastWasGreenCont && !link->havePriority() && (*i).myDistance > getCarFollowModel().getMaxDecel()) {
992  vSafe = (*i).myVLinkWait;
993  braking = true;
994  lastWasGreenCont = false;
995  if (ls == LINKSTATE_EQUAL) {
996  link->removeApproaching(this);
997  }
998  break; // could be revalidated
999  }
1000  // have waited; may pass if opened...
1001  if (opened) {
1002  vSafe = (*i).myVLinkPass;
1003  lastWasGreenCont = link->isCont() && (ls == LINKSTATE_TL_GREEN_MAJOR);
1004  } else {
1005  lastWasGreenCont = false;
1006  vSafe = (*i).myVLinkWait;
1007  braking = true;
1008  if (ls == LINKSTATE_EQUAL) {
1009  link->removeApproaching(this);
1010  }
1011  break;
1012  }
1013  } else {
1014  vSafe = (*i).myVLinkWait;
1015  braking = vSafe < getSpeed();
1016  break;
1017  }
1018  }
1019  if (braking) {
1020  myHaveToWaitOnNextLink = true;
1021  }
1022 
1023  SUMOReal vNext = getCarFollowModel().moveHelper(this, vSafe);
1024  //if (vNext > vSafe) {
1025  // WRITE_WARNING("vehicle '" + getID() + "' cannot brake hard enough to reach safe speed "
1026  // + toString(vSafe) + ", moving at " + toString(vNext) + " instead. time="
1027  // + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
1028  //}
1029  vNext = MAX2(vNext, (SUMOReal) 0.);
1030 #ifndef NO_TRACI
1031  if (myInfluencer != 0) {
1033  const SUMOReal vMin = MAX2(SUMOReal(0), getVehicleType().getCarFollowModel().getSpeedAfterMaxDecel(myState.mySpeed));
1034  vNext = myInfluencer->influenceSpeed(MSNet::getInstance()->getCurrentTimeStep(), vNext, vSafe, vMin, vMax);
1035  if (myInfluencer->isVTDControlled()) {
1036  vNext = 0;
1037  }
1038  }
1039 #endif
1040  // visit waiting time
1041  if (vNext <= SUMO_const_haltingSpeed) {
1043  braking = true;
1044  } else {
1045  myWaitingTime = 0;
1046  }
1047  if (myState.mySpeed < vNext) {
1048  braking = false;
1049  }
1050  if (braking) {
1052  } else {
1054  }
1055  // call reminders after vNext is set
1056  const SUMOReal pos = myState.myPos;
1057 
1058  // update position and speed
1059  myAcceleration = vNext - myState.mySpeed;
1060  myState.myPos += SPEED2DIST(vNext);
1061  myState.mySpeed = vNext;
1062  std::vector<MSLane*> passedLanes;
1063  for (std::vector<MSLane*>::reverse_iterator i = myFurtherLanes.rbegin(); i != myFurtherLanes.rend(); ++i) {
1064  passedLanes.push_back(*i);
1065  }
1066  if (passedLanes.size() == 0 || passedLanes.back() != myLane) {
1067  passedLanes.push_back(myLane);
1068  }
1069  bool moved = false;
1070  // move on lane(s)
1071  if (myState.myPos <= myLane->getLength()) {
1072  // we are staying at our lane
1073  // there is no need to go over succeeding lanes
1074  workOnMoveReminders(pos, pos + SPEED2DIST(vNext), vNext);
1075  } else {
1076  // we are moving at least to the next lane (maybe pass even more than one)
1077  if (myCurrEdge != myRoute->end() - 1) {
1078  MSLane* approachedLane = myLane;
1079  // move the vehicle forward
1080  for (i = myLFLinkLanes.begin(); i != myLFLinkLanes.end() && approachedLane != 0 && myState.myPos > approachedLane->getLength(); ++i) {
1082  MSLink* link = (*i).myLink;
1083  // check whether the vehicle was allowed to enter lane
1084  // otherwise it is decelareted and we do not need to test for it's
1085  // approach on the following lanes when a lane changing is performed
1086  // proceed to the next lane
1087  if (link != 0) {
1088  approachedLane = link->getViaLaneOrLane();
1089  } else {
1090  approachedLane = 0;
1091  }
1092  if (approachedLane != myLane && approachedLane != 0) {
1093  myState.myPos -= myLane->getLength();
1094  assert(myState.myPos > 0);
1095  enterLaneAtMove(approachedLane);
1096  myLane = approachedLane;
1097  if (getLaneChangeModel().isChangingLanes()) {
1098  if (link->getDirection() == LINKDIR_LEFT || link->getDirection() == LINKDIR_RIGHT) {
1099  // abort lane change
1100  WRITE_WARNING("Vehicle '" + getID() + "' could not finish continuous lane change (turn lane) time=" +
1101  time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
1103  }
1104  }
1105 #ifdef HAVE_INTERNAL_LANES
1106  // erase leader for the past link
1107  if (myLeaderForLink.find(link) != myLeaderForLink.end()) {
1108  myLinkLeaders.erase(myLeaderForLink[link]);
1109  myLeaderForLink.erase(link);
1110  }
1111 #endif
1112  moved = true;
1113  if (approachedLane->getEdge().isVaporizing()) {
1115  break;
1116  }
1117  }
1118  passedLanes.push_back(approachedLane);
1119  }
1120  }
1121  }
1122  // clear previously set information
1123  for (std::vector<MSLane*>::iterator i = myFurtherLanes.begin(); i != myFurtherLanes.end(); ++i) {
1124  (*i)->resetPartialOccupation(this);
1125  }
1126  myFurtherLanes.clear();
1127 
1128  if (myInfluencer != 0 && myInfluencer->isVTDControlled()) {
1129  myWaitingTime = 0;
1130 // myInfluencer->setVTDControlled(false);
1131  return false;
1132  }
1133 
1134  if (!hasArrived() && !myLane->getEdge().isVaporizing()) {
1135  if (myState.myPos > myLane->getLength()) {
1136  WRITE_WARNING("Vehicle '" + getID() + "' performs emergency stop on lane '" + myLane->getID() + " at position " +
1137  toString(myState.myPos) + " (decel=" + toString(myAcceleration - myState.mySpeed) + "), time="
1138  + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
1140  myState.mySpeed = 0;
1141  }
1142  if (myState.myPos - getVehicleType().getLength() < 0 && passedLanes.size() > 0) {
1143  SUMOReal leftLength = getVehicleType().getLength() - myState.myPos;
1144  std::vector<MSLane*>::reverse_iterator i = passedLanes.rbegin() + 1;
1145  while (leftLength > 0 && i != passedLanes.rend()) {
1146  myFurtherLanes.push_back(*i);
1147  leftLength -= (*i)->setPartialOccupation(this, leftLength);
1148  ++i;
1149  }
1150  }
1151  if (getLaneChangeModel().isChangingLanes()) {
1153  }
1155  }
1156  return moved;
1157 }
1158 
1159 
1160 SUMOReal
1161 MSVehicle::getSpaceTillLastStanding(const MSLane* l, bool& foundStopped) const {
1162  SUMOReal lengths = 0;
1163  const MSLane::VehCont& vehs = l->getVehiclesSecure();
1164  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
1165  if ((*i)->getSpeed() < SUMO_const_haltingSpeed) {
1166  foundStopped = true;
1167  const SUMOReal ret = (*i)->getPositionOnLane() - (*i)->getVehicleType().getLengthWithGap() - lengths;
1168  l->releaseVehicles();
1169  return ret;
1170  }
1171  lengths += (*i)->getVehicleType().getLengthWithGap();
1172  }
1173  l->releaseVehicles();
1174  return l->getLength() - lengths;
1175 }
1176 
1177 
1178 void
1179 MSVehicle::checkRewindLinkLanes(const SUMOReal lengthsInFront, DriveItemVector& lfLinks) const {
1180 #ifdef DEBUG_VEHICLE_GUI_SELECTION
1181  if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(this)->getGlID())) {
1182  int bla = 0;
1183  if (MSNet::getInstance()->getCurrentTimeStep() == 152000) {
1184  bla = 0;
1185  }
1186  }
1187 #endif
1188 #ifdef HAVE_INTERNAL_LANES
1190  bool hadVehicle = false;
1191  SUMOReal seenSpace = -lengthsInFront;
1192 
1193  bool foundStopped = false;
1194  // compute available space until a stopped vehicle is found
1195  // this is the sum of non-interal lane length minus in-between vehicle lenghts
1196  for (unsigned int i = 0; i < lfLinks.size(); ++i) {
1197  // skip unset links
1198  DriveProcessItem& item = lfLinks[i];
1199  if (item.myLink == 0 || foundStopped) {
1200  item.availableSpace = seenSpace;
1201  item.hadVehicle = hadVehicle;
1202  continue;
1203  }
1204  // get the next lane, determine whether it is an internal lane
1205  const MSLane* approachedLane = item.myLink->getViaLane();
1206  if (approachedLane != 0) {
1207  if (item.myLink->isCrossing()/* && item.myLink->willHaveBlockedFoe()*/) {
1208  seenSpace = seenSpace - approachedLane->getVehLenSum();
1209  hadVehicle |= approachedLane->getVehicleNumber() != 0;
1210  } else {
1211  seenSpace = seenSpace + getSpaceTillLastStanding(approachedLane, foundStopped);// - approachedLane->getVehLenSum() + approachedLane->getLength();
1212  hadVehicle |= approachedLane->getVehicleNumber() != 0;
1213  }
1214  item.availableSpace = seenSpace;
1215  item.hadVehicle = hadVehicle;
1216  continue;
1217  }
1218  approachedLane = item.myLink->getLane();
1219  const MSVehicle* last = approachedLane->getLastVehicle();
1220  if (last == 0) {
1221  last = approachedLane->getPartialOccupator();
1222  if (last != 0) {
1224  item.availableSpace = MAX2(seenSpace, seenSpace + approachedLane->getPartialOccupatorEnd() + last->getCarFollowModel().brakeGap(last->getSpeed()));
1225  hadVehicle = true;
1227  seenSpace = seenSpace + getSpaceTillLastStanding(approachedLane, foundStopped);// - approachedLane->getVehLenSum() + approachedLane->getLength();
1229  if (last->myHaveToWaitOnNextLink) {
1230  foundStopped = true;
1231  }
1232  } else {
1233  seenSpace += approachedLane->getLength();
1234  item.availableSpace = seenSpace;
1235  }
1236  } else {
1237  if (last->signalSet(VEH_SIGNAL_BRAKELIGHT)) {
1238  const SUMOReal lastBrakeGap = last->getCarFollowModel().brakeGap(approachedLane->getLastVehicle()->getSpeed());
1239  const SUMOReal lastGap = last->getPositionOnLane() - last->getVehicleType().getLengthWithGap() + lastBrakeGap - last->getSpeed() * last->getCarFollowModel().getHeadwayTime();
1240  item.availableSpace = MAX2(seenSpace, seenSpace + lastGap);
1241  seenSpace += getSpaceTillLastStanding(approachedLane, foundStopped);// - approachedLane->getVehLenSum() + approachedLane->getLength();
1242  } else {
1243  seenSpace += getSpaceTillLastStanding(approachedLane, foundStopped);
1244  item.availableSpace = seenSpace;
1245  }
1246  if (last->myHaveToWaitOnNextLink) {
1247  foundStopped = true;
1248  }
1249  hadVehicle = true;
1250  }
1251  item.hadVehicle = hadVehicle;
1252  }
1253 
1254 
1255 #ifdef DEBUG_VEHICLE_GUI_SELECTION
1256  if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(this)->getGlID())) {
1257  int bla = 0;
1258  }
1259 #endif
1260  // check which links allow continuation and add pass available to the previous item
1261  for (int i = (int)(lfLinks.size() - 1); i > 0; --i) {
1262  DriveProcessItem& item = lfLinks[i - 1];
1263  const bool opened = item.myLink != 0 && (item.myLink->havePriority() ||
1264  item.myLink->opened(item.myArrivalTime, item.myArrivalSpeed,
1267  bool allowsContinuation = item.myLink == 0 || item.myLink->isCont() || !lfLinks[i].hadVehicle || opened;
1268  if (!opened && item.myLink != 0) {
1269  if (i > 1) {
1270  DriveProcessItem& item2 = lfLinks[i - 2];
1271  if (item2.myLink != 0 && item2.myLink->isCont()) {
1272  allowsContinuation = true;
1273  }
1274  }
1275  }
1276  if (allowsContinuation) {
1277  item.availableSpace = lfLinks[i].availableSpace;
1278  }
1279  }
1280 
1281  // find removalBegin
1282  int removalBegin = -1;
1283  for (unsigned int i = 0; hadVehicle && i < lfLinks.size() && removalBegin < 0; ++i) {
1284  // skip unset links
1285  const DriveProcessItem& item = lfLinks[i];
1286  if (item.myLink == 0) {
1287  continue;
1288  }
1289  /*
1290  SUMOReal impatienceCorrection = MAX2(SUMOReal(0), SUMOReal(SUMOReal(myWaitingTime)));
1291  if (seenSpace<getVehicleType().getLengthWithGap()-impatienceCorrection/10.&&nextSeenNonInternal!=0) {
1292  removalBegin = lastLinkToInternal;
1293  }
1294  */
1295 
1296  const SUMOReal leftSpace = item.availableSpace - getVehicleType().getLengthWithGap();
1297  if (leftSpace < 0/* && item.myLink->willHaveBlockedFoe()*/) {
1298  SUMOReal impatienceCorrection = 0;
1299  /*
1300  if(item.myLink->getState()==LINKSTATE_MINOR) {
1301  impatienceCorrection = MAX2(SUMOReal(0), STEPS2TIME(myWaitingTime));
1302  }
1303  */
1304  if (leftSpace < -impatienceCorrection / 10. && item.myLink->isCrossing()) {
1305  removalBegin = i;
1306  }
1307  //removalBegin = i;
1308  }
1309  }
1310  // abort requests
1311  if (removalBegin != -1 && !(removalBegin == 0 && myLane->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL)) {
1312  while (removalBegin < (int)(lfLinks.size())) {
1314  lfLinks[removalBegin].myVLinkPass = lfLinks[removalBegin].myVLinkWait;
1315  if (lfLinks[removalBegin].myDistance >= brakeGap || (lfLinks[removalBegin].myDistance > 0 && myState.mySpeed < ACCEL2SPEED(getCarFollowModel().getMaxDecel()))) {
1316  lfLinks[removalBegin].mySetRequest = false;
1317  }
1318  ++removalBegin;
1319  }
1320  }
1321  }
1322 #else
1323  UNUSED_PARAMETER(lengthsInFront);
1324 #endif
1325  for (DriveItemVector::iterator i = lfLinks.begin(); i != lfLinks.end(); ++i) {
1326  if ((*i).myLink != 0) {
1327  if ((*i).myLink->getState() == LINKSTATE_ALLWAY_STOP) {
1328  (*i).myArrivalTime += (SUMOTime)RandHelper::rand((size_t)2); // tie braker
1329  }
1330  (*i).myLink->setApproaching(this, (*i).myArrivalTime, (*i).myArrivalSpeed, (*i).getLeaveSpeed(),
1331  (*i).mySetRequest, (*i).myArrivalTimeBraking, (*i).myArrivalSpeedBraking, getWaitingTime());
1332  }
1333  }
1334 }
1335 
1336 
1337 void
1339  for (MoveReminderCont::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end();) {
1340  if (rem->first->getLane() != 0 && rem->first->getLane() != getLane()) {
1341 #ifdef _DEBUG
1342  if (myTraceMoveReminders) {
1343  traceMoveReminder("notifyEnter_skipped", rem->first, rem->second, true);
1344  }
1345 #endif
1346  ++rem;
1347  } else {
1348  if (rem->first->notifyEnter(*this, reason)) {
1349 #ifdef _DEBUG
1350  if (myTraceMoveReminders) {
1351  traceMoveReminder("notifyEnter", rem->first, rem->second, true);
1352  }
1353 #endif
1354  ++rem;
1355  } else {
1356 #ifdef _DEBUG
1357  if (myTraceMoveReminders) {
1358  traceMoveReminder("notifyEnter", rem->first, rem->second, false);
1359  }
1360 #endif
1361  rem = myMoveReminders.erase(rem);
1362  }
1363  }
1364  }
1365 }
1366 
1367 
1368 bool
1369 MSVehicle::enterLaneAtMove(MSLane* enteredLane, bool onTeleporting) {
1370  myAmOnNet = !onTeleporting;
1371  // vaporizing edge?
1372  /*
1373  if (enteredLane->getEdge().isVaporizing()) {
1374  // yep, let's do the vaporization...
1375  myLane = enteredLane;
1376  return true;
1377  }
1378  */
1379  // move mover reminder one lane further
1380  adaptLaneEntering2MoveReminder(*enteredLane);
1381  // set the entered lane as the current lane
1382  myLane = enteredLane;
1383 
1384  // internal edges are not a part of the route...
1385  if (enteredLane->getEdge().getPurpose() != MSEdge::EDGEFUNCTION_INTERNAL) {
1386  ++myCurrEdge;
1387  }
1388  if (!onTeleporting) {
1389  // may be optimized: compute only, if the current or the next have more than one lane...!!!
1390  getBestLanes(true);
1392 #ifndef NO_TRACI
1393  if (myInfluencer != 0) {
1395  }
1396 #endif
1397  } else {
1399  // normal move() isn't called so reset position here
1400  myState.myPos = 0;
1401  }
1402  return hasArrived();
1403 }
1404 
1405 
1406 void
1408  myAmOnNet = true;
1409  myLane = enteredLane;
1410  // need to update myCurrentLaneInBestLanes
1411  getBestLanes();
1412  // switch to and activate the new lane's reminders
1413  // keep OldLaneReminders
1414  for (std::vector< MSMoveReminder* >::const_iterator rem = enteredLane->getMoveReminders().begin(); rem != enteredLane->getMoveReminders().end(); ++rem) {
1415  addReminder(*rem);
1416  }
1418  /*
1419  for (std::vector<MSLane*>::iterator i = myFurtherLanes.begin(); i != myFurtherLanes.end(); ++i) {
1420  (*i)->resetPartialOccupation(this);
1421  }
1422  myFurtherLanes.clear();
1423  */
1424  if (myState.myPos - getVehicleType().getLength() < 0) {
1425  // we have to rebuild "further lanes"
1426  const MSRoute& route = getRoute();
1428  MSLane* lane = myLane;
1429  SUMOReal leftLength = getVehicleType().getLength() - myState.myPos;
1430  while (i != route.begin() && leftLength > 0) {
1431  /* const MSEdge* const prev = */ *(--i);
1432  lane = lane->getLogicalPredecessorLane();
1433  if (lane == 0) {
1434  break;
1435  }
1436  myFurtherLanes.push_back(lane);
1437  leftLength -= (lane)->setPartialOccupation(this, leftLength);
1438  /*
1439  const std::vector<MSLane::IncomingLaneInfo> &incomingLanes = lane->getIncomingLanes();
1440  for (std::vector<MSLane::IncomingLaneInfo>::const_iterator j = incomingLanes.begin(); j != incomingLanes.end(); ++j) {
1441  if (&(*j).lane->getEdge() == prev) {
1442  #ifdef HAVE_INTERNAL_LANES
1443  (*j).lane->setPartialOccupation(this, leftLength);
1444  #else
1445  leftLength -= (*j).length;
1446  (*j).lane->setPartialOccupation(this, leftLength);
1447  #endif
1448  leftLength -= (*j).lane->getLength();
1449  break;
1450  }
1451  }
1452  */
1453  }
1454  }
1455 #ifndef NO_TRACI
1456  // check if further changes are necessary
1457  if (myInfluencer != 0) {
1459  }
1460 #endif
1461 }
1462 
1463 
1464 void
1466  myState = State(pos, speed);
1467  assert(myState.myPos >= 0);
1468  assert(myState.mySpeed >= 0);
1469  myWaitingTime = 0;
1470  myLane = enteredLane;
1471  // set and activate the new lane's reminders
1472  for (std::vector< MSMoveReminder* >::const_iterator rem = enteredLane->getMoveReminders().begin(); rem != enteredLane->getMoveReminders().end(); ++rem) {
1473  addReminder(*rem);
1474  }
1475  activateReminders(notification);
1476  std::string msg;
1477  if (MSGlobals::gCheckRoutes && !hasValidRoute(msg)) {
1478  throw ProcessError("Vehicle '" + getID() + "' has no valid route. " + msg);
1479  }
1480  myAmOnNet = true;
1481  // build the list of lanes the vehicle is lapping into
1482  SUMOReal leftLength = myType->getLength() - pos;
1483  MSLane* clane = enteredLane;
1484  while (leftLength > 0) {
1485  clane = clane->getLogicalPredecessorLane();
1486  if (clane == 0) {
1487  break;
1488  }
1489  myFurtherLanes.push_back(clane);
1490  leftLength -= (clane)->setPartialOccupation(this, leftLength);
1491  }
1492 }
1493 
1494 
1495 void
1497  for (MoveReminderCont::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end();) {
1498  if (rem->first->notifyLeave(*this, myState.myPos + rem->second, reason)) {
1499 #ifdef _DEBUG
1500  if (myTraceMoveReminders) {
1501  traceMoveReminder("notifyLeave", rem->first, rem->second, true);
1502  }
1503 #endif
1504  ++rem;
1505  } else {
1506 #ifdef _DEBUG
1507  if (myTraceMoveReminders) {
1508  traceMoveReminder("notifyLeave", rem->first, rem->second, false);
1509  }
1510 #endif
1511  rem = myMoveReminders.erase(rem);
1512  }
1513  }
1514  if (reason != MSMoveReminder::NOTIFICATION_JUNCTION) {
1515  for (std::vector<MSLane*>::iterator i = myFurtherLanes.begin(); i != myFurtherLanes.end(); ++i) {
1516  (*i)->resetPartialOccupation(this);
1517  }
1518  myFurtherLanes.clear();
1519  }
1520  if (reason >= MSMoveReminder::NOTIFICATION_TELEPORT) {
1521  myAmOnNet = false;
1522  }
1523 }
1524 
1525 
1528  return *myLaneChangeModel;
1529 }
1530 
1531 
1534  return *myLaneChangeModel;
1535 }
1536 
1537 
1538 const std::vector<MSVehicle::LaneQ>&
1539 MSVehicle::getBestLanes(bool forceRebuild, MSLane* startLane) const {
1540 #ifdef DEBUG_VEHICLE_GUI_SELECTION
1541  if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(this)->getGlID())) {
1542  int bla = 0;
1543  myLastBestLanesEdge = 0;
1544  }
1545 #endif
1546 
1547  if (startLane == 0) {
1548  startLane = myLane;
1549  }
1550  assert(startLane != 0);
1551  // update occupancy and current lane index, only, if the vehicle has not moved to a new lane
1552  // (never for internal lanes)
1553  if ((myLastBestLanesEdge == &startLane->getEdge() && !forceRebuild) ||
1554  (startLane->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL && myBestLanes.size() > 0)) {
1555  std::vector<LaneQ>& lanes = *myBestLanes.begin();
1556  std::vector<LaneQ>::iterator i;
1557  for (i = lanes.begin(); i != lanes.end(); ++i) {
1558  SUMOReal nextOccupation = 0;
1559  for (std::vector<MSLane*>::const_iterator j = (*i).bestContinuations.begin() + 1; j != (*i).bestContinuations.end(); ++j) {
1560  nextOccupation += (*j)->getVehLenSum();
1561  }
1562  (*i).nextOccupation = nextOccupation;
1563  if ((*i).lane == startLane) {
1565  }
1566  }
1567  return *myBestLanes.begin();
1568  }
1569  // start rebuilding
1570  myLastBestLanesEdge = &startLane->getEdge();
1571  myBestLanes.clear();
1572 
1573  // get information about the next stop
1574  const MSEdge* nextStopEdge = 0;
1575  const MSLane* nextStopLane = 0;
1576  SUMOReal nextStopPos = 0;
1577  if (!myStops.empty()) {
1578  const Stop& nextStop = myStops.front();
1579  nextStopLane = nextStop.lane;
1580  nextStopEdge = &nextStopLane->getEdge();
1581  nextStopPos = nextStop.startPos;
1582  }
1583  if (myParameter->arrivalLaneProcedure == ARRIVAL_LANE_GIVEN && nextStopEdge == 0) {
1584  nextStopEdge = *(myRoute->end() - 1);
1585  nextStopLane = nextStopEdge->getLanes()[myParameter->arrivalLane];
1586  nextStopPos = myArrivalPos;
1587  }
1588  if (nextStopEdge != 0) {
1589  // make sure that the "wrong" lanes get a penalty. (penalty needs to be
1590  // large enough to overcome a magic threshold in MSLCM_DK2004.cpp:383)
1591  nextStopPos = MIN2((SUMOReal)nextStopPos, (SUMOReal)(nextStopEdge->getLength() - 2 * POSITION_EPS));
1592  }
1593 
1594  // go forward along the next lanes;
1595  int seen = 0;
1596  SUMOReal seenLength = 0;
1597  bool progress = true;
1598  for (MSRouteIterator ce = myCurrEdge; progress;) {
1599  std::vector<LaneQ> currentLanes;
1600  const std::vector<MSLane*>* allowed = 0;
1601  const MSEdge* nextEdge = 0;
1602  if (ce != myRoute->end() && ce + 1 != myRoute->end()) {
1603  nextEdge = *(ce + 1);
1604  allowed = (*ce)->allowedLanes(*nextEdge, myType->getVehicleClass());
1605  }
1606  const std::vector<MSLane*>& lanes = (*ce)->getLanes();
1607  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
1608  LaneQ q;
1609  MSLane* cl = *i;
1610  q.lane = cl;
1611  q.bestContinuations.push_back(cl);
1612  q.bestLaneOffset = 0;
1613  q.length = cl->getLength();
1614  q.allowsContinuation = allowed == 0 || find(allowed->begin(), allowed->end(), cl) != allowed->end();
1615  currentLanes.push_back(q);
1616  }
1617  //
1618  if (nextStopEdge == *ce) {
1619  progress = false;
1620  for (std::vector<LaneQ>::iterator q = currentLanes.begin(); q != currentLanes.end(); ++q) {
1621  if (nextStopLane != 0 && nextStopLane != (*q).lane) {
1622  (*q).allowsContinuation = false;
1623  (*q).length = nextStopPos;
1624  }
1625  }
1626  }
1627 
1628  myBestLanes.push_back(currentLanes);
1629  ++seen;
1630  seenLength += currentLanes[0].lane->getLength();
1631  ++ce;
1632  progress &= (seen <= 4 || seenLength < 3000);
1633  progress &= seen <= 8;
1634  progress &= ce != myRoute->end();
1635  /*
1636  if(progress) {
1637  progress &= (currentLanes.size()!=1||(*ce)->getLanes().size()!=1);
1638  }
1639  */
1640  }
1641 
1642  // we are examining the last lane explicitly
1643  if (myBestLanes.size() != 0) {
1644  SUMOReal bestLength = -1;
1645  int bestThisIndex = 0;
1646  int index = 0;
1647  std::vector<LaneQ>& last = myBestLanes.back();
1648  for (std::vector<LaneQ>::iterator j = last.begin(); j != last.end(); ++j, ++index) {
1649  if ((*j).length > bestLength) {
1650  bestLength = (*j).length;
1651  bestThisIndex = index;
1652  }
1653  }
1654  index = 0;
1655  for (std::vector<LaneQ>::iterator j = last.begin(); j != last.end(); ++j, ++index) {
1656  if ((*j).length < bestLength) {
1657  (*j).bestLaneOffset = bestThisIndex - index;
1658  }
1659  }
1660  }
1661 
1662  // go backward through the lanes
1663  // track back best lane and compute the best prior lane(s)
1664  for (std::vector<std::vector<LaneQ> >::reverse_iterator i = myBestLanes.rbegin() + 1; i != myBestLanes.rend(); ++i) {
1665  std::vector<LaneQ>& nextLanes = (*(i - 1));
1666  std::vector<LaneQ>& clanes = (*i);
1667  MSEdge& cE = clanes[0].lane->getEdge();
1668  int index = 0;
1669  SUMOReal bestConnectedLength = -1;
1670  SUMOReal bestLength = -1;
1671  for (std::vector<LaneQ>::iterator j = nextLanes.begin(); j != nextLanes.end(); ++j, ++index) {
1672  if ((*j).lane->isApproachedFrom(&cE) && bestConnectedLength < (*j).length) {
1673  bestConnectedLength = (*j).length;
1674  }
1675  if (bestLength < (*j).length) {
1676  bestLength = (*j).length;
1677  }
1678  }
1679  if (bestConnectedLength > 0) {
1680  int bestThisIndex = 0;
1681  index = 0;
1682  for (std::vector<LaneQ>::iterator j = clanes.begin(); j != clanes.end(); ++j, ++index) {
1683  LaneQ bestConnectedNext;
1684  bestConnectedNext.length = -1;
1685  if ((*j).allowsContinuation) {
1686  for (std::vector<LaneQ>::const_iterator m = nextLanes.begin(); m != nextLanes.end(); ++m) {
1687  if ((*m).lane->isApproachedFrom(&cE, (*j).lane)) {
1688  if (bestConnectedNext.length < (*m).length || (bestConnectedNext.length == (*m).length && abs(bestConnectedNext.bestLaneOffset) > abs((*m).bestLaneOffset))) {
1689  bestConnectedNext = *m;
1690  }
1691  }
1692  }
1693  if (bestConnectedNext.length == bestConnectedLength && abs(bestConnectedNext.bestLaneOffset) < 2) {
1694  (*j).length += bestLength;
1695  } else {
1696  (*j).length += bestConnectedNext.length;
1697  }
1698  }
1699  if (clanes[bestThisIndex].length < (*j).length || (clanes[bestThisIndex].length == (*j).length && abs(abs(clanes[bestThisIndex].bestLaneOffset > (*j).bestLaneOffset)))) {
1700  bestThisIndex = index;
1701  }
1702  copy(bestConnectedNext.bestContinuations.begin(), bestConnectedNext.bestContinuations.end(), back_inserter((*j).bestContinuations));
1703  }
1704 
1705  index = 0;
1706  for (std::vector<LaneQ>::iterator j = clanes.begin(); j != clanes.end(); ++j, ++index) {
1707  if ((*j).length < clanes[bestThisIndex].length || ((*j).length == clanes[bestThisIndex].length && abs((*j).bestLaneOffset) < abs(clanes[bestThisIndex].bestLaneOffset))) {
1708  (*j).bestLaneOffset = bestThisIndex - index;
1709  } else {
1710  (*j).bestLaneOffset = 0;
1711  }
1712  }
1713 
1714  } else {
1715 
1716  int bestThisIndex = 0;
1717  int bestNextIndex = 0;
1718  int bestDistToNeeded = (int) clanes.size();
1719  index = 0;
1720  for (std::vector<LaneQ>::iterator j = clanes.begin(); j != clanes.end(); ++j, ++index) {
1721  if ((*j).allowsContinuation) {
1722  int nextIndex = 0;
1723  for (std::vector<LaneQ>::const_iterator m = nextLanes.begin(); m != nextLanes.end(); ++m, ++nextIndex) {
1724  if ((*m).lane->isApproachedFrom(&cE, (*j).lane)) {
1725  if (bestDistToNeeded > abs((*m).bestLaneOffset)) {
1726  bestDistToNeeded = abs((*m).bestLaneOffset);
1727  bestThisIndex = index;
1728  bestNextIndex = nextIndex;
1729  }
1730  }
1731  }
1732  }
1733  }
1734  clanes[bestThisIndex].length += nextLanes[bestNextIndex].length;
1735  copy(nextLanes[bestNextIndex].bestContinuations.begin(), nextLanes[bestNextIndex].bestContinuations.end(), back_inserter(clanes[bestThisIndex].bestContinuations));
1736  index = 0;
1737  for (std::vector<LaneQ>::iterator j = clanes.begin(); j != clanes.end(); ++j, ++index) {
1738  if ((*j).length < clanes[bestThisIndex].length || ((*j).length == clanes[bestThisIndex].length && abs((*j).bestLaneOffset) < abs(clanes[bestThisIndex].bestLaneOffset))) {
1739  (*j).bestLaneOffset = bestThisIndex - index;
1740  } else {
1741  (*j).bestLaneOffset = 0;
1742  }
1743  }
1744 
1745  }
1746 
1747  }
1748 
1749  // update occupancy and current lane index
1750  std::vector<LaneQ>& currLanes = *myBestLanes.begin();
1751  std::vector<LaneQ>::iterator i;
1752  for (i = currLanes.begin(); i != currLanes.end(); ++i) {
1753  SUMOReal nextOccupation = 0;
1754  for (std::vector<MSLane*>::const_iterator j = (*i).bestContinuations.begin() + 1; j != (*i).bestContinuations.end(); ++j) {
1755  nextOccupation += (*j)->getVehLenSum();
1756  }
1757  (*i).nextOccupation = nextOccupation;
1758  if ((*i).lane == startLane) {
1760  }
1761  }
1762  return *myBestLanes.begin();
1763 }
1764 
1765 
1766 const std::vector<MSLane*>&
1768  if (myBestLanes.empty() || myBestLanes[0].empty()) {
1769  return myEmptyLaneVector;
1770  }
1771  return (*myCurrentLaneInBestLanes).bestContinuations;
1772 }
1773 
1774 
1775 const std::vector<MSLane*>&
1777  if (myBestLanes.size() == 0) {
1778  return myEmptyLaneVector;
1779  }
1780  for (std::vector<LaneQ>::const_iterator i = myBestLanes[0].begin(); i != myBestLanes[0].end(); ++i) {
1781  if ((*i).lane == l) {
1782  return (*i).bestContinuations;
1783  }
1784  }
1785  return myEmptyLaneVector;
1786 }
1787 
1788 
1789 bool
1791  std::vector<MSLane*>& bestLaneConts = (*myCurrentLaneInBestLanes).bestContinuations;
1792  if (myLane->getLinkCont()[0]->getLane() != bestLaneConts[1]) {
1793  bestLaneConts.erase(bestLaneConts.begin() + 1, bestLaneConts.end());
1794  return true;
1795  }
1796  return false;
1797 }
1798 
1799 
1800 bool
1802  if (getPositionOnLane() > myLane->getLength()) {
1804  return true;
1805  }
1806  return false;
1807 }
1808 
1809 
1810 SUMOReal
1812 #ifdef DEBUG_VEHICLE_GUI_SELECTION
1813  SUMOReal distance = 1000000.;
1814 #else
1816 #endif
1817  if (isOnRoad() && destEdge != NULL) {
1818  if (&myLane->getEdge() == *myCurrEdge) {
1819  // vehicle is on a normal edge
1820  distance = myRoute->getDistanceBetween(getPositionOnLane(), destPos, *myCurrEdge, destEdge);
1821  } else {
1822  // vehicle is on inner junction edge
1823  distance = myLane->getLength() - getPositionOnLane();
1824  distance += myRoute->getDistanceBetween(0, destPos, *(myCurrEdge + 1), destEdge);
1825  }
1826  }
1827  return distance;
1828 }
1829 
1830 
1831 SUMOReal
1834 }
1835 
1836 
1837 SUMOReal
1840 }
1841 
1842 
1843 SUMOReal
1846 }
1847 
1848 
1849 SUMOReal
1852 }
1853 
1854 
1855 SUMOReal
1858 }
1859 
1860 
1861 SUMOReal
1864 }
1865 
1866 
1867 SUMOReal
1870 }
1871 
1872 
1873 void
1875  if (myPersonDevice == 0) {
1877  myMoveReminders.push_back(std::make_pair(myPersonDevice, 0.));
1878  }
1879  myPersonDevice->addPerson(person);
1880  if (myStops.size() > 0 && myStops.front().reached && myStops.front().triggered) {
1881  unsigned int numExpected = (unsigned int) myStops.front().awaitedPersons.size();
1882  if (numExpected != 0) {
1883  // I added the if-statement and number retrieval, assuming that it should be a "conditional short jump" only and
1884  // in most cases we won't have the list of expected passenger - only for simulating car-sharing, probably.
1885  // Bus drivers usually do not know the names of the passengers.
1886  myStops.front().awaitedPersons.erase(person->getID());
1887  numExpected = (unsigned int) myStops.front().awaitedPersons.size();
1888  }
1889  if (numExpected == 0) {
1890  myStops.front().duration = 0;
1891  }
1892  }
1893 }
1894 
1895 
1896 unsigned int
1898  unsigned int boarded = myPersonDevice == 0 ? 0 : myPersonDevice->size();
1899  return boarded + myParameter->personNumber;
1900 }
1901 
1902 
1903 void
1906  int state = getLaneChangeModel().getOwnState();
1907  if ((state & LCA_LEFT) != 0) {
1909  } else if ((state & LCA_RIGHT) != 0) {
1911  } else {
1912  const MSLane* lane = getLane();
1913  MSLinkCont::const_iterator link = lane->succLinkSec(*this, 1, *lane, getBestLanesContinuation());
1914  if (link != lane->getLinkCont().end() && lane->getLength() - getPositionOnLane() < lane->getVehicleMaxSpeed(this) * (SUMOReal) 7.) {
1915  switch ((*link)->getDirection()) {
1916  case LINKDIR_TURN:
1917  case LINKDIR_LEFT:
1918  case LINKDIR_PARTLEFT:
1920  break;
1921  case LINKDIR_RIGHT:
1922  case LINKDIR_PARTRIGHT:
1924  break;
1925  default:
1926  break;
1927  }
1928  }
1929  }
1930 
1931 }
1932 
1933 
1934 void
1936  if (myType->amVehicleSpecific()) {
1937  delete myType;
1938  }
1939  myType = type;
1940 }
1941 
1942 unsigned int
1944  std::vector<MSLane*>::const_iterator laneP = std::find((*myCurrEdge)->getLanes().begin(), (*myCurrEdge)->getLanes().end(), myLane);
1945  return (unsigned int) std::distance((*myCurrEdge)->getLanes().begin(), laneP);
1946 }
1947 
1948 
1949 SUMOReal
1951  return MAX2((SUMOReal)0, MIN2((SUMOReal)1, getVehicleType().getImpatience() +
1953 }
1954 
1955 
1956 #ifndef NO_TRACI
1957 bool
1958 MSVehicle::addTraciStop(MSLane* lane, SUMOReal pos, SUMOReal /*radius*/, SUMOTime duration, bool parking, bool triggered) {
1959  //if the stop exists update the duration
1960  for (std::list<Stop>::iterator iter = myStops.begin(); iter != myStops.end(); iter++) {
1961  if (iter->lane == lane && fabs(iter->endPos - pos) < POSITION_EPS) {
1962  if (duration == 0 && !iter->reached) {
1963  myStops.erase(iter);
1964  } else {
1965  iter->duration = duration;
1966  }
1967  return true;
1968  }
1969  }
1970 
1972  newStop.lane = lane->getID();
1973  newStop.busstop = MSNet::getInstance()->getBusStopID(lane, pos);
1974  newStop.startPos = pos - POSITION_EPS;
1975  newStop.endPos = pos;
1976  newStop.duration = duration;
1977  newStop.until = -1;
1978  newStop.triggered = triggered;
1979  newStop.parking = parking;
1980  newStop.index = STOP_INDEX_FIT;
1981  return addStop(newStop);
1982 }
1983 
1984 
1985 bool
1987  Stop& stop = myStops.front();
1988  if (!stop.reached) {
1989  return false;
1990  }
1991  stop.duration = 0;
1992  return true;
1993 }
1994 
1995 
1998  return myStops.front();
1999 }
2000 
2001 
2004  if (myInfluencer == 0) {
2005  myInfluencer = new Influencer();
2006  }
2007  return *myInfluencer;
2008 }
2009 
2010 
2011 SUMOReal
2013  if (myInfluencer != 0) {
2014  return myInfluencer->getOriginalSpeed();
2015  }
2016  return myState.mySpeed;
2017 }
2018 
2019 
2020 void
2023  // here starts the vehicle internal part (see loading)
2024  std::vector<int> internals;
2025  internals.push_back(myDeparture);
2026  internals.push_back((int)distance(myRoute->begin(), myCurrEdge));
2027  out.writeAttr(SUMO_ATTR_STATE, toString(internals));
2030  out.closeTag();
2031 }
2032 
2033 
2034 void
2035 MSVehicle::loadState(const SUMOSAXAttributes& attrs, const SUMOTime offset) {
2036  unsigned int routeOffset;
2037  std::istringstream bis(attrs.getString(SUMO_ATTR_STATE));
2038  bis >> myDeparture;
2039  bis >> routeOffset;
2040  if (hasDeparted()) {
2041  myDeparture -= offset;
2042  myCurrEdge += routeOffset;
2043  }
2046 }
2047 
2048 #endif
2049 
2050 
2051 /****************************************************************************/