SUMO - Simulation of Urban MObility
MSVehicle.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2017 German Aerospace Center (DLR) and others.
4 /****************************************************************************/
5 //
6 // This program and the accompanying materials
7 // are made available under the terms of the Eclipse Public License v2.0
8 // which accompanies this distribution, and is available at
9 // http://www.eclipse.org/legal/epl-v20.html
10 //
11 /****************************************************************************/
28 // Representation of a vehicle in the micro simulation
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>
46 #include <utils/common/ToString.h>
53 #include <utils/common/StdDefs.h>
54 #include <utils/geom/GeomHelper.h>
68 #include "MSVehicleControl.h"
69 #include "MSVehicleTransfer.h"
70 #include "MSGlobals.h"
71 #include "MSStoppingPlace.h"
72 #include "MSParkingArea.h"
74 #include "MSEdgeWeightsStorage.h"
76 #include "MSMoveReminder.h"
77 #include "MSTransportableControl.h"
78 #include "MSLane.h"
79 #include "MSJunction.h"
80 #include "MSVehicle.h"
81 #include "MSEdge.h"
82 #include "MSVehicleType.h"
83 #include "MSNet.h"
84 #include "MSRoute.h"
85 #include "MSLinkCont.h"
86 #include "MSLeaderInfo.h"
87 
88 //#define DEBUG_PLAN_MOVE
89 //#define DEBUG_CHECKREWINDLINKLANES
90 //#define DEBUG_EXEC_MOVE
91 //#define DEBUG_FURTHER
92 //#define DEBUG_TARGET_LANE
93 //#define DEBUG_STOPS
94 //#define DEBUG_BESTLANES
95 //#define DEBUG_IGNORE_RED
96 //#define DEBUG_ACTIONSTEPS
97 //#define DEBUG_COND (getID() == "blocker")
98 //#define DEBUG_COND (true)
99 #define DEBUG_COND (isSelected())
100 
101 
102 #define STOPPING_PLACE_OFFSET 0.5
103 
104 #define CRLL_LOOK_AHEAD 5
105 
106 // @todo Calibrate with real-world values / make configurable
107 #define DIST_TO_STOPLINE_EXPECT_PRIORITY 1.0
108 
109 // ===========================================================================
110 // static value definitions
111 // ===========================================================================
112 std::vector<MSLane*> MSVehicle::myEmptyLaneVector;
113 std::vector<MSTransportable*> MSVehicle::myEmptyTransportableVector;
114 
115 
116 // ===========================================================================
117 // method definitions
118 // ===========================================================================
119 /* -------------------------------------------------------------------------
120  * methods of MSVehicle::State
121  * ----------------------------------------------------------------------- */
123  myPos = state.myPos;
124  mySpeed = state.mySpeed;
125  myPosLat = state.myPosLat;
126  myBackPos = state.myBackPos;
129 }
130 
131 
134  myPos = state.myPos;
135  mySpeed = state.mySpeed;
136  myPosLat = state.myPosLat;
137  myBackPos = state.myBackPos;
140  return *this;
141 }
142 
143 
144 bool
146  return (myPos != state.myPos ||
147  mySpeed != state.mySpeed ||
148  myPosLat != state.myPosLat ||
150  myPreviousSpeed != state.myPreviousSpeed ||
151  myBackPos != state.myBackPos);
152 }
153 
154 
155 MSVehicle::State::State(double pos, double speed, double posLat, double backPos) :
156  myPos(pos), mySpeed(speed), myPosLat(posLat), myBackPos(backPos), myPreviousSpeed(speed), myLastCoveredDist(SPEED2DIST(speed)) {}
157 
158 
159 
160 /* -------------------------------------------------------------------------
161  * methods of MSVehicle::WaitingTimeCollector
162  * ----------------------------------------------------------------------- */
163 
165 
167 
172  return *this;
173 }
174 
177  myWaitingIntervals.clear();
178  passTime(t, true);
179  return *this;
180 }
181 
182 SUMOTime
184  assert(memorySpan <= myMemorySize);
185  if (memorySpan == -1) {
186  memorySpan = myMemorySize;
187  }
188  SUMOTime totalWaitingTime = 0;
189  for (waitingIntervalList::const_iterator i = myWaitingIntervals.begin(); i != myWaitingIntervals.end(); i++) {
190  if (i->second >= memorySpan) {
191  if (i->first >= memorySpan) {
192  break;
193  } else {
194  totalWaitingTime += memorySpan - i->first;
195  }
196  } else {
197  totalWaitingTime += i->second - i->first;
198  }
199  }
200  return totalWaitingTime;
201 }
202 
203 void
205  waitingIntervalList::iterator i = myWaitingIntervals.begin();
206  waitingIntervalList::iterator end = myWaitingIntervals.end();
207  bool startNewInterval = i == end || (i->first != 0);
208  while (i != end) {
209  i->first += dt;
210  if (i->first >= myMemorySize) {
211  break;
212  }
213  i->second += dt;
214  i++;
215  }
216 
217  // remove intervals beyond memorySize
218  waitingIntervalList::iterator::difference_type d = std::distance(i, end);
219  while (d > 0) {
220  myWaitingIntervals.pop_back();
221  d--;
222  }
223 
224  if (!waiting) {
225  return;
226  } else if (!startNewInterval) {
227  myWaitingIntervals.begin()->first = 0;
228  } else {
229  myWaitingIntervals.push_front(std::make_pair(0, dt));
230  }
231  return;
232 }
233 
234 
235 
236 
237 
238 /* -------------------------------------------------------------------------
239  * methods of MSVehicle::Influencer
240  * ----------------------------------------------------------------------- */
241 #ifndef NO_TRACI
243  myLatDist(0),
244  mySpeedAdaptationStarted(true),
245  myConsiderSafeVelocity(true),
246  myConsiderMaxAcceleration(true),
247  myConsiderMaxDeceleration(true),
248  myRespectJunctionPriority(true),
249  myEmergencyBrakeRedLight(true),
250  myLastRemoteAccess(-TIME2STEPS(20)),
251  myStrategicLC(LC_NOCONFLICT),
252  myCooperativeLC(LC_NOCONFLICT),
253  mySpeedGainLC(LC_NOCONFLICT),
254  myRightDriveLC(LC_NOCONFLICT),
255  mySublaneLC(LC_NOCONFLICT),
256  myTraciLaneChangePriority(LCP_URGENT),
257  myTraCISignals(-1),
258  myRoutingMode(0) {
259 }
260 
261 
263 
264 
265 void
266 MSVehicle::Influencer::setSpeedTimeLine(const std::vector<std::pair<SUMOTime, double> >& speedTimeLine) {
268  mySpeedTimeLine = speedTimeLine;
269 }
270 
271 
272 void
273 MSVehicle::Influencer::setLaneTimeLine(const std::vector<std::pair<SUMOTime, int> >& laneTimeLine) {
274  myLaneTimeLine = laneTimeLine;
275 }
276 
277 void
279  myLatDist = latDist;
280 }
281 
282 int
284  return (1 * myConsiderSafeVelocity +
289 }
290 
291 
292 int
294  return (1 * myStrategicLC +
295  4 * myCooperativeLC +
296  16 * mySpeedGainLC +
297  64 * myRightDriveLC +
299  1024 * mySublaneLC);
300 }
301 
302 
303 double
304 MSVehicle::Influencer::influenceSpeed(SUMOTime currentTime, double speed, double vSafe, double vMin, double vMax) {
305  // keep original speed
306  myOriginalSpeed = speed;
307  // remove leading commands which are no longer valid
308  while (mySpeedTimeLine.size() == 1 || (mySpeedTimeLine.size() > 1 && currentTime > mySpeedTimeLine[1].first)) {
309  mySpeedTimeLine.erase(mySpeedTimeLine.begin());
310  }
311  // do nothing if the time line does not apply for the current time
312  if (mySpeedTimeLine.size() < 2 || currentTime < mySpeedTimeLine[0].first) {
313  return speed;
314  }
315  // compute and set new speed
317  mySpeedTimeLine[0].second = speed;
319  }
320  currentTime += DELTA_T;
321  const double td = STEPS2TIME(currentTime - mySpeedTimeLine[0].first) / STEPS2TIME(mySpeedTimeLine[1].first + DELTA_T - mySpeedTimeLine[0].first);
322  speed = mySpeedTimeLine[0].second - (mySpeedTimeLine[0].second - mySpeedTimeLine[1].second) * td;
324  speed = MIN2(speed, vSafe);
325  }
327  speed = MIN2(speed, vMax);
328  }
330  speed = MAX2(speed, vMin);
331  }
332  return speed;
333 }
334 
335 
336 double
338  return mySpeedTimeLine.empty() ? -1 : myOriginalSpeed;
339 }
340 
341 
342 int
343 MSVehicle::Influencer::influenceChangeDecision(const SUMOTime currentTime, const MSEdge& currentEdge, const int currentLaneIndex, int state) {
344  // remove leading commands which are no longer valid
345  while (myLaneTimeLine.size() == 1 || (myLaneTimeLine.size() > 1 && currentTime > myLaneTimeLine[1].first)) {
346  myLaneTimeLine.erase(myLaneTimeLine.begin());
347  }
348  ChangeRequest changeRequest = REQUEST_NONE;
349  // do nothing if the time line does not apply for the current time
350  if (myLaneTimeLine.size() >= 2 && currentTime >= myLaneTimeLine[0].first) {
351  const int destinationLaneIndex = myLaneTimeLine[1].second;
352  if (destinationLaneIndex < (int)currentEdge.getLanes().size()) {
353  if (currentLaneIndex > destinationLaneIndex) {
354  changeRequest = REQUEST_RIGHT;
355  } else if (currentLaneIndex < destinationLaneIndex) {
356  changeRequest = REQUEST_LEFT;
357  } else {
358  changeRequest = REQUEST_HOLD;
359  }
360  }
361  }
362  // check whether the current reason shall be canceled / overridden
363  if ((state & LCA_WANTS_LANECHANGE_OR_STAY) != 0) {
364  // flags for the current reason
365  LaneChangeMode mode = LC_NEVER;
366  if ((state & LCA_TRACI) != 0 && myLatDist != 0) {
367  // continue sublane change manoeuvre
368  return state;
369  } else if ((state & LCA_STRATEGIC) != 0) {
370  mode = myStrategicLC;
371  } else if ((state & LCA_COOPERATIVE) != 0) {
372  mode = myCooperativeLC;
373  } else if ((state & LCA_SPEEDGAIN) != 0) {
374  mode = mySpeedGainLC;
375  } else if ((state & LCA_KEEPRIGHT) != 0) {
376  mode = myRightDriveLC;
377  } else if ((state & LCA_SUBLANE) != 0) {
378  mode = mySublaneLC;
379  } else if ((state & LCA_TRACI) != 0) {
380  mode = LC_NEVER;
381  } else {
382  WRITE_WARNING("Lane change model did not provide a reason for changing (state=" + toString(state) + ", time=" + time2string(currentTime) + "\n");
383  }
384  if (mode == LC_NEVER) {
385  // cancel all lcModel requests
386  state &= ~LCA_WANTS_LANECHANGE_OR_STAY;
387  state &= ~LCA_URGENT;
388  } else if (mode == LC_NOCONFLICT && changeRequest != REQUEST_NONE) {
389  if (
390  ((state & LCA_LEFT) != 0 && changeRequest != REQUEST_LEFT) ||
391  ((state & LCA_RIGHT) != 0 && changeRequest != REQUEST_RIGHT) ||
392  ((state & LCA_STAY) != 0 && changeRequest != REQUEST_HOLD)) {
393  // cancel conflicting lcModel request
394  state &= ~LCA_WANTS_LANECHANGE_OR_STAY;
395  state &= ~LCA_URGENT;
396  }
397  } else if (mode == LC_ALWAYS) {
398  // ignore any TraCI requests
399  return state;
400  }
401  }
402  // apply traci requests
403  if (changeRequest == REQUEST_NONE) {
404  return state;
405  } else {
406  state |= LCA_TRACI;
407  // security checks
409  || (myTraciLaneChangePriority == LCP_NOOVERLAP && (state & LCA_OVERLAPPING) == 0)) {
410  state &= ~(LCA_BLOCKED | LCA_OVERLAPPING);
411  }
412  if (changeRequest != REQUEST_HOLD && myTraciLaneChangePriority != LCP_OPPORTUNISTIC) {
413  state |= LCA_URGENT;
414  }
415  switch (changeRequest) {
416  case REQUEST_HOLD:
417  return state | LCA_STAY;
418  case REQUEST_LEFT:
419  return state | LCA_LEFT;
420  case REQUEST_RIGHT:
421  return state | LCA_RIGHT;
422  default:
423  throw ProcessError("should not happen");
424  }
425  }
426 }
427 
428 
429 double
431  assert(myLaneTimeLine.size() >= 2);
432  assert(currentTime >= myLaneTimeLine[0].first);
433  return STEPS2TIME(myLaneTimeLine[1].first - currentTime);
434 }
435 
436 
437 void
439  myConsiderSafeVelocity = ((speedMode & 1) != 0);
440  myConsiderMaxAcceleration = ((speedMode & 2) != 0);
441  myConsiderMaxDeceleration = ((speedMode & 4) != 0);
442  myRespectJunctionPriority = ((speedMode & 8) != 0);
443  myEmergencyBrakeRedLight = ((speedMode & 16) != 0);
444 }
445 
446 
447 void
449  myStrategicLC = (LaneChangeMode)(value & (1 + 2));
450  myCooperativeLC = (LaneChangeMode)((value & (4 + 8)) >> 2);
451  mySpeedGainLC = (LaneChangeMode)((value & (16 + 32)) >> 4);
452  myRightDriveLC = (LaneChangeMode)((value & (64 + 128)) >> 6);
453  myTraciLaneChangePriority = (TraciLaneChangePriority)((value & (256 + 512)) >> 8);
454  mySublaneLC = (LaneChangeMode)((value & (1024 + 2048)) >> 10);
455 }
456 
457 
458 void
459 MSVehicle::Influencer::setRemoteControlled(Position xyPos, MSLane* l, double pos, double posLat, double angle, int edgeOffset, const ConstMSEdgeVector& route, SUMOTime t) {
460  myRemoteXYPos = xyPos;
461  myRemoteLane = l;
462  myRemotePos = pos;
463  myRemotePosLat = posLat;
464  myRemoteAngle = angle;
465  myRemoteEdgeOffset = edgeOffset;
466  myRemoteRoute = route;
467  myLastRemoteAccess = t;
468 }
469 
470 
471 bool
474 }
475 
476 
477 bool
479  return myLastRemoteAccess >= t - TIME2STEPS(10);
480 }
481 
482 void
484  const bool wasOnRoad = v->isOnRoad();
485  if (v->isOnRoad()) {
488  }
489  if (myRemoteRoute.size() != 0) {
491  }
493  if (myRemoteLane != 0 && myRemotePos > myRemoteLane->getLength()) {
495  }
496  if (myRemoteLane != 0 && fabs(myRemotePosLat) < 0.5 * (myRemoteLane->getWidth() + v->getVehicleType().getWidth())) {
498  v->updateBestLanes();
499  if (!wasOnRoad) {
500  v->drawOutsideNetwork(false);
501  }
502  //std::cout << "on road network p=" << myRemoteXYPos << " a=" << myRemoteAngle << " l=" << Named::getIDSecure(myRemoteLane) << " pos=" << myRemotePos << " posLat=" << myRemotePosLat << "\n";
503  } else {
504  if (v->getDeparture() == NOT_YET_DEPARTED) {
505  v->onDepart();
506  }
507  v->drawOutsideNetwork(true);
508  //std::cout << "outside network p=" << myRemoteXYPos << " a=" << myRemoteAngle << " l=" << Named::getIDSecure(myRemoteLane) << "\n";
509  }
510  // ensure that the position is correct (i.e. when the lanePosition is ambiguous at corners)
512  // inverse of GeomHelper::naviDegree
513  v->setAngle(M_PI / 2. - DEG2RAD(myRemoteAngle));
514 }
515 
516 
517 double
519  double dist = 0;
520  if (myRemoteLane == 0) {
521  dist = veh->getPosition().distanceTo2D(myRemoteXYPos);
522  } else {
524  }
525  if (DIST2SPEED(dist) > veh->getMaxSpeed()) {
526  return oldSpeed;
527  } else {
528  return DIST2SPEED(dist);
529  }
530 }
531 
532 double
534  double dist = 0;
535  if (myRemoteLane == 0) {
536  dist = veh->getPosition().distanceTo2D(myRemoteXYPos);
537  } else {
539  }
540  if (DIST2SPEED(dist) > veh->getMaxSpeed()) {
541  return 0;
542  } else {
543  return dist;
544  }
545 }
546 
547 
550  if (myRoutingMode == 1) {
552  } else {
553  return MSNet::getInstance()->getRouterTT();
554  }
555 }
556 
557 #endif
558 /* -------------------------------------------------------------------------
559  * Stop-methods
560  * ----------------------------------------------------------------------- */
561 double
563  if (busstop != 0) {
564  return busstop->getLastFreePos(veh);
565  } else if (containerstop != 0) {
566  return containerstop->getLastFreePos(veh);
567  } else if (parkingarea != 0) {
568  return parkingarea->getLastFreePos(veh);
569  } else if (chargingStation != 0) {
570  return chargingStation->getLastFreePos(veh);
571  }
572  return pars.endPos;
573 }
574 
575 
576 std::string
578  if (parkingarea != 0) {
579  return "parkingArea:" + parkingarea->getID();
580  } else if (containerstop != 0) {
581  return "containerStop:" + containerstop->getID();
582  } else if (busstop != 0) {
583  return "busStop:" + busstop->getID();
584  } else if (chargingStation != 0) {
585  return "chargingStation:" + chargingStation->getID();
586  } else {
587  return "lane:" + lane->getID() + " pos:" + toString(pars.endPos);
588  }
589 }
590 
591 
592 void
594  // lots of duplication with SUMOVehicleParameter::Stop::write()
595  dev.openTag(SUMO_TAG_STOP);
596  if (busstop != 0) {
597  dev.writeAttr(SUMO_ATTR_BUS_STOP, busstop->getID());
598  }
599  if (containerstop != 0) {
600  dev.writeAttr(SUMO_ATTR_CONTAINER_STOP, containerstop->getID());
601  }
602  if (busstop == 0 && containerstop == 0) {
603  dev.writeAttr(SUMO_ATTR_LANE, lane->getID());
604  dev.writeAttr(SUMO_ATTR_STARTPOS, pars.startPos);
605  dev.writeAttr(SUMO_ATTR_ENDPOS, pars.endPos);
606  }
607  if (duration >= 0) {
608  dev.writeAttr(SUMO_ATTR_DURATION, STEPS2TIME(duration));
609  }
610  if (pars.until >= 0) {
611  dev.writeAttr(SUMO_ATTR_UNTIL, STEPS2TIME(pars.until));
612  }
613  if (pars.triggered) {
614  dev.writeAttr(SUMO_ATTR_TRIGGERED, pars.triggered);
615  }
616  if (pars.containerTriggered) {
617  dev.writeAttr(SUMO_ATTR_CONTAINER_TRIGGERED, pars.containerTriggered);
618  }
619  if (pars.parking) {
620  dev.writeAttr(SUMO_ATTR_PARKING, pars.parking);
621  }
622  if (pars.awaitedPersons.size() > 0) {
623  dev.writeAttr(SUMO_ATTR_EXPECTED, joinToString(pars.awaitedPersons, " "));
624  }
625  if (pars.awaitedContainers.size() > 0) {
626  dev.writeAttr(SUMO_ATTR_EXPECTED_CONTAINERS, joinToString(pars.awaitedContainers, " "));
627  }
628  dev.closeTag();
629 }
630 
631 
632 /* -------------------------------------------------------------------------
633  * MSVehicle-methods
634  * ----------------------------------------------------------------------- */
636  MSVehicleType* type, const double speedFactor) :
637  MSBaseVehicle(pars, route, type, speedFactor),
638  myWaitingTime(0),
640  myTimeLoss(0),
641  myState(0, 0, 0, 0),
642  myActionStep(true),
643  myLastActionTime(0),
644  myLane(0),
647  myPersonDevice(0),
649  myAcceleration(0),
650  mySignals(0),
651  myAmOnNet(false),
654  myHaveToWaitOnNextLink(false),
655  myAngle(0),
656  myStopDist(std::numeric_limits<double>::max()),
659  myEdgeWeights(0)
660 #ifndef NO_TRACI
661  , myInfluencer(0)
662 #endif
663 {
664  if (!(*myCurrEdge)->isTazConnector()) {
665  if (pars->departLaneProcedure == DEPART_LANE_GIVEN) {
666  if ((*myCurrEdge)->getDepartLane(*this) == 0) {
667  throw ProcessError("Invalid departlane definition for vehicle '" + pars->id + "'.");
668  }
669  } else {
670  if ((*myCurrEdge)->allowedLanes(type->getVehicleClass()) == 0) {
671  throw ProcessError("Vehicle '" + pars->id + "' is not allowed to depart on any lane of its first edge.");
672  }
673  }
674  if (pars->departSpeedProcedure == DEPART_SPEED_GIVEN && pars->departSpeed > type->getMaxSpeed()) {
675  throw ProcessError("Departure speed for vehicle '" + pars->id +
676  "' is too high for the vehicle type '" + type->getID() + "'.");
677  }
678  }
681  myNextDriveItem = myLFLinkLanes.begin();
682 }
683 
684 
686  delete myEdgeWeights;
687  for (std::vector<MSLane*>::iterator i = myFurtherLanes.begin(); i != myFurtherLanes.end(); ++i) {
688  (*i)->resetPartialOccupation(this);
689  }
693  // still needed when calling resetPartialOccupation (getShadowLane) and when removing
694  // approach information from parallel links
695  delete myLaneChangeModel;
696  myFurtherLanes.clear();
697  myFurtherLanesPosLat.clear();
698  //
699  if (myType->isVehicleSpecific()) {
701  }
702 #ifndef NO_TRACI
703  delete myInfluencer;
704 #endif
705 }
706 
707 
708 void
710 #ifdef DEBUG_ACTIONSTEPS
711  if DEBUG_COND {
712  std::cout << SIMTIME << " Removing vehicle '" << getID() << "' (reason: " << toString(reason) << ")" << std::endl;
713  }
714 #endif
717  leaveLane(reason);
718 }
719 
720 
721 // ------------ interaction with the route
722 bool
724  return (myCurrEdge == myRoute->end() - 1
725  && (myStops.empty() || myStops.front().edge != myCurrEdge)
727  && !isRemoteControlled());
728 }
729 
730 
731 bool
732 MSVehicle::replaceRoute(const MSRoute* newRoute, bool onInit, int offset, bool addRouteStops, bool removeStops) {
733  const ConstMSEdgeVector& edges = newRoute->getEdges();
734  // assert the vehicle may continue (must not be "teleported" or whatever to another position)
735  if (!onInit && !newRoute->contains(*myCurrEdge)) {
736  return false;
737  }
738 
739  // rebuild in-vehicle route information
740  if (onInit) {
741  myCurrEdge = newRoute->begin();
742  } else {
743  MSRouteIterator newCurrEdge = find(edges.begin() + offset, edges.end(), *myCurrEdge);;
744  if (myLane->getEdge().isInternal() && (
745  (newCurrEdge + 1) == edges.end() || (*(newCurrEdge + 1)) != &(myLane->getOutgoingLanes()[0]->getEdge()))) {
746  return false;
747  }
748  myCurrEdge = newCurrEdge;
749  }
750  const bool stopsFromScratch = onInit && myRoute->getStops().empty();
751  // check whether the old route may be deleted (is not used by anyone else)
752  newRoute->addReference();
753  myRoute->release();
754  // assign new route
755  myRoute = newRoute;
756  // update arrival definition
758  // save information that the vehicle was rerouted
761  // if we did not drive yet it may be best to simply reassign the stops from scratch
762  if (stopsFromScratch) {
763  myStops.clear();
765  } else {
766  // recheck old stops
767  for (std::list<Stop>::iterator iter = myStops.begin(); iter != myStops.end();) {
768  if (removeStops && find(myCurrEdge, edges.end(), &iter->lane->getEdge()) == edges.end()) {
769  iter = myStops.erase(iter);
770  } else {
771  // iter->edge may point to edges.end() if removeStops is false but it should be replaced by the triggered rerouter anyway
772  iter->edge = find(myCurrEdge, edges.end(), &iter->lane->getEdge());
773  ++iter;
774  }
775  }
776  // add new stops
777  if (addRouteStops) {
778  for (std::vector<SUMOVehicleParameter::Stop>::const_iterator i = newRoute->getStops().begin(); i != newRoute->getStops().end(); ++i) {
779  std::string error;
780  addStop(*i, error);
781  if (error != "") {
782  WRITE_WARNING(error);
783  }
784  }
785  }
786  }
787  // update best lanes (after stops were added)
790  updateBestLanes(true, onInit ? (*myCurrEdge)->getLanes().front() : 0);
791  return true;
792 }
793 
794 
795 bool
796 MSVehicle::willPass(const MSEdge* const edge) const {
797  return find(myCurrEdge, myRoute->end(), edge) != myRoute->end();
798 }
799 
800 
801 int
803  return (int) std::distance(myRoute->begin(), myCurrEdge);
804 }
805 
806 
807 void
809  myCurrEdge = myRoute->begin() + index;
810  // !!! hack
811  myArrivalPos = (*(myRoute->end() - 1))->getLanes()[0]->getLength();
812 }
813 
814 
815 
818  return _getWeightsStorage();
819 }
820 
821 
824  return _getWeightsStorage();
825 }
826 
827 
830  if (myEdgeWeights == 0) {
832  }
833  return *myEdgeWeights;
834 }
835 
836 
837 // ------------ Interaction with move reminders
838 void
839 MSVehicle::workOnMoveReminders(double oldPos, double newPos, double newSpeed) {
840  // This erasure-idiom works for all stl-sequence-containers
841  // See Meyers: Effective STL, Item 9
842  for (MoveReminderCont::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end();) {
843  // XXX: calling notifyMove with newSpeed seems not the best choice. For the ballistic update, the average speed is calculated and used
844  // although a higher order quadrature-formula might be more adequate.
845  // For the euler case (where the speed is considered constant for each time step) it is conceivable that
846  // the current calculations may lead to systematic errors for large time steps (compared to reality). Refs. #2579
847  if (!rem->first->notifyMove(*this, oldPos + rem->second, newPos + rem->second, MAX2(0., newSpeed))) {
848 #ifdef _DEBUG
849  if (myTraceMoveReminders) {
850  traceMoveReminder("notifyMove", rem->first, rem->second, false);
851  }
852 #endif
853  rem = myMoveReminders.erase(rem);
854  } else {
855 #ifdef _DEBUG
856  if (myTraceMoveReminders) {
857  traceMoveReminder("notifyMove", rem->first, rem->second, true);
858  }
859 #endif
860  ++rem;
861  }
862  }
863 }
864 
865 
866 // XXX: consider renaming...
867 void
869  // save the old work reminders, patching the position information
870  // add the information about the new offset to the old lane reminders
871  const double oldLaneLength = myLane->getLength();
872  for (MoveReminderCont::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end(); ++rem) {
873  rem->second += oldLaneLength;
874 #ifdef _DEBUG
875 // if (rem->first==0) std::cout << "Null reminder (?!)" << std::endl;
876 // std::cout << "Adapted MoveReminder on lane " << ((rem->first->getLane()==0) ? "NULL" : rem->first->getLane()->getID()) <<" position to " << rem->second << std::endl;
877  if (myTraceMoveReminders) {
878  traceMoveReminder("adaptedPos", rem->first, rem->second, true);
879  }
880 #endif
881  }
882  for (std::vector< MSMoveReminder* >::const_iterator rem = enteredLane.getMoveReminders().begin(); rem != enteredLane.getMoveReminders().end(); ++rem) {
883  addReminder(*rem);
884  }
885 }
886 
887 
888 // ------------ Other getter methods
889 double
891  if (myLane == 0) {
892  return 0;
893  }
894  const double lp = getPositionOnLane();
895  const double gp = myLane->interpolateLanePosToGeometryPos(lp);
896  return myLane->getShape().slopeDegreeAtOffset(gp);
897 }
898 
899 
900 Position
901 MSVehicle::getPosition(const double offset) const {
902  if (myLane == 0) {
903  // when called in the context of GUI-Drawing, the simulation step is already incremented
905  return myCachedPosition;
906  } else {
907  return Position::INVALID;
908  }
909  }
910  if (isParking()) {
911  if (myStops.begin()->parkingarea != 0) {
912  return myStops.begin()->parkingarea->getVehiclePosition(*this);
913  } else {
914  // position beside the road
915  PositionVector shp = myLane->getEdge().getLanes()[0]->getShape();
916  shp.move2side(SUMO_const_laneWidth * (MSNet::getInstance()->lefthand() ? -1 : 1));
918  }
919  }
920  const bool changingLanes = getLaneChangeModel().isChangingLanes();
921  if (offset == 0. && !changingLanes) {
924  }
925  return myCachedPosition;
926  }
928  return result;
929 }
930 
931 
932 Position
935  const std::vector<MSLane*>& bestLanes = getBestLanesContinuation();
936  auto nextBestLane = bestLanes.begin();
937  double pos = myState.myPos;
938  const MSLane* lane = getLane();
939  assert(lane != 0);
940  bool success = true;
941 
942  while (offset > 0) {
943  // take into account lengths along internal lanes
944  while (lane->isInternal() && offset > 0) {
945  if (offset > lane->getLength() - pos) {
946  offset -= lane->getLength() - pos;
947  lane = lane->getLinkCont()[0]->getViaLaneOrLane();
948  pos = 0.;
949  if (lane == 0) {
950  success = false;
951  offset = 0.;
952  }
953  } else {
954  pos += offset;
955  offset = 0;
956  }
957  }
958  // set nextBestLane to next non-internal lane
959  while (nextBestLane != bestLanes.end() && *nextBestLane == 0) {
960  ++nextBestLane;
961  }
962  if (offset > 0) {
963  assert(!lane->isInternal());
964  assert(lane == *nextBestLane);
965  if (offset > lane->getLength() - pos) {
966  offset -= lane->getLength() - pos;
967  ++nextBestLane;
968  assert(nextBestLane == bestLanes.end() || *nextBestLane != 0);
969  if (nextBestLane == bestLanes.end()) {
970  success = false;
971  offset = 0.;
972  } else {
973  MSLink* link = lane->getLinkTo(*nextBestLane);
974  assert(link != 0);
975  lane = link->getViaLaneOrLane();
976  pos = 0.;
977  }
978  } else {
979  pos += offset;
980  offset = 0;
981  }
982  }
983 
984  }
985 
986  if (success) {
988  } else {
989  return Position::INVALID;
990  }
991 }
992 
993 
994 Position
995 MSVehicle::validatePosition(Position result, double offset) const {
996  int furtherIndex = 0;
997  while (result == Position::INVALID) {
998  if (furtherIndex >= (int)myFurtherLanes.size()) {
999  //WRITE_WARNING("Could not compute position for vehicle '" + getID() + "', time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
1000  break;
1001  }
1002  //std::cout << SIMTIME << " veh=" << getID() << " lane=" << myLane->getID() << " pos=" << getPositionOnLane() << " posLat=" << getLateralPositionOnLane() << " offset=" << offset << " result=" << result << " i=" << furtherIndex << " further=" << myFurtherLanes.size() << "\n";
1003  result = myFurtherLanes[furtherIndex]->geometryPositionAtOffset(myFurtherLanes[furtherIndex]->getLength() + offset, -getLateralPositionOnLane());
1004  furtherIndex++;
1005  }
1006  return result;
1007 }
1008 
1009 
1010 const MSEdge*
1012  // too close to the next junction, so avoid an emergency brake here
1013  if (myLane != 0 && (myCurrEdge + 1) != myRoute->end() &&
1015  return *(myCurrEdge + 1);
1016  }
1017  if (myLane != 0) {
1018  return myLane->getNextNormal();
1019  }
1020  return *myCurrEdge;
1021 }
1022 
1023 void
1024 MSVehicle::setAngle(double angle, bool straightenFurther) {
1025 #ifdef DEBUG_FURTHER
1026  if (DEBUG_COND) {
1027  std::cout << SIMTIME << " veh '" << getID() << " setAngle(" << angle << ") straightenFurther=" << straightenFurther << std::endl;
1028  }
1029 #endif
1030  myAngle = angle;
1031  if (straightenFurther && myFurtherLanesPosLat.size() > 0) {
1033  }
1034 }
1035 
1036 
1037 double
1039  Position p1;
1040  const double posLat = -myState.myPosLat; // @todo get rid of the '-'
1041  if (isParking()) {
1042  if (myStops.begin()->parkingarea != 0) {
1043  return myStops.begin()->parkingarea->getVehicleAngle(*this);
1044  } else {
1046  }
1047  }
1049  // cannot use getPosition() because it already includes the offset to the side and thus messes up the angle
1051  } else {
1052  p1 = getPosition();
1053  }
1054 
1055  Position p2 = getBackPosition();
1056  if (p2 == Position::INVALID) {
1057  // Handle special case of vehicle's back reaching out of the network
1058  if (myFurtherLanes.size() > 0) {
1059  p2 = myFurtherLanes.back()->geometryPositionAtOffset(0, -myFurtherLanesPosLat.back());
1060  } else {
1061  p2 = myLane->geometryPositionAtOffset(0, posLat);
1062  }
1063  }
1064  double result = (p1 != p2 ? p2.angleTo2D(p1) :
1067  result += DEG2RAD(getLaneChangeModel().getAngleOffset());
1068  }
1069 #ifdef DEBUG_FURTHER
1070  if (DEBUG_COND) {
1071  std::cout << SIMTIME << " computeAngle veh=" << getID() << " p1=" << p1 << " p2=" << p2 << " angle=" << RAD2DEG(result) << " naviDegree=" << GeomHelper::naviDegree(result) << "\n";
1072  }
1073 #endif
1074  return result;
1075 }
1076 
1077 
1078 const Position
1080  const double posLat = -myState.myPosLat; // @todo get rid of the '-'
1081  if (myState.myPos >= myType->getLength()) {
1082  // vehicle is fully on the new lane
1084  } else {
1086  // special case where the target lane has no predecessor
1087  return myLane->geometryPositionAtOffset(0, posLat);
1088  } else {
1089 #ifdef DEBUG_FURTHER
1090  if (DEBUG_COND) {
1091  std::cout << " getBackPosition veh=" << getID() << " myLane=" << myLane->getID() << " further=" << toString(myFurtherLanes) << " myFurtherLanesPosLat=" << toString(myFurtherLanesPosLat) << "\n";
1092  }
1093 #endif
1094  return myFurtherLanes.size() > 0 && !getLaneChangeModel().isChangingLanes()
1095  ? myFurtherLanes.back()->geometryPositionAtOffset(getBackPositionOnLane(myFurtherLanes.back()), -myFurtherLanesPosLat.back())
1096  : myLane->geometryPositionAtOffset(0, posLat);
1097  }
1098  }
1099 }
1100 
1101 // ------------
1102 bool
1103 MSVehicle::addStop(const SUMOVehicleParameter::Stop& stopPar, std::string& errorMsg, SUMOTime untilOffset, bool collision,
1104  MSRouteIterator* searchStart) {
1105  Stop stop(stopPar);
1106  stop.lane = MSLane::dictionary(stopPar.lane);
1107  if (!stop.lane->allowsVehicleClass(myType->getVehicleClass())) {
1108  errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on lane '" + stopPar.lane + "'.";
1109  return false;
1110  }
1115  stop.duration = stopPar.duration;
1116  stop.triggered = stopPar.triggered;
1117  stop.containerTriggered = stopPar.containerTriggered;
1118  stop.timeToBoardNextPerson = 0;
1119  stop.timeToLoadNextContainer = 0;
1120  if (stopPar.until != -1) {
1121  // !!! it would be much cleaner to invent a constructor for stops which takes "until" as an argument
1122  const_cast<SUMOVehicleParameter::Stop&>(stop.pars).until += untilOffset;
1123  }
1124  stop.collision = collision;
1125  stop.reached = false;
1126  stop.numExpectedPerson = (int)stopPar.awaitedPersons.size();
1127  stop.numExpectedContainer = (int)stopPar.awaitedContainers.size();
1128  std::string stopType = "stop";
1129  std::string stopID = "";
1130  if (stop.busstop != 0) {
1131  stopType = "busStop";
1132  stopID = stop.busstop->getID();
1133  } else if (stop.containerstop != 0) {
1134  stopType = "containerStop";
1135  stopID = stop.containerstop->getID();
1136  } else if (stop.chargingStation != 0) {
1137  stopType = "chargingStation";
1138  stopID = stop.chargingStation->getID();
1139  } else if (stop.parkingarea != 0) {
1140  stopType = "parkingArea";
1141  stopID = stop.parkingarea->getID();
1142  }
1143  const std::string errorMsgStart = stopID == "" ? stopType : stopType + " '" + stopID + "'";
1144 
1145  if (stop.pars.startPos < 0 || stop.pars.endPos > stop.lane->getLength()) {
1146  errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stopPar.lane + "' has an invalid position.";
1147  return false;
1148  }
1149  if (stopType != "stop" && stopType != "parkingArea" && myType->getLength() / 2. > stop.pars.endPos - stop.pars.startPos) {
1150  errorMsg = errorMsgStart + " on lane '" + stopPar.lane + "' is too short for vehicle '" + myParameter->id + "'.";
1151  }
1152  // if stop is on an internal edge the normal edge before the intersection is used
1153  const MSEdge* stopEdge = stop.lane->getEdge().getNormalBefore();
1154  if (searchStart == 0) {
1155  searchStart = &myCurrEdge;
1156  }
1157  stop.edge = find(*searchStart, myRoute->end(), stopEdge);
1158  MSRouteIterator prevStopEdge = myCurrEdge;
1159  double prevStopPos = myState.myPos;
1160  // where to insert the stop
1161  std::list<Stop>::iterator iter = myStops.begin();
1162  if (stopPar.index == STOP_INDEX_END || stopPar.index >= static_cast<int>(myStops.size())) {
1163  if (myStops.size() > 0) {
1164  prevStopEdge = myStops.back().edge;
1165  prevStopPos = myStops.back().pars.endPos;
1166  iter = myStops.end();
1167  stop.edge = find(prevStopEdge, myRoute->end(), stopEdge);
1168  if (prevStopEdge == stop.edge && prevStopPos > stop.pars.endPos) {
1169  stop.edge = find(prevStopEdge + 1, myRoute->end(), stopEdge);
1170  }
1171  }
1172  } else {
1173  if (stopPar.index == STOP_INDEX_FIT) {
1174  while (iter != myStops.end() && (iter->edge < stop.edge ||
1175  (iter->pars.endPos < stop.pars.endPos && iter->edge == stop.edge))) {
1176  prevStopEdge = iter->edge;
1177  prevStopPos = iter->pars.endPos;
1178  ++iter;
1179  }
1180  } else {
1181  int index = stopPar.index;
1182  while (index > 0) {
1183  prevStopEdge = iter->edge;
1184  prevStopPos = iter->pars.endPos;
1185  ++iter;
1186  --index;
1187  }
1188  stop.edge = find(prevStopEdge, myRoute->end(), stopEdge);
1189  }
1190  }
1191  if (stop.edge == myRoute->end() || prevStopEdge > stop.edge ||
1192  (prevStopEdge == stop.edge && prevStopPos > stop.pars.endPos && !collision)
1193  || (stop.lane->getEdge().isInternal() && stop.lane->getNextNormal() != *(stop.edge + 1))) {
1194  if (stop.edge != myRoute->end()) {
1195  // check if the edge occurs again later in the route
1196  MSRouteIterator next = stop.edge + 1;
1197  return addStop(stopPar, errorMsg, untilOffset, collision, &next);
1198  }
1199  errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stopPar.lane + "' is not downstream the current route.";
1200  return false;
1201  }
1202  // David.C:
1203  //if (!stop.parking && (myCurrEdge == stop.edge && myState.myPos > stop.endPos - getCarFollowModel().brakeGap(myState.mySpeed))) {
1204  const double endPosOffset = stop.lane->getEdge().isInternal() ? (*stop.edge)->getLength() : 0;
1205  if (collision) {
1206  assert(myCurrEdge == stop.edge);
1207  myState.myPos = stop.pars.endPos;
1208  myState.mySpeed = 0;
1209  } else if (myCurrEdge == stop.edge && myState.myPos > stop.pars.endPos + endPosOffset - getCarFollowModel().brakeGap(myState.mySpeed)) {
1210  errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stopPar.lane + "' is too close to break.";
1211  return false;
1212  }
1213  if (!hasDeparted() && myCurrEdge == stop.edge) {
1214  double pos = -1;
1216  pos = myParameter->departPos;
1217  if (pos < 0.) {
1218  pos += (*myCurrEdge)->getLength();
1219  }
1220  }
1222  pos = MIN2(static_cast<double>(getVehicleType().getLength() + POSITION_EPS), (*myCurrEdge)->getLength());
1223  }
1224  if (pos > stop.pars.endPos + endPosOffset) {
1225  if (stop.edge != myRoute->end()) {
1226  // check if the edge occurs again later in the route
1227  MSRouteIterator next = stop.edge + 1;
1228  return addStop(stopPar, errorMsg, untilOffset, collision, &next);
1229  }
1230  errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stopPar.lane + "' is before departPos.";
1231  return false;
1232  }
1233  }
1234  if (iter != myStops.begin()) {
1235  std::list<Stop>::iterator iter2 = iter;
1236  iter2--;
1237  if (stop.pars.until >= 0 && iter2->pars.until > stop.pars.until) {
1238  errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stopPar.lane + "' ends earlier than previous stop.";
1239  }
1240  }
1241  myStops.insert(iter, stop);
1242  return true;
1243 }
1244 
1245 
1246 bool
1247 MSVehicle::replaceParkingArea(MSParkingArea* parkingArea, std::string& errorMsg) {
1248  // Check if there is a parking area to be replaced
1249  assert(parkingArea != 0);
1250  if (myStops.empty()) {
1251  errorMsg = "Vehicle '" + myParameter->id + "' has no stops.";
1252  return false;
1253  }
1255  Stop stop = myStops.front();
1256  if (stop.reached) {
1257  errorMsg = "current stop already reached";
1258  return false;
1259  }
1260  if (stop.parkingarea == 0) {
1261  errorMsg = "current stop is not a parkingArea";
1262  return false;
1263  }
1264  if (stop.parkingarea == parkingArea) {
1265  errorMsg = "current stop is the same as the new parking area";
1266  return false;
1267  }
1268  stopPar.lane = parkingArea->getLane().getID();
1269 
1270  // merge duplicated stops equals to parking area
1271  int removeStops = 0;
1272  SUMOTime duration = 0;
1273 
1274  for (std::list<Stop>::const_iterator iter = myStops.begin(); iter != myStops.end(); ++iter) {
1275  if (duration == 0) {
1276  duration = iter->duration;
1277  ++removeStops;
1278  } else {
1279  if (iter->parkingarea != 0 && iter->parkingarea == parkingArea) {
1280  duration += iter->duration;
1281  ++removeStops;
1282  } else {
1283  break;
1284  }
1285  }
1286  }
1287 
1288  stopPar.index = 0;
1289  stopPar.busstop = "";
1290  stopPar.chargingStation = "";
1291  stopPar.containerstop = "";
1292  stopPar.parkingarea = parkingArea->getID();
1293  stopPar.startPos = parkingArea->getBeginLanePosition();
1294  stopPar.endPos = parkingArea->getEndLanePosition();
1295  stopPar.duration = duration;
1296  stopPar.until = stop.pars.until;
1297  stopPar.awaitedPersons = stop.pars.awaitedPersons;
1298  stopPar.awaitedContainers = stop.pars.awaitedContainers;
1299  stopPar.triggered = stop.pars.triggered;
1301  stopPar.parking = stop.pars.parking;
1302  stopPar.parametersSet = stop.pars.parametersSet;
1303 
1304  // remove stops equals to parking area
1305  while (removeStops > 0) {
1306  myStops.pop_front();
1307  --removeStops;
1308  }
1309  const bool result = addStop(stopPar, errorMsg);
1310  if (myLane != 0) {
1311  updateBestLanes(true);
1312  }
1313  return result;
1314 }
1315 
1316 
1319  MSParkingArea* nextParkingArea = 0;
1320  if (!myStops.empty()) {
1322  Stop stop = myStops.front();
1323  if (!stop.reached && stop.parkingarea != 0) {
1324  nextParkingArea = stop.parkingarea;
1325  }
1326  }
1327  return nextParkingArea;
1328 }
1329 
1330 
1331 bool
1333  return !myStops.empty() && myStops.begin()->reached /*&& myState.mySpeed < SUMO_const_haltingSpeed @todo #1864#*/;
1334 }
1335 
1336 bool
1338  return isStopped() && myStops.front().lane == myLane;
1339 }
1340 
1341 bool
1342 MSVehicle::keepStopping(bool afterProcessing) const {
1343  if (isStopped()) {
1344  // after calling processNextStop, DELTA_T has already been subtracted from the duration
1345  return myStops.front().duration + (afterProcessing ? DELTA_T : 0) > 0 || isStoppedTriggered() || myStops.front().collision;
1346  } else {
1347  return false;
1348  }
1349 }
1350 
1351 SUMOTime
1353  return (myStops.empty() || !myStops.front().collision) ? myCollisionImmunity : MAX2((SUMOTime)0, myStops.front().duration);
1354 }
1355 
1356 
1357 bool
1359  return isStopped() && myStops.begin()->pars.parking;
1360 }
1361 
1362 
1363 bool
1365  return isStopped() && (myStops.begin()->triggered || myStops.begin()->containerTriggered);
1366 }
1367 
1368 
1369 bool
1370 MSVehicle::isStoppedInRange(double pos) const {
1371  return isStopped() && myStops.begin()->pars.startPos <= pos && myStops.begin()->pars.endPos >= pos;
1372 }
1373 
1374 
1375 double
1376 MSVehicle::processNextStop(double currentVelocity) {
1377  if (myStops.empty()) {
1378  // no stops; pass
1379  return currentVelocity;
1380  }
1381 
1382 #ifdef DEBUG_STOPS
1383  if (DEBUG_COND) {
1384  std::cout << "\nPROCESS_NEXT_STOP\n" << SIMTIME << " vehicle '" << getID() << "'" << std::endl;
1385  }
1386 #endif
1387 
1388  Stop& stop = myStops.front();
1389  if (stop.reached) {
1390 
1391 #ifdef DEBUG_STOPS
1392  if (DEBUG_COND) {
1393  std::cout << SIMTIME << " vehicle '" << getID() << "' reached stop.\n"
1394  << "Remaining duration: " << STEPS2TIME(stop.duration) << std::endl;
1395  }
1396 #endif
1397  // ok, we have already reached the next stop
1398  // any waiting persons may board now
1399  MSNet* const net = MSNet::getInstance();
1400  const bool boarded = net->hasPersons() && net->getPersonControl().boardAnyWaiting(&myLane->getEdge(), this, &stop) && stop.numExpectedPerson == 0;
1401  // load containers
1402  const bool loaded = net->hasContainers() && net->getContainerControl().loadAnyWaiting(&myLane->getEdge(), this, &stop) && stop.numExpectedContainer == 0;
1403  if (boarded) {
1404  if (stop.busstop != 0) {
1405  const std::vector<MSTransportable*>& persons = myPersonDevice->getTransportables();
1406  for (std::vector<MSTransportable*>::const_iterator i = persons.begin(); i != persons.end(); ++i) {
1407  stop.busstop->removeTransportable(*i);
1408  }
1409  }
1410  // the triggering condition has been fulfilled. Maybe we want to wait a bit longer for additional riders (car pooling)
1411  stop.triggered = false;
1415 #ifdef DEBUG_STOPS
1416  if (DEBUG_COND) {
1417  std::cout << SIMTIME << " vehicle '" << getID() << "' unregisters as waiting for person." << std::endl;
1418  }
1419 #endif
1420  }
1421  }
1422  if (loaded) {
1423  if (stop.containerstop != 0) {
1424  const std::vector<MSTransportable*>& containers = myContainerDevice->getTransportables();
1425  for (std::vector<MSTransportable*>::const_iterator i = containers.begin(); i != containers.end(); ++i) {
1427  }
1428  }
1429  // the triggering condition has been fulfilled
1430  stop.containerTriggered = false;
1434 #ifdef DEBUG_STOPS
1435  if (DEBUG_COND) {
1436  std::cout << SIMTIME << " vehicle '" << getID() << "' unregisters as waiting for container." << std::endl;
1437  }
1438 #endif
1439  }
1440  }
1441  if (!keepStopping() && isOnRoad()) {
1442 #ifdef DEBUG_STOPS
1443  if (DEBUG_COND) {
1444  std::cout << SIMTIME << " vehicle '" << getID() << "' resumes from stopping." << std::endl;
1445  }
1446 #endif
1448  } else {
1450  if (getVehicleType().getPersonCapacity() == getPersonNumber()) {
1451  WRITE_WARNING("Vehicle '" + getID() + "' ignores triggered stop on lane '" + stop.lane->getID() + "' due to capacity constraints.");
1452  stop.triggered = false;
1453  }
1454  // we can only register after waiting for one step. otherwise we might falsely signal a deadlock
1457 #ifdef DEBUG_STOPS
1458  if (DEBUG_COND) {
1459  std::cout << SIMTIME << " vehicle '" << getID() << "' registers as waiting for person." << std::endl;
1460  }
1461 #endif
1462  }
1464  if (getVehicleType().getContainerCapacity() == getContainerNumber()) {
1465  WRITE_WARNING("Vehicle '" + getID() + "' ignores container triggered stop on lane '" + stop.lane->getID() + "' due to capacity constraints.");
1466  stop.containerTriggered = false;
1467  }
1468  // we can only register after waiting for one step. otherwise we might falsely signal a deadlock
1471 #ifdef DEBUG_STOPS
1472  if (DEBUG_COND) {
1473  std::cout << SIMTIME << " vehicle '" << getID() << "' registers as waiting for container." << std::endl;
1474  }
1475 #endif
1476  }
1477  // we have to wait some more time
1478  stop.duration -= getActionStepLength();
1479 
1481  // euler
1482  return 0;
1483  } else {
1484  // ballistic:
1485  return getCarFollowModel().stopSpeed(this, getSpeed(), stop.getEndPos(*this) - myState.pos());
1486  }
1487  }
1488  } else {
1489 
1490 #ifdef DEBUG_STOPS
1491  if (DEBUG_COND) {
1492  std::cout << SIMTIME << " vehicle '" << getID() << "' hasn't reached next stop." << std::endl;
1493  }
1494 #endif
1495 
1496  // is the next stop on the current lane?
1497  if (stop.edge == myCurrEdge) {
1498  // get the stopping position
1499  double endPos = stop.pars.endPos;
1500  bool useStoppingPlace = false;
1501  bool fitsOnStoppingPlace = true;
1502  if (stop.busstop != 0) {
1503  useStoppingPlace = true;
1504  // on bus stops, we have to wait for free place if they are in use...
1505  endPos = stop.busstop->getLastFreePos(*this);
1506  // at least half the bus has to fit on non-empty bus stops
1507  if (endPos != stop.busstop->getEndLanePosition() && endPos - myType->getLength() / 2. < stop.busstop->getBeginLanePosition()) {
1508  fitsOnStoppingPlace = false;
1509  }
1510  }
1511  // if the stop is a container stop we check if the vehicle fits into the last free position of the stop
1512  if (stop.containerstop != 0) {
1513  useStoppingPlace = true;
1514  // on container stops, we have to wait for free place if they are in use...
1515  endPos = stop.containerstop->getLastFreePos(*this);
1516  if (endPos != stop.containerstop->getEndLanePosition() && endPos - myType->getLength() / 2. < stop.containerstop->getBeginLanePosition()) {
1517  fitsOnStoppingPlace = false;
1518  }
1519  }
1520  // if the stop is a parking area we check if there is a free position on the area
1521  if (stop.parkingarea != 0) {
1522  endPos = stop.parkingarea->getLastFreePos(*this);
1523  if (stop.parkingarea->getOccupancy() == stop.parkingarea->getCapacity()) {
1524  fitsOnStoppingPlace = false;
1525  // leave enough space so parking vehicles can exit
1526  endPos -= getVehicleType().getMinGap();
1527  // trigger potential parkingZoneReroute
1528  for (std::vector< MSMoveReminder* >::const_iterator rem = myLane->getMoveReminders().begin(); rem != myLane->getMoveReminders().end(); ++rem) {
1529  addReminder(*rem);
1530  }
1531  MSParkingArea* oldParkingArea = stop.parkingarea;
1533  if (myStops.empty() || myStops.front().parkingarea != oldParkingArea) {
1534  // rerouted, keep driving
1535  return currentVelocity;
1536  }
1537  }
1538  }
1539  if (stop.lane->getEdge().isInternal() && &myLane->getEdge() != &stop.lane->getEdge()) {
1540  // endPos is on subsequent edge
1541  endPos += myLane->getLength();
1542  }
1543 
1544  const double reachedThreshold = (useStoppingPlace ? endPos - STOPPING_PLACE_OFFSET : stop.pars.startPos) - NUMERICAL_EPS;
1545  if (myState.pos() >= reachedThreshold && fitsOnStoppingPlace && currentVelocity <= SUMO_const_haltingSpeed && myLane == stop.lane) {
1546  // ok, we may stop (have reached the stop)
1547  stop.reached = true;
1548 #ifdef DEBUG_STOPS
1549  if (DEBUG_COND) {
1550  std::cout << SIMTIME << " vehicle '" << getID() << "' reached next stop." << std::endl;
1551  }
1552 #endif
1553  if (MSStopOut::active()) {
1555  }
1556  MSNet::getInstance()->getVehicleControl().addWaiting(&myLane->getEdge(), this);
1558  // compute stopping time
1559  if (stop.pars.until >= 0) {
1560  if (stop.duration == -1) {
1562  } else {
1564  }
1565  }
1566  if (stop.busstop != 0) {
1567  // let the bus stop know the vehicle
1568  stop.busstop->enter(this, myState.pos() + getVehicleType().getMinGap(), myState.pos() - myType->getLength());
1569  }
1570  if (stop.containerstop != 0) {
1571  // let the container stop know the vehicle
1573  }
1574  if (stop.parkingarea != 0) {
1575  // let the parking area know the vehicle
1577  }
1578  }
1579  // decelerate
1581  // euler
1582  return getCarFollowModel().stopSpeed(this, getSpeed(), endPos - myState.pos() + NUMERICAL_EPS);
1583  } else {
1584  // ballistic
1585  return getCarFollowModel().stopSpeed(this, myState.mySpeed, endPos - myState.myPos);
1586  }
1587  }
1588  }
1589  return currentVelocity;
1590 }
1591 
1592 
1593 const ConstMSEdgeVector
1595  ConstMSEdgeVector result;
1596  for (std::list<Stop>::const_iterator iter = myStops.begin(); iter != myStops.end(); ++iter) {
1597  result.push_back(*iter->edge);
1598  }
1599  return result;
1600 }
1601 
1602 
1603 bool
1606  if (myActionStep) {
1607  myLastActionTime = t;
1608  }
1609  return myActionStep;
1610 }
1611 
1612 void
1613 MSVehicle::resetActionOffset(const SUMOTime timeUntilNextAction) {
1614  myLastActionTime = MSNet::getInstance()->getCurrentTimeStep() + timeUntilNextAction;
1615 }
1616 
1617 void
1618 MSVehicle::updateActionOffset(const SUMOTime oldActionStepLength, const SUMOTime newActionStepLength) {
1620  SUMOTime timeSinceLastAction = now - myLastActionTime;
1621  if (timeSinceLastAction == 0) {
1622  // Action was scheduled now, may be delayed be new action step length
1623  timeSinceLastAction = oldActionStepLength;
1624  }
1625  if (timeSinceLastAction >= newActionStepLength) {
1626  // Action point required in this step
1627  myLastActionTime = now;
1628  } else {
1629  SUMOTime timeUntilNextAction = newActionStepLength - timeSinceLastAction;
1630  resetActionOffset(timeUntilNextAction);
1631  }
1632 }
1633 
1634 
1635 
1636 void
1637 MSVehicle::planMove(const SUMOTime t, const MSLeaderInfo& ahead, const double lengthsInFront) {
1638 #ifdef DEBUG_PLAN_MOVE
1639  if (DEBUG_COND) {
1640  std::cout
1641  << "\nPLAN_MOVE\n"
1642  << STEPS2TIME(t)
1643  << " veh=" << getID()
1644  << " lane=" << myLane->getID()
1645  << " pos=" << getPositionOnLane()
1646  << " posLat=" << getLateralPositionOnLane()
1647  << " speed=" << getSpeed()
1648  << "\n";
1649  }
1650 #endif
1651  if (!checkActionStep(t)) {
1652 #ifdef DEBUG_ACTIONSTEPS
1653  if DEBUG_COND {
1654  std::cout << STEPS2TIME(t) << " vehicle '" << getID() << "' skips action." << std::endl;
1655  }
1656 #endif
1657  // During non-action passed drive items still need to be removed
1659  return;
1660  } else {
1661 #ifdef DEBUG_ACTIONSTEPS
1662  if DEBUG_COND {
1663  std::cout << STEPS2TIME(t) << " vehicle = '" << getID() << "' takes action." << std::endl;
1664  }
1665 #endif
1666 
1667 
1669 #ifdef DEBUG_PLAN_MOVE
1670  if (DEBUG_COND) {
1671  DriveItemVector::iterator i;
1672  for (i = myLFLinkLanes.begin(); i != myLFLinkLanes.end(); ++i) {
1673  std::cout
1674  << " vPass=" << (*i).myVLinkPass
1675  << " vWait=" << (*i).myVLinkWait
1676  << " linkLane=" << ((*i).myLink == 0 ? "NULL" : (*i).myLink->getViaLaneOrLane()->getID())
1677  << " request=" << (*i).mySetRequest
1678  << "\n";
1679  }
1680  }
1681 #endif
1682  checkRewindLinkLanes(lengthsInFront, myLFLinkLanes);
1683  myNextDriveItem = myLFLinkLanes.begin();
1684 #ifdef DEBUG_PLAN_MOVE
1685  if (DEBUG_COND) {
1686  std::cout << " after checkRewindLinkLanes\n";
1687  DriveItemVector::iterator i;
1688  for (i = myLFLinkLanes.begin(); i != myLFLinkLanes.end(); ++i) {
1689  std::cout
1690  << " vPass=" << (*i).myVLinkPass
1691  << " vWait=" << (*i).myVLinkWait
1692  << " linkLane=" << ((*i).myLink == 0 ? "NULL" : (*i).myLink->getViaLaneOrLane()->getID())
1693  << " request=" << (*i).mySetRequest
1694  << " atime=" << (*i).myArrivalTime
1695  << " atimeB=" << (*i).myArrivalTimeBraking
1696  << "\n";
1697  }
1698  }
1699 #endif
1700  }
1702 }
1703 
1704 
1705 void
1707  // remove information about approaching links, will be reset later in this step
1709  lfLinks.clear();
1710  myStopDist = std::numeric_limits<double>::max();
1711  //
1712  const MSCFModel& cfModel = getCarFollowModel();
1713  const double vehicleLength = getVehicleType().getLength();
1714  const double maxV = cfModel.maxNextSpeed(myState.mySpeed, this);
1715  const bool opposite = getLaneChangeModel().isOpposite();
1716  double laneMaxV = myLane->getVehicleMaxSpeed(this);
1717  // v is the initial maximum velocity of this vehicle in this step
1718  double v = MIN2(maxV, laneMaxV);
1719 #ifndef NO_TRACI
1720  if (myInfluencer != 0) {
1721  //const double vMin = MAX2(0., cfModel.getSpeedAfterMaxDecel(myState.mySpeed));
1722  const double vMin = MAX2(0., cfModel.minNextSpeed(myState.mySpeed, this));
1723  v = myInfluencer->influenceSpeed(MSNet::getInstance()->getCurrentTimeStep(), v, v, vMin, maxV);
1724  }
1725 #endif
1726  // all links within dist are taken into account (potentially)
1727  // the distance already "seen"; in the following always up to the end of the current "lane"
1728  const double dist = SPEED2DIST(maxV) + cfModel.brakeGap(maxV);
1729 
1730  const std::vector<MSLane*>& bestLaneConts = getBestLanesContinuation();
1731 #ifdef DEBUG_PLAN_MOVE
1732  if (DEBUG_COND) {
1733  std::cout << " bestLaneConts=" << toString(bestLaneConts) << "\n";
1734  }
1735 #endif
1736  assert(bestLaneConts.size() > 0);
1737  bool hadNonInternal = false;
1738  double seen = opposite ? myState.myPos : myLane->getLength() - myState.myPos; // the distance already "seen"; in the following always up to the end of the current "lane"
1739  double seenNonInternal = 0;
1740  double vLinkPass = MIN2(cfModel.estimateSpeedAfterDistance(seen, v, cfModel.getMaxAccel()), laneMaxV); // upper bound
1741  int view = 0;
1742  DriveProcessItem* lastLink = 0;
1743  bool slowedDownForMinor = false; // whether the vehicle already had to slow down on approach to a minor link
1744  // iterator over subsequent lanes and fill lfLinks until stopping distance or stopped
1745  const MSLane* lane = opposite ? myLane->getOpposite() : myLane;
1746  assert(lane != 0);
1747  const MSLane* leaderLane = myLane;
1748 #ifdef _MSC_VER
1749 #pragma warning(push)
1750 #pragma warning(disable: 4127) // do not warn about constant conditional expression
1751 #endif
1752  while (true) {
1753 #ifdef _MSC_VER
1754 #pragma warning(pop)
1755 #endif
1756  // check leader on lane
1757  // leader is given for the first edge only
1758  if (opposite &&
1759  (leaderLane->getVehicleNumber() > 1
1760  || (leaderLane != myLane && leaderLane->getVehicleNumber() > 0))) {
1761  // find opposite-driving leader that must be respected on the currently looked at lane
1762  // XXX make sure to look no further than leaderLane
1763  CLeaderDist leader = leaderLane->getOppositeLeader(this, getPositionOnLane(), true);
1764  ahead.clear();
1765  if (leader.first != 0 && leader.first->getLane() == leaderLane && leader.first->getLaneChangeModel().isOpposite()) {
1766  ahead.addLeader(leader.first, true);
1767  }
1768  }
1769  adaptToLeaders(ahead, 0, seen, lastLink, leaderLane, v, vLinkPass);
1770 #ifdef DEBUG_PLAN_MOVE
1771  if (DEBUG_COND) {
1772  std::cout << "\nv = " << v << "\n";
1773 
1774  }
1775 #endif
1776  // XXX efficiently adapt to shadow leaders using neighAhead by iteration over the whole edge in parallel (lanechanger-style)
1777  if (getLaneChangeModel().getShadowLane() != 0) {
1778  // also slow down for leaders on the shadowLane relative to the current lane
1779  const MSLane* shadowLane = getLaneChangeModel().getShadowLane(lane);
1780  if (shadowLane != 0) {
1781  const double latOffset = getLane()->getRightSideOnEdge() - getLaneChangeModel().getShadowLane()->getRightSideOnEdge();
1782  adaptToLeaders(shadowLane->getLastVehicleInformation(this, latOffset, lane->getLength() - seen),
1783  latOffset,
1784  seen, lastLink, shadowLane, v, vLinkPass);
1785  }
1786  }
1787  // adapt to pedestrians on the same lane
1788  if (lane->getEdge().getPersons().size() > 0 && MSPModel::getModel()->hasPedestrians(lane)) {
1789  const double relativePos = lane->getLength() - seen;
1790 #ifdef DEBUG_PLAN_MOVE
1791  if (DEBUG_COND) {
1792  std::cout << SIMTIME << " adapt to pedestrians on lane=" << lane->getID() << " relPos=" << relativePos << "\n";
1793  }
1794 #endif
1795  PersonDist leader = MSPModel::getModel()->nextBlocking(lane, relativePos,
1797  if (leader.first != 0) {
1798  const double stopSpeed = cfModel.stopSpeed(this, getSpeed(), leader.second - getVehicleType().getMinGap());
1799  v = MIN2(v, stopSpeed);
1800 #ifdef DEBUG_PLAN_MOVE
1801  if (DEBUG_COND) {
1802  std::cout << SIMTIME << " pedLeader=" << leader.first->getID() << " dist=" << leader.second << " v=" << v << "\n";
1803  }
1804 #endif
1805  }
1806  }
1807 
1808  // process stops
1809  if (!myStops.empty() && &myStops.begin()->lane->getEdge() == &lane->getEdge() && !myStops.begin()->reached
1810  // ignore stops that occur later in a looped route
1811  && myStops.front().edge == myCurrEdge + view) {
1812  // we are approaching a stop on the edge; must not drive further
1813  const Stop& stop = *myStops.begin();
1814  const double endPos = stop.getEndPos(*this) + NUMERICAL_EPS;
1815  myStopDist = seen + endPos - lane->getLength();
1816  const double stopSpeed = cfModel.stopSpeed(this, getSpeed(), myStopDist);
1817  if (lastLink != 0) {
1818  lastLink->adaptLeaveSpeed(cfModel.stopSpeed(this, vLinkPass, endPos));
1819  }
1820  v = MIN2(v, stopSpeed);
1821  lfLinks.push_back(DriveProcessItem(v, myStopDist));
1822 
1823 #ifdef DEBUG_PLAN_MOVE
1824  if (DEBUG_COND) {
1825  std::cout << "\n" << SIMTIME << " next stop: distance = " << myStopDist << " requires stopSpeed = " << stopSpeed << "\n";
1826 
1827  }
1828 #endif
1829 
1830  break;
1831  }
1832 
1833  // move to next lane
1834  // get the next link used
1835  MSLinkCont::const_iterator link = MSLane::succLinkSec(*this, view + 1, *lane, bestLaneConts);
1836  // check whether the vehicle is on its final edge
1837  if (myCurrEdge + view + 1 == myRoute->end()) {
1838  const double arrivalSpeed = (myParameter->arrivalSpeedProcedure == ARRIVAL_SPEED_GIVEN ?
1839  myParameter->arrivalSpeed : laneMaxV);
1840  // subtract the arrival speed from the remaining distance so we get one additional driving step with arrival speed
1841  // XXX: This does not work for ballistic update refs #2579
1842  const double distToArrival = seen + myArrivalPos - lane->getLength() - SPEED2DIST(arrivalSpeed);
1843  const double va = MAX2(NUMERICAL_EPS, cfModel.freeSpeed(this, getSpeed(), distToArrival, arrivalSpeed));
1844  v = MIN2(v, va);
1845  if (lastLink != 0) {
1846  lastLink->adaptLeaveSpeed(va);
1847  }
1848  lfLinks.push_back(DriveProcessItem(v, seen, lane->getEdge().isFringe() ? 1000 : 0));
1849  break;
1850  }
1851  // check whether the lane or the shadowLane is a dead end (allow some leeway on intersections)
1852  if (lane->isLinkEnd(link) ||
1853  ((*link)->getViaLane() == 0
1855  // do not get stuck on narrow edges
1856  && getVehicleType().getWidth() <= lane->getEdge().getWidth()
1857  // this is the exit link of a junction. The normal edge should support the shadow
1858  && ((getLaneChangeModel().getShadowLane((*link)->getLane()) == 0)
1859  // the internal lane after an internal junction has no parallel lane. make sure there is no shadow before continuing
1860  || (lane->getEdge().isInternal() && lane->getIncomingLanes()[0].lane->getEdge().isInternal()))
1861  // ignore situations where the shadow lane is part of a double-connection with the current lane
1862  && (getLaneChangeModel().getShadowLane() == 0
1863  || getLaneChangeModel().getShadowLane()->getLinkCont().size() == 0
1864  || getLaneChangeModel().getShadowLane()->getLinkCont().front()->getLane() != (*link)->getLane())
1865  )) {
1866  double va = MIN2(cfModel.stopSpeed(this, getSpeed(), seen), laneMaxV);
1867  if (lastLink != 0) {
1868  lastLink->adaptLeaveSpeed(va);
1869  }
1870  if (getLaneChangeModel().getCommittedSpeed() > 0) {
1871  v = MIN2(getLaneChangeModel().getCommittedSpeed(), v);
1872  } else {
1873  v = MIN2(va, v);
1874  }
1875 #ifdef DEBUG_PLAN_MOVE
1876  if (DEBUG_COND) {
1877  std::cout << " braking for link end: overlap=" << getLateralOverlap() << " va=" << va << " committed=" << getLaneChangeModel().getCommittedSpeed() << " v=" << v << "\n";
1878 
1879  }
1880 #endif
1881  if (lane->isLinkEnd(link)) {
1882  lfLinks.push_back(DriveProcessItem(v, seen));
1883  break;
1884  }
1885  }
1886  const bool yellowOrRed = (*link)->haveRed() || (*link)->haveYellow();
1887  // We distinguish 3 cases when determining the point at which a vehicle stops:
1888  // - links that require stopping: here the vehicle needs to stop close to the stop line
1889  // to ensure it gets onto the junction in the next step. Otherwise the vehicle would 'forget'
1890  // that it already stopped and need to stop again. This is necessary pending implementation of #999
1891  // - red/yellow light: here the vehicle 'knows' that it will have priority eventually and does not need to stop on a precise spot
1892  // - other types of minor links: the vehicle needs to stop as close to the junction as necessary
1893  // to minimize the time window for passing the junction. If the
1894  // vehicle 'decides' to accelerate and cannot enter the junction in
1895  // the next step, new foes may appear and cause a collision (see #1096)
1896  // - major links: stopping point is irrelevant
1897  const double laneStopOffset = yellowOrRed || (*link)->havePriority() ? DIST_TO_STOPLINE_EXPECT_PRIORITY : POSITION_EPS;
1898  const double stopDist = MAX2(0., seen - laneStopOffset);
1899  // check whether we need to slow down in order to finish a continuous lane change
1900  if (getLaneChangeModel().isChangingLanes()) {
1901  if ( // slow down to finish lane change before a turn lane
1902  ((*link)->getDirection() == LINKDIR_LEFT || (*link)->getDirection() == LINKDIR_RIGHT) ||
1903  // slow down to finish lane change before the shadow lane ends
1904  (getLaneChangeModel().getShadowLane() != 0 &&
1905  (*link)->getViaLaneOrLane()->getParallelLane(getLaneChangeModel().getShadowDirection()) == 0)) {
1906  // XXX maybe this is too harsh. Vehicles could cut some corners here
1907  const double timeRemaining = STEPS2TIME(getLaneChangeModel().remainingTime());
1908  assert(timeRemaining != 0); // we seem to suppose that isChangingLanes() implies this (Leo)
1909  // XXX: Euler-logic (#860), but I couldn't identify problems from this yet (Leo). Refs. #2575
1910  const double va = MAX2(0., (seen - POSITION_EPS) / timeRemaining);
1911 #ifdef DEBUG_PLAN_MOVE
1912  if (DEBUG_COND) std::cout << SIMTIME << " veh=" << getID() << " slowing down to finish continuous change before"
1913  << " link=" << (*link)->getViaLaneOrLane()->getID()
1914  << " timeRemaining=" << timeRemaining
1915  << " v=" << v
1916  << " va=" << va
1917  << "\n";
1918 #endif
1919  v = MIN2(va, v);
1920  }
1921  }
1922 
1923  // - always issue a request to leave the intersection we are currently on
1924  const bool leavingCurrentIntersection = myLane->getEdge().isInternal() && lastLink == 0;
1925  // - do not issue a request to enter an intersection after we already slowed down for an earlier one
1926  const bool abortRequestAfterMinor = slowedDownForMinor && (*link)->getInternalLaneBefore() == 0;
1927  // - even if red, if we cannot break we should issue a request
1928  bool setRequest = (v > 0 && !abortRequestAfterMinor) || (leavingCurrentIntersection);
1929 
1930  double vLinkWait = MIN2(v, cfModel.stopSpeed(this, getSpeed(), stopDist));
1931  const double brakeDist = cfModel.brakeGap(myState.mySpeed, cfModel.getMaxDecel(), 0.);
1932  const bool canBrake = seen >= brakeDist;
1933 #ifdef DEBUG_PLAN_MOVE
1934  if (DEBUG_COND) {
1935  std::cout
1936  << " stopDist=" << stopDist
1937  << " vLinkWait=" << vLinkWait
1938  << " brakeDist=" << brakeDist
1939  << "\n";
1940  }
1941 #endif
1942  if (yellowOrRed && canBrake && !ignoreRed(*link, canBrake)) {
1943  // the vehicle is able to brake in front of a yellow/red traffic light
1944  lfLinks.push_back(DriveProcessItem(*link, vLinkWait, vLinkWait, false, t + TIME2STEPS(seen / MAX2(vLinkWait, NUMERICAL_EPS)), vLinkWait, 0, 0, seen));
1945  //lfLinks.push_back(DriveProcessItem(0, vLinkWait, vLinkWait, false, 0, 0, stopDist));
1946  break;
1947  }
1948 
1949  if (ignoreRed(*link, canBrake) && STEPS2TIME(t - (*link)->getLastStateChange()) > 2) {
1950  // restrict speed when ignoring a red light
1951  const double redSpeed = MIN2(v, getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_DRIVE_RED_SPEED, v));
1952  const double va = MAX2(redSpeed, cfModel.freeSpeed(this, getSpeed(), seen, redSpeed));
1953  v = MIN2(va, v);
1954 #ifdef DEBUG_EXEC_MOVE
1955  if (DEBUG_COND) std::cout
1956  << " ignoreRed spent=" << STEPS2TIME(t - (*link)->getLastStateChange())
1957  << " redSpeed=" << redSpeed
1958  << " va=" << va
1959  << " v=" << v
1960  << "\n";
1961 #endif
1962  }
1963 
1965  // we want to pass the link but need to check for foes on internal lanes
1966  checkLinkLeader(*link, lane, seen, lastLink, v, vLinkPass, vLinkWait, setRequest);
1967  if (getLaneChangeModel().getShadowLane() != 0) {
1968  MSLink* parallelLink = (*link)->getParallelLink(getLaneChangeModel().getShadowDirection());
1969  if (parallelLink != 0) {
1970  checkLinkLeader(parallelLink, lane, seen, lastLink, v, vLinkPass, vLinkWait, setRequest, true);
1971  }
1972  }
1973  }
1974 
1975  if (lastLink != 0) {
1976  lastLink->adaptLeaveSpeed(laneMaxV);
1977  }
1978  double arrivalSpeed = vLinkPass;
1979  // vehicles should decelerate when approaching a minor link
1980  // - unless they are close enough to have clear visibility of all relevant foe lanes and may start to accelerate again
1981  // - and unless they are so close that stopping is impossible (i.e. when a green light turns to yellow when close to the junction)
1982 
1983  // whether the vehicle/driver is close enough to the link to see all possible foes #2123
1984  double visibilityDistance = (*link)->getFoeVisibilityDistance();
1985  double determinedFoePresence = seen < visibilityDistance;
1986 // // VARIANT: account for time needed to recognize whether relevant vehicles are on the foe lanes. (Leo)
1987 // double foeRecognitionTime = 0.0;
1988 // double determinedFoePresence = seen < visibilityDistance - myState.mySpeed*foeRecognitionTime;
1989 
1990 #ifdef DEBUG_PLAN_MOVE
1991  if (DEBUG_COND) {
1992  std::cout << " approaching link=" << (*link)->getViaLaneOrLane()->getID() << " prio=" << (*link)->havePriority() << " seen=" << seen << " visibilityDistance=" << visibilityDistance << " brakeDist=" << brakeDist << "\n";
1993  }
1994 #endif
1995 
1996  if (!(*link)->havePriority() && !determinedFoePresence && brakeDist < seen && !(*link)->lastWasContMajor()) {
1997  // vehicle decelerates just enough to be able to stop if necessary and then accelerates
1998  double maxSpeedAtVisibilityDist = cfModel.maximumSafeStopSpeed(visibilityDistance, myState.mySpeed, false, 0.);
1999  // XXX: estimateSpeedAfterDistance does not use euler-logic (thus returns a lower value than possible here...)
2000  double maxArrivalSpeed = cfModel.estimateSpeedAfterDistance(visibilityDistance, maxSpeedAtVisibilityDist, cfModel.getMaxAccel());
2001  arrivalSpeed = MIN2(vLinkPass, maxArrivalSpeed);
2002  slowedDownForMinor = true;
2003 #ifdef DEBUG_PLAN_MOVE
2004  if (DEBUG_COND) {
2005  std::cout << " slowedDownForMinor maxArrivalSpeed=" << maxArrivalSpeed << " arrivalSpeed=" << arrivalSpeed << "\n";
2006  }
2007 #endif
2008  }
2009 
2010  SUMOTime arrivalTime;
2012  // @note intuitively it would make sense to compare arrivalSpeed with getSpeed() instead of v
2013  // however, due to the current position update rule (ticket #860) the vehicle moves with v in this step
2014  // subtract DELTA_T because t is the time at the end of this step and the movement is not carried out yet
2015  arrivalTime = t - DELTA_T + cfModel.getMinimalArrivalTime(seen, v, arrivalSpeed);
2016  } else {
2017  arrivalTime = t - DELTA_T + cfModel.getMinimalArrivalTime(seen, myState.mySpeed, arrivalSpeed);
2018  }
2019 
2020  // compute arrival speed and arrival time if vehicle starts braking now
2021  // if stopping is possible, arrivalTime can be arbitrarily large. A small value keeps fractional times (impatience) meaningful
2022  double arrivalSpeedBraking = 0;
2023  SUMOTime arrivalTimeBraking = arrivalTime + TIME2STEPS(30);
2024  if (seen < cfModel.brakeGap(v)) { // XXX: should this use the current speed (at least for the ballistic case)? (Leo) Refs. #2575
2025  // vehicle cannot come to a complete stop in time
2027  arrivalSpeedBraking = cfModel.getMinimalArrivalSpeedEuler(seen, v);
2028  // due to discrete/continuous mismatch (when using Euler update) we have to ensure that braking actually helps
2029  arrivalSpeedBraking = MIN2(arrivalSpeedBraking, arrivalSpeed);
2030  } else {
2031  arrivalSpeedBraking = cfModel.getMinimalArrivalSpeed(seen, myState.mySpeed);
2032  }
2033  arrivalTimeBraking = MAX2(arrivalTime, t + TIME2STEPS(seen / ((v + arrivalSpeedBraking) * 0.5)));
2034  }
2035  lfLinks.push_back(DriveProcessItem(*link, v, vLinkWait, setRequest,
2036  arrivalTime, arrivalSpeed,
2037  arrivalTimeBraking, arrivalSpeedBraking,
2038  seen,
2039  estimateLeaveSpeed(*link, arrivalSpeed)));
2040  if ((*link)->getViaLane() == 0) {
2041  hadNonInternal = true;
2042  ++view;
2043  }
2044  // we need to look ahead far enough to see available space for checkRewindLinkLanes
2045  if ((!setRequest || v <= 0 || seen > dist) && hadNonInternal && seenNonInternal > vehicleLength * CRLL_LOOK_AHEAD) {
2046  break;
2047  }
2048  // get the following lane
2049  lane = (*link)->getViaLaneOrLane();
2050  laneMaxV = lane->getVehicleMaxSpeed(this);
2051  // the link was passed
2052  // compute the velocity to use when the link is not blocked by other vehicles
2053  // the vehicle shall be not faster when reaching the next lane than allowed
2054  const double va = cfModel.freeSpeed(this, getSpeed(), seen, laneMaxV);
2055  v = MIN2(va, v);
2056  seenNonInternal += lane->getEdge().isInternal() ? 0 : lane->getLength();
2057  // do not restrict results to the current vehicle to allow caching for the current time step
2058  leaderLane = opposite ? lane->getOpposite() : lane;
2059  if (leaderLane == 0) {
2060  break;
2061  }
2062  ahead = opposite ? MSLeaderInfo(leaderLane) : leaderLane->getLastVehicleInformation(0, 0);
2063  seen += lane->getLength();
2064  vLinkPass = MIN2(cfModel.estimateSpeedAfterDistance(lane->getLength(), v, cfModel.getMaxAccel()), laneMaxV); // upper bound
2065  lastLink = &lfLinks.back();
2066  }
2067 
2068 //#ifdef DEBUG_PLAN_MOVE
2069 // if(DEBUG_COND){
2070 // std::cout << "planMoveInternal found safe speed v = " << v << std::endl;
2071 // }
2072 //#endif
2073 
2074 }
2075 
2076 
2077 void
2078 MSVehicle::adaptToLeaders(const MSLeaderInfo& ahead, double latOffset,
2079  const double seen, DriveProcessItem* const lastLink,
2080  const MSLane* const lane, double& v, double& vLinkPass) const {
2081  int rightmost;
2082  int leftmost;
2083  ahead.getSubLanes(this, latOffset, rightmost, leftmost);
2084 #ifdef DEBUG_PLAN_MOVE
2085  if (DEBUG_COND) std::cout << SIMTIME
2086  << "\nADAPT_TO_LEADERS\nveh=" << getID()
2087  << " lane=" << lane->getID()
2088  << " rm=" << rightmost
2089  << " lm=" << leftmost
2090  << " ahead=" << ahead.toString()
2091  << "\n";
2092 #endif
2093  /*
2094  if (getLaneChangeModel().getCommittedSpeed() > 0) {
2095  v = MIN2(v, getLaneChangeModel().getCommittedSpeed());
2096  vLinkPass = MIN2(vLinkPass, getLaneChangeModel().getCommittedSpeed());
2097  #ifdef DEBUG_PLAN_MOVE
2098  if (DEBUG_COND) std::cout << " hasCommitted=" << getLaneChangeModel().getCommittedSpeed() << "\n";
2099  #endif
2100  return;
2101  }
2102  */
2103  for (int sublane = rightmost; sublane <= leftmost; ++sublane) {
2104  const MSVehicle* pred = ahead[sublane];
2105  if (pred != 0) {
2106  // @todo avoid multiple adaptations to the same leader
2107  const double predBack = pred->getBackPositionOnLane(lane);
2108  const double gap = (lastLink == 0
2109  ? predBack - myState.myPos - getVehicleType().getMinGap()
2110  : predBack + seen - lane->getLength() - getVehicleType().getMinGap());
2111 #ifdef DEBUG_PLAN_MOVE
2112  if (DEBUG_COND) {
2113  std::cout << " pred=" << pred->getID() << " predLane=" << pred->getLane()->getID() << " predPos=" << pred->getPositionOnLane() << " gap=" << gap << " predBack=" << predBack << " seen=" << seen << " lane=" << lane->getID() << " myLane=" << myLane->getID() << "\n";
2114  }
2115 #endif
2116  adaptToLeader(std::make_pair(pred, gap), seen, lastLink, lane, v, vLinkPass);
2117  }
2118  }
2119 }
2120 
2121 
2122 void
2123 MSVehicle::adaptToLeader(const std::pair<const MSVehicle*, double> leaderInfo,
2124  const double seen, DriveProcessItem* const lastLink,
2125  const MSLane* const lane, double& v, double& vLinkPass,
2126  double distToCrossing) const {
2127  if (leaderInfo.first != 0) {
2128  const double vsafeLeader = getSafeFollowSpeed(leaderInfo, seen, lane, distToCrossing);
2129  if (lastLink != 0) {
2130  lastLink->adaptLeaveSpeed(vsafeLeader);
2131  }
2132  v = MIN2(v, vsafeLeader);
2133  vLinkPass = MIN2(vLinkPass, vsafeLeader);
2134 
2135 #ifdef DEBUG_PLAN_MOVE
2136  if (DEBUG_COND) std::cout
2137  << SIMTIME
2138  //std::cout << std::setprecision(10);
2139  << " veh=" << getID()
2140  << " lead=" << leaderInfo.first->getID()
2141  << " leadSpeed=" << leaderInfo.first->getSpeed()
2142  << " gap=" << leaderInfo.second
2143  << " leadLane=" << leaderInfo.first->getLane()->getID()
2144  << " predPos=" << leaderInfo.first->getPositionOnLane()
2145  << " seen=" << seen
2146  << " lane=" << lane->getID()
2147  << " myLane=" << myLane->getID()
2148  << " dTC=" << distToCrossing
2149  << " v=" << v
2150  << " vSafeLeader=" << vsafeLeader
2151  << " vLinkPass=" << vLinkPass
2152  << "\n";
2153 #endif
2154  }
2155 }
2156 
2157 
2158 void
2159 MSVehicle::checkLinkLeader(const MSLink* link, const MSLane* lane, double seen,
2160  DriveProcessItem* const lastLink, double& v, double& vLinkPass, double& vLinkWait, bool& setRequest,
2161  bool isShadowLink) const {
2162  const MSLink::LinkLeaders linkLeaders = link->getLeaderInfo(this, seen, 0, isShadowLink);
2163  for (MSLink::LinkLeaders::const_iterator it = linkLeaders.begin(); it != linkLeaders.end(); ++it) {
2164  // the vehicle to enter the junction first has priority
2165  const MSVehicle* leader = (*it).vehAndGap.first;
2166  if (leader == 0) {
2167  // leader is a pedestrian. Passing 'this' as a dummy.
2168  //std::cout << SIMTIME << " veh=" << getID() << " is blocked on link to " << (*link)->getViaLaneOrLane()->getID() << " by pedestrian. dist=" << it->distToCrossing << "\n";
2169  adaptToLeader(std::make_pair(this, -1), seen, lastLink, lane, v, vLinkPass, it->distToCrossing);
2170  } else if (link->isLeader(this, leader)) {
2172  // sibling link (XXX: could also be partial occupator where this check fails)
2173  &leader->getLane()->getEdge() == &lane->getEdge()) {
2174  // check for sublane obstruction (trivial for sibling link leaders)
2175  const MSLane* conflictLane = link->getInternalLaneBefore();
2176  MSLeaderInfo linkLeadersAhead = MSLeaderInfo(conflictLane);
2177  linkLeadersAhead.addLeader(leader, false, 0); // assume sibling lane has the same geometry as the leader lane
2178  const double latOffset = isShadowLink ? (getLane()->getRightSideOnEdge() - getLaneChangeModel().getShadowLane()->getRightSideOnEdge()) : 0;
2179  // leader is neither on lane nor conflictLane (the conflict is only established geometrically)
2180  adaptToLeaders(linkLeadersAhead, latOffset, seen, lastLink, leader->getLane(), v, vLinkPass);
2181 #ifdef DEBUG_PLAN_MOVE
2182  if (DEBUG_COND) {
2183  std::cout << SIMTIME << " veh=" << getID()
2184  << " siblingFoe link=" << link->getViaLaneOrLane()->getID()
2185  << " isShadowLink=" << isShadowLink
2186  << " lane=" << lane->getID()
2187  << " foe=" << leader->getID()
2188  << " foeLane=" << leader->getLane()->getID()
2189  << " latOffset=" << latOffset
2190  << " latOffsetFoe=" << leader->getLatOffset(lane)
2191  << " linkLeadersAhead=" << linkLeadersAhead.toString()
2192  << "\n";
2193  }
2194 #endif
2195  } else {
2196  adaptToLeader(it->vehAndGap, seen, lastLink, lane, v, vLinkPass, it->distToCrossing);
2197  }
2198  if (lastLink != 0) {
2199  // we are not yet on the junction with this linkLeader.
2200  // at least we can drive up to the previous link and stop there
2201  v = MAX2(v, lastLink->myVLinkWait);
2202  }
2203  // if blocked by a leader from the same or next lane we must yield our request
2204  if (v < SUMO_const_haltingSpeed
2205  //&& leader->getSpeed() < SUMO_const_haltingSpeed
2207  || leader->getLane()->getLogicalPredecessorLane() == myLane)) {
2208  setRequest = false;
2209  if (lastLink != 0 && leader->getLane()->getLogicalPredecessorLane() == myLane) {
2210  // we are not yet on the junction so must abort that request as well
2211  // (or maybe we are already on the junction and the leader is a partial occupator beyond)
2212  lastLink->mySetRequest = false;
2213  }
2214  // other vehicles may become junction leader when yielding
2215  link->passedJunction(this);
2216  }
2217  }
2218  }
2219  // if this is the link between two internal lanes we may have to slow down for pedestrians
2220  vLinkWait = MIN2(vLinkWait, v);
2221 }
2222 
2223 
2224 double
2225 MSVehicle::getSafeFollowSpeed(const std::pair<const MSVehicle*, double> leaderInfo,
2226  const double seen, const MSLane* const lane, double distToCrossing) const {
2227  assert(leaderInfo.first != 0);
2228  const MSCFModel& cfModel = getCarFollowModel();
2229  double vsafeLeader = 0;
2231  vsafeLeader = -std::numeric_limits<double>::max();
2232  }
2233  if (leaderInfo.second >= 0) {
2234  vsafeLeader = cfModel.followSpeed(this, getSpeed(), leaderInfo.second, leaderInfo.first->getSpeed(), leaderInfo.first->getCarFollowModel().getApparentDecel());
2235  } else {
2236  // the leading, in-lapping vehicle is occupying the complete next lane
2237  // stop before entering this lane
2238  vsafeLeader = cfModel.stopSpeed(this, getSpeed(), seen - lane->getLength() - POSITION_EPS);
2239  }
2240  if (distToCrossing >= 0) {
2241  // drive up to the crossing point with the current link leader
2242  vsafeLeader = MAX2(vsafeLeader, cfModel.stopSpeed(this, getSpeed(), distToCrossing));
2243  }
2244  return vsafeLeader;
2245 }
2246 
2247 double
2248 MSVehicle::getDeltaPos(double accel) {
2249  double vNext = myState.mySpeed + ACCEL2SPEED(accel);
2251  // apply implicit Euler positional update
2252  return SPEED2DIST(MAX2(vNext, 0.));
2253  } else {
2254  // apply ballistic update
2255  if (vNext >= 0) {
2256  // assume constant acceleration during this time step
2257  return SPEED2DIST(myState.mySpeed + 0.5 * ACCEL2SPEED(accel));
2258  } else {
2259  // negative vNext indicates a stop within the middle of time step
2260  // The corresponding stop time is s = mySpeed/deceleration \in [0,dt], and the
2261  // covered distance is therefore deltaPos = mySpeed*s - 0.5*deceleration*s^2.
2262  // Here, deceleration = (myState.mySpeed - vNext)/dt is the constant deceleration
2263  // until the vehicle stops.
2264  return -SPEED2DIST(0.5 * myState.mySpeed * myState.mySpeed / ACCEL2SPEED(accel));
2265  }
2266  }
2267 }
2268 
2269 void
2270 MSVehicle::processLinkAproaches(double& vSafe, double& vSafeMin, double& vSafeMinDist) {
2271 
2272  // Speed limit due to zipper merging
2273  double vSafeZipper = std::numeric_limits<double>::max();
2274 
2275  myHaveToWaitOnNextLink = false;
2276 
2277  // Get safe velocities from DriveProcessItems.
2278  assert(myLFLinkLanes.size() != 0 || isRemoteControlled());
2279  for (DriveItemVector::iterator i = myLFLinkLanes.begin(); i != myLFLinkLanes.end(); ++i) {
2280  MSLink* link = (*i).myLink;
2281 
2282 #ifdef DEBUG_EXEC_MOVE
2283  if (DEBUG_COND) {
2284  std::cout
2285  << SIMTIME
2286  << " veh=" << getID()
2287  << " link=" << (link == 0 ? "NULL" : link->getViaLaneOrLane()->getID())
2288  << " req=" << (*i).mySetRequest
2289  << " vP=" << (*i).myVLinkPass
2290  << " vW=" << (*i).myVLinkWait
2291  << " d=" << (*i).myDistance
2292  << "\n";
2293  gDebugFlag1 = true; // See MSLink_DEBUG_OPENED
2294  }
2295 #endif
2296 
2297  // the vehicle must change the lane on one of the next lanes (XXX: refs to code further below???, Leo)
2298  if (link != 0 && (*i).mySetRequest) {
2299 
2300  const LinkState ls = link->getState();
2301  // vehicles should brake when running onto a yellow light if the distance allows to halt in front
2302  const bool yellow = link->haveYellow();
2303  const bool canBrake = ((*i).myDistance > getCarFollowModel().brakeGap(myState.mySpeed, getCarFollowModel().getMaxDecel(), 0.)
2305  const bool ignoreRedLink = ignoreRed(link, canBrake);
2306  if (yellow && canBrake && !ignoreRedLink) {
2307  vSafe = (*i).myVLinkWait;
2308  myHaveToWaitOnNextLink = true;
2309  link->removeApproaching(this);
2310  break;
2311  }
2312  //
2313 #ifdef NO_TRACI
2314  const bool influencerPrio = false;
2315 #else
2316  const bool influencerPrio = (myInfluencer != 0 && !myInfluencer->getRespectJunctionPriority());
2317 #endif
2318  std::vector<const SUMOVehicle*> collectFoes;
2319  bool opened = (yellow || influencerPrio
2320  || link->opened((*i).myArrivalTime, (*i).myArrivalSpeed, (*i).getLeaveSpeed(),
2324  ls == LINKSTATE_ZIPPER ? &collectFoes : 0,
2325  ignoreRedLink, this));
2326  if (opened && getLaneChangeModel().getShadowLane() != 0) {
2327  MSLink* parallelLink = (*i).myLink->getParallelLink(getLaneChangeModel().getShadowDirection());
2328  if (parallelLink != 0) {
2329  const double shadowLatPos = getLateralPositionOnLane() - getLaneChangeModel().getShadowDirection() * 0.5 * (
2331  opened = yellow || influencerPrio || (opened & parallelLink->opened((*i).myArrivalTime, (*i).myArrivalSpeed, (*i).getLeaveSpeed(),
2334  getWaitingTime(), shadowLatPos, 0,
2335  ignoreRedLink, this));
2336 #ifdef DEBUG_EXEC_MOVE
2337  if (DEBUG_COND) {
2338  std::cout << SIMTIME
2339  << " veh=" << getID()
2340  << " shadowLane=" << getLaneChangeModel().getShadowLane()->getID()
2341  << " shadowDir=" << getLaneChangeModel().getShadowDirection()
2342  << " parallelLink=" << (parallelLink == 0 ? "NULL" : parallelLink->getViaLaneOrLane()->getID())
2343  << " opened=" << opened
2344  << "\n";
2345  }
2346 #endif
2347  }
2348  }
2349  // vehicles should decelerate when approaching a minor link
2350  if (opened && !influencerPrio && !link->havePriority() && !link->lastWasContMajor() && !link->isCont() && !ignoreRedLink) {
2351  double visibilityDistance = link->getFoeVisibilityDistance();
2352  double determinedFoePresence = i->myDistance <= visibilityDistance;
2353  if (!determinedFoePresence) {
2354  vSafe = (*i).myVLinkWait;
2355  myHaveToWaitOnNextLink = true;
2356  if (ls == LINKSTATE_EQUAL) {
2357  link->removeApproaching(this);
2358  }
2359  break;
2360  } else {
2361  // past the point of no return. we need to drive fast enough
2362  // to make it across the link. However, minor slowdowns
2363  // should be permissible to follow leading traffic safely
2364  // XXX: There is a problem in subsecond simulation: If we cannot
2365  // make it across the minor link in one step, new traffic
2366  // could appear on a major foe link and cause a collision. Refs. #1845, #2123
2367  vSafeMinDist = myLane->getLength() - getPositionOnLane(); // distance that must be covered
2369  vSafeMin = MIN2((double) DIST2SPEED(vSafeMinDist + POSITION_EPS), (*i).myVLinkPass);
2370  } else {
2371  vSafeMin = MIN2((double) DIST2SPEED(2 * vSafeMinDist + NUMERICAL_EPS) - getSpeed(), (*i).myVLinkPass);
2372  }
2373  }
2374  }
2375  // have waited; may pass if opened...
2376  if (opened) {
2377  vSafe = (*i).myVLinkPass;
2378  if (vSafe < getCarFollowModel().getMaxDecel() && vSafe <= (*i).myVLinkWait && vSafe < getCarFollowModel().maxNextSpeed(getSpeed(), this)) {
2379  // this vehicle is probably not gonna drive across the next junction (heuristic)
2380  myHaveToWaitOnNextLink = true;
2381  }
2382  } else if (link->getState() == LINKSTATE_ZIPPER) {
2383  vSafeZipper = MIN2(vSafeZipper,
2384  link->getZipperSpeed(this, (*i).myDistance, (*i).myVLinkPass, (*i).myArrivalTime, &collectFoes));
2385  } else {
2386  vSafe = (*i).myVLinkWait;
2387  myHaveToWaitOnNextLink = true;
2388  if (ls == LINKSTATE_EQUAL) {
2389  link->removeApproaching(this);
2390  }
2391 #ifdef DEBUG_EXEC_MOVE
2392  if (DEBUG_COND) {
2393  std::cout << SIMTIME << " braking for closed link=" << link->getViaLaneOrLane()->getID() << "\n";
2394  }
2395 #endif
2396  break;
2397  }
2398  } else {
2399  // we have: i->link == 0 || !i->setRequest
2400  vSafe = (*i).myVLinkWait;
2401  if (vSafe < getSpeed()) {
2402  myHaveToWaitOnNextLink = true;
2403  }
2404  break;
2405  }
2406  }
2407 
2408 //#ifdef DEBUG_EXEC_MOVE
2409 // if (DEBUG_COND) {
2410 // std::cout << "\nvCurrent = " << toString(getSpeed(), 24) << "" << std::endl;
2411 // std::cout << "vSafe = " << toString(vSafe, 24) << "" << std::endl;
2412 // std::cout << "vSafeMin = " << toString(vSafeMin, 24) << "" << std::endl;
2413 // std::cout << "vSafeMinDist = " << toString(vSafeMinDist, 24) << "" << std::endl;
2414 //
2415 // double gap = getLeader().second;
2416 // std::cout << "gap = " << toString(gap, 24) << std::endl;
2417 // std::cout << "vSafeStoppedLeader = " << toString(getCarFollowModel().stopSpeed(this, getSpeed(), gap), 24)
2418 // << "\n" << std::endl;
2419 // }
2420 //#endif
2421 
2422  if ((MSGlobals::gSemiImplicitEulerUpdate && vSafe + NUMERICAL_EPS < vSafeMin)
2423  || (!MSGlobals::gSemiImplicitEulerUpdate && (vSafe + NUMERICAL_EPS < vSafeMin && vSafeMin != 0))) { // this might be good for the euler case as well
2424  // cannot drive across a link so we need to stop before it
2425  // XXX: (Leo) This often called stopSpeed with vSafeMinDist==0 (for the ballistic update), since vSafe can become negative
2426  // For the Euler update the term '+ NUMERICAL_EPS' prevented a call here... Recheck, consider of -INVALID_SPEED instead of 0 to indicate absence of vSafeMin restrictions. Refs. #2577
2427  vSafe = MIN2(vSafe, getCarFollowModel().stopSpeed(this, getSpeed(), vSafeMinDist));
2428  vSafeMin = 0;
2429  myHaveToWaitOnNextLink = true;
2430 
2431 #ifdef DEBUG_EXEC_MOVE
2432  if (DEBUG_COND) {
2433  std::cout << "vSafeMin Problem?" << std::endl;
2434  }
2435 #endif
2436 
2437  }
2438 
2439  // vehicles inside a roundabout should maintain their requests
2440  if (myLane->getEdge().isRoundabout()) {
2441  myHaveToWaitOnNextLink = false;
2442  }
2443 
2444  vSafe = MIN2(vSafe, vSafeZipper);
2445 }
2446 
2447 
2448 void
2449 MSVehicle::processTraCISpeedControl(double vSafe, double& vNext) {
2450  if (myInfluencer != 0) {
2453  }
2454  const double vMax = getVehicleType().getCarFollowModel().maxNextSpeed(myState.mySpeed, this);
2455  const double vMin = MAX2(0., getVehicleType().getCarFollowModel().minNextSpeed(myState.mySpeed, this));
2456  vNext = myInfluencer->influenceSpeed(MSNet::getInstance()->getCurrentTimeStep(), vNext, vSafe, vMin, vMax);
2457  }
2458 }
2459 
2460 
2461 void
2463 #ifdef DEBUG_ACTIONSTEPS
2464  if DEBUG_COND {
2465  std::cout << SIMTIME << " veh=" << getID() << " removePassedDriveItems()\n"
2466  << " Current items: ";
2467  for (auto& j : myLFLinkLanes) {
2468  if (j.myLink == 0) {
2469  std::cout << "\n Stop at distance " << j.myDistance;
2470  } else {
2471  const MSLane* to = j.myLink->getViaLaneOrLane();
2472  const MSLane* from = j.myLink->getLaneBefore();
2473  std::cout << "\n Link at distance " << j.myDistance << ": '"
2474  << (from == 0 ? "NONE" : from->getID()) << "' -> '" << (to == 0 ? "NONE" : to->getID()) << "'";
2475  }
2476  }
2477  std::cout << "\n myNextDriveItem: ";
2478  if (myLFLinkLanes.size() != 0) {
2479  if (myNextDriveItem->myLink == 0) {
2480  std::cout << "\n Stop at distance " << myNextDriveItem->myDistance;
2481  } else {
2482  const MSLane* to = myNextDriveItem->myLink->getViaLaneOrLane();
2483  const MSLane* from = myNextDriveItem->myLink->getLaneBefore();
2484  std::cout << "\n Link at distance " << myNextDriveItem->myDistance << ": '"
2485  << (from == 0 ? "NONE" : from->getID()) << "' -> '" << (to == 0 ? "NONE" : to->getID()) << "'";
2486  }
2487  }
2488  std::cout << std::endl;
2489  }
2490 #endif
2491  for (auto j = myLFLinkLanes.begin(); j != myNextDriveItem; ++j) {
2492 #ifdef DEBUG_ACTIONSTEPS
2493  if DEBUG_COND {
2494  std::cout << " Removing item: ";
2495  if (j->myLink == 0) {
2496  std::cout << "Stop at distance " << j->myDistance;
2497  } else {
2498  const MSLane* to = j->myLink->getViaLaneOrLane();
2499  const MSLane* from = j->myLink->getLaneBefore();
2500  std::cout << "Link at distance " << j->myDistance << ": '"
2501  << (from == 0 ? "NONE" : from->getID()) << "' -> '" << (to == 0 ? "NONE" : to->getID()) << "'";
2502  }
2503  std::cout << std::endl;
2504  }
2505 #endif
2506  if (j->myLink != 0) {
2507  j->myLink->removeApproaching(this);
2508  }
2509  }
2511  myNextDriveItem = myLFLinkLanes.begin();
2512 }
2513 
2514 
2515 void
2517 #ifdef DEBUG_ACTIONSTEPS
2518  if (DEBUG_COND) {
2519  std::cout << SIMTIME << " updateDriveItems(), veh='" << getID() << "' (lane: '" << getLane()->getID() << "')\nCurrent drive items:" << std::endl;
2520  DriveItemVector::iterator i;
2521  for (i = myLFLinkLanes.begin(); i != myLFLinkLanes.end(); ++i) {
2522  std::cout
2523  << " vPass=" << (*i).myVLinkPass
2524  << " vWait=" << (*i).myVLinkWait
2525  << " linkLane=" << ((*i).myLink == 0 ? "NULL" : (*i).myLink->getViaLaneOrLane()->getID())
2526  << " request=" << (*i).mySetRequest
2527  << "\n";
2528  }
2529  std::cout << " myNextDriveItem's linkLane: " << (myNextDriveItem->myLink == 0 ? "NULL" : myNextDriveItem->myLink->getViaLaneOrLane()->getID()) << std::endl;
2530  }
2531 #endif
2532  if (myLFLinkLanes.size() == 0) {
2533  // nothing to update
2534  return;
2535  }
2536  const MSLink* nextPlannedLink = 0;
2537 // auto i = myLFLinkLanes.begin();
2538  auto i = myNextDriveItem;
2539  while (i != myLFLinkLanes.end() && nextPlannedLink == 0) {
2540  nextPlannedLink = i->myLink;
2541  ++i;
2542  }
2543 
2544  if (nextPlannedLink == 0) {
2545  // No link for upcoming item -> no need for an update
2546 #ifdef DEBUG_ACTIONSTEPS
2547  if (DEBUG_COND) {
2548  std::cout << "Found no link-related drive item." << std::endl;
2549  }
2550 #endif
2551  return;
2552  }
2553 
2554  if (getLane() == nextPlannedLink->getLaneBefore()) {
2555  // Current lane approaches the stored next link, i.e. no LC happend and no update is required.
2556 #ifdef DEBUG_ACTIONSTEPS
2557  if (DEBUG_COND) {
2558  std::cout << "Continuing on planned lane sequence, no update required." << std::endl;
2559  }
2560 #endif
2561  return;
2562  }
2563  // Lane must have been changed, determine the change direction
2564  MSLink* parallelLink = nextPlannedLink->getParallelLink(1);
2565  if (parallelLink != 0 && parallelLink->getLaneBefore() == getLane()) {
2566  // lcDir = 1;
2567  } else {
2568  parallelLink = nextPlannedLink->getParallelLink(-1);
2569  if (parallelLink != 0 && parallelLink->getLaneBefore() == getLane()) {
2570  // lcDir = -1;
2571  } else {
2572  // If the vehicle's current lane is not the approaching lane for the next
2573  // drive process item's link, it is expected to lead to a parallel link,
2574  // XXX: What if the lc was an overtaking maneuver and there is no upcoming link?
2575  // Then a stop item should be scheduled! -> TODO!
2576  //assert(false);
2577  return;
2578  }
2579  }
2580 #ifdef DEBUG_ACTIONSTEPS
2581  if (DEBUG_COND) {
2582  std::cout << "Changed lane. Drive items will be updated along the current lane continuation." << std::endl;
2583  }
2584 #endif
2585  // Trace link sequence along current best lanes and transfer drive items to the corresponding links
2586 // DriveItemVector::iterator driveItemIt = myLFLinkLanes.begin();
2587  DriveItemVector::iterator driveItemIt = myNextDriveItem;
2588  // In the loop below, lane holds the currently considered lane on the vehicles continuation (including internal lanes)
2589  MSLane* lane = myLane;
2590  // *lit is a pointer to the next lane in best continuations for the current lane (always non-internal)
2591  std::vector<MSLane*>::const_iterator bestLaneIt = getBestLanesContinuation().begin();
2592  // if the vehicle's current lane is internal, the first entry in the best continuations is null
2593  assert((*bestLaneIt) == 0 || !myLane->isInternal());
2594  // Pointer to the new link for the current drive process item
2595  MSLink* newLink = 0;
2596  while (driveItemIt != myLFLinkLanes.end()) {
2597  if (driveItemIt->myLink == 0) {
2598  // Items not related to a specific link are not updated
2599  // (XXX: when a stop item corresponded to a dead end, which is overcome by the LC that made
2600  // the update necessary, this may slow down the vehicle's continuation on the new lane...)
2601  ++driveItemIt;
2602  continue;
2603  }
2604  // Set nextBestLane to the next non-null consecutive lane entry
2605  while (bestLaneIt != getBestLanesContinuation().end() && (*bestLaneIt == 0 || (*bestLaneIt)->getID() == myLane->getID())) {
2606  ++bestLaneIt;
2607  }
2608  // Continuation links for current best lanes are less than for the former drive items (myLFLinkLanes)
2609  // We just remove the leftover link-items, as they cannot be mapped to new links.
2610  if (bestLaneIt == getBestLanesContinuation().end()) {
2611 #ifdef DEBUG_ACTIONSTEPS
2612  if (DEBUG_COND) {
2613  std::cout << "Reached end of the new continuation sequence. Erasing leftover link-items." << std::endl;
2614  }
2615 #endif
2616  while (driveItemIt != myLFLinkLanes.end()) {
2617  if (driveItemIt->myLink == 0) {
2618  ++driveItemIt;
2619  continue;
2620  } else {
2621  driveItemIt->myLink->removeApproaching(this);
2622  driveItemIt = myLFLinkLanes.erase(driveItemIt);
2623  }
2624  }
2625  break;
2626  }
2627  // Do the actual link-remapping for the item. And un/register approaching information on the corresponding links
2628  newLink = lane->getLinkTo(*bestLaneIt);
2629 
2630  if (newLink == driveItemIt->myLink) {
2631  // new continuation merged into previous - stop update
2632 #ifdef DEBUG_ACTIONSTEPS
2633  if (DEBUG_COND) {
2634  std::cout << "Old and new continuation sequences merge at link\n"
2635  << "'" << newLink->getLaneBefore()->getID() << "'->'" << newLink->getViaLaneOrLane()->getID() << "'"
2636  << "\nNo update beyond merge required." << std::endl;
2637  }
2638 #endif
2639  break;
2640  }
2641 
2642 #ifdef DEBUG_ACTIONSTEPS
2643  if (DEBUG_COND) {
2644  std::cout << "Updating link\n'" << driveItemIt->myLink->getLaneBefore()->getID() << "'->'" << driveItemIt->myLink->getViaLaneOrLane()->getID() << "'"
2645  << std::endl;
2646  std::cout << "\n'" << newLink->getLaneBefore()->getID() << "'->'" << newLink->getViaLaneOrLane()->getID() << "'" << std::endl;
2647  }
2648 #endif
2649  newLink->setApproaching(this, driveItemIt->myLink->getApproaching(this));
2650  driveItemIt->myLink->removeApproaching(this);
2651  driveItemIt->myLink = newLink;
2652  lane = newLink->getViaLaneOrLane();
2653  ++driveItemIt;
2654  if (!lane->isInternal()) {
2655  ++bestLaneIt;
2656  }
2657  }
2658 #ifdef DEBUG_ACTIONSTEPS
2659  if (DEBUG_COND) {
2660  std::cout << "Updated drive items:" << std::endl;
2661  DriveItemVector::iterator i;
2662  for (i = myLFLinkLanes.begin(); i != myLFLinkLanes.end(); ++i) {
2663  std::cout
2664  << " vPass=" << (*i).myVLinkPass
2665  << " vWait=" << (*i).myVLinkWait
2666  << " linkLane=" << ((*i).myLink == 0 ? "NULL" : (*i).myLink->getViaLaneOrLane()->getID())
2667  << " request=" << (*i).mySetRequest
2668  << "\n";
2669  }
2670  }
2671 #endif
2672 }
2673 
2674 
2675 void
2677  // To avoid casual blinking brake lights at high speeds due to dawdling of the
2678  // leading vehicle, we don't show brake lights when the deceleration could be caused
2679  // by frictional forces and air resistance (i.e. proportional to v^2, coefficient could be adapted further)
2680  double pseudoFriction = (0.05 + 0.005 * getSpeed()) * getSpeed();
2681  bool brakelightsOn = vNext < getSpeed() - ACCEL2SPEED(pseudoFriction);
2682 
2683  if (vNext <= SUMO_const_haltingSpeed && !isStopped()) {
2684  brakelightsOn = true;
2685  }
2686  if (brakelightsOn) {
2688  } else {
2690  }
2691 }
2692 
2693 
2694 void
2696  if (vNext <= SUMO_const_haltingSpeed && !isStopped()) {
2699  } else {
2700  myWaitingTime = 0;
2702  }
2703 }
2704 
2705 
2706 void
2708  // update time loss (depends on the updated edge)
2709  if (!isStopped()) {
2710  const double vmax = myLane->getVehicleMaxSpeed(this);
2711  if (vmax > 0) {
2712  myTimeLoss += TS * (vmax - vNext) / vmax;
2713  }
2714  }
2715 }
2716 
2717 
2718 void
2719 MSVehicle::processLaneAdvances(std::vector<MSLane*>& passedLanes, bool& moved, std::string& emergencyReason) {
2720  for (std::vector<MSLane*>::reverse_iterator i = myFurtherLanes.rbegin(); i != myFurtherLanes.rend(); ++i) {
2721  passedLanes.push_back(*i);
2722  }
2723  if (passedLanes.size() == 0 || passedLanes.back() != myLane) {
2724  passedLanes.push_back(myLane);
2725  }
2726  // move on lane(s)
2727  if (myState.myPos > myLane->getLength()) {
2728  // The vehicle has moved at least to the next lane (maybe it passed even more than one)
2729  if (myCurrEdge != myRoute->end() - 1) {
2730  MSLane* approachedLane = myLane;
2731  // move the vehicle forward
2732  for (myNextDriveItem = myLFLinkLanes.begin(); myNextDriveItem != myLFLinkLanes.end() && approachedLane != 0 && myState.myPos > approachedLane->getLength(); ++myNextDriveItem) {
2733  MSLink* link = myNextDriveItem->myLink;
2734  // check whether the vehicle was allowed to enter lane
2735  // otherwise it is decelerated and we do not need to test for it's
2736  // approach on the following lanes when a lane changing is performed
2737  // proceed to the next lane
2738  if (link != 0) {
2739  approachedLane = link->getViaLaneOrLane();
2740 #ifndef NO_TRACI
2742 #endif
2743  if (link->haveRed() && !ignoreRed(link, false)) {
2744  emergencyReason = " because of a red traffic light";
2745  ++myNextDriveItem;
2746  break;
2747  }
2748 #ifndef NO_TRACI
2749  }
2750 #endif
2751  } else if (myState.myPos < myLane->getLength() + NUMERICAL_EPS) {
2752  // avoid warning due to numerical instability
2753  approachedLane = myLane;
2755  } else {
2756  emergencyReason = " because there is no connection to the next edge";
2757  approachedLane = 0;
2758  ++myNextDriveItem;
2759  break;
2760  }
2761  if (approachedLane != myLane && approachedLane != 0) {
2763  myState.myPos -= myLane->getLength();
2764  assert(myState.myPos > 0);
2765  enterLaneAtMove(approachedLane);
2767  // erase leaders when past the junction
2768  if (link->getViaLane() == 0) {
2769  link->passedJunction(this);
2770  }
2771  }
2772  if (hasArrived()) {
2773  ++myNextDriveItem;
2774  break;
2775  }
2776  if (getLaneChangeModel().isChangingLanes()) {
2777  if (link->getDirection() == LINKDIR_LEFT || link->getDirection() == LINKDIR_RIGHT) {
2778  // abort lane change
2779  WRITE_WARNING("Vehicle '" + getID() + "' could not finish continuous lane change (turn lane) time=" +
2780  time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
2782  }
2783  }
2784  moved = true;
2785  if (approachedLane->getEdge().isVaporizing()) {
2787  ++myNextDriveItem;
2788  break;
2789  }
2790  passedLanes.push_back(approachedLane);
2791  }
2792  }
2793  // NOTE: Passed drive items will be erased in the next simstep's planMove()
2794 
2795 #ifdef DEBUG_ACTIONSTEPS
2796  if (DEBUG_COND && myNextDriveItem != myLFLinkLanes.begin()) {
2797  std::cout << "Updated drive items:" << std::endl;
2798  for (DriveItemVector::iterator i = myLFLinkLanes.begin(); i != myLFLinkLanes.end(); ++i) {
2799  std::cout
2800  << " vPass=" << (*i).myVLinkPass
2801  << " vWait=" << (*i).myVLinkWait
2802  << " linkLane=" << ((*i).myLink == 0 ? "NULL" : (*i).myLink->getViaLaneOrLane()->getID())
2803  << " request=" << (*i).mySetRequest
2804  << "\n";
2805  }
2806  }
2807 #endif
2808  } else if (!hasArrived() && myState.myPos < myLane->getLength() + NUMERICAL_EPS) {
2809  // avoid warning due to numerical instability when stopping at the end of the route
2811  }
2812 
2813  }
2814 }
2815 
2816 
2817 
2818 bool
2820 #ifdef DEBUG_EXEC_MOVE
2821  if (DEBUG_COND) std::cout << "\nEXECUTE_MOVE\n"
2822  << SIMTIME
2823  << " veh=" << getID()
2824  << " speed=" << getSpeed() // toString(getSpeed(), 24)
2825  << std::endl;
2826 #endif
2827 
2828 
2829  // Maximum safe velocity
2830  double vSafe = std::numeric_limits<double>::max();
2831  // Minimum safe velocity (lower bound).
2832  double vSafeMin = -std::numeric_limits<double>::max();
2833  // The distance to a link, which should either be crossed this step
2834  // or in front of which we need to stop.
2835  double vSafeMinDist = 0;
2836 
2837  if (myActionStep) {
2838  // Actuate control (i.e. choose bounds for safe speed in current simstep (euler), resp. after current sim step (ballistic))
2839  processLinkAproaches(vSafe, vSafeMin, vSafeMinDist);
2840 #ifdef DEBUG_ACTIONSTEPS
2841  if DEBUG_COND {
2842  std::cout << SIMTIME << " vehicle '" << getID() << "'\n"
2843  " vsafe from processLinkApproaches(): vsafe " << vSafe << std::endl;
2844  }
2845 #endif
2846  } else {
2847  // Continue with current acceleration
2848  vSafe = getSpeed() + ACCEL2SPEED(myAcceleration);
2849 #ifdef DEBUG_ACTIONSTEPS
2850  if DEBUG_COND {
2851  std::cout << SIMTIME << " vehicle '" << getID() << "' skips processLinkApproaches()\n"
2852  " continues with constant accel " << myAcceleration << "...\n"
2853  << "speed: " << getSpeed() << " -> " << vSafe << std::endl;
2854  }
2855 #endif
2856  }
2857 
2858 
2859 //#ifdef DEBUG_EXEC_MOVE
2860 // if (DEBUG_COND) {
2861 // std::cout << "vSafe = " << toString(vSafe,12) << "\n" << std::endl;
2862 // }
2863 //#endif
2864 
2865  // Determine vNext = speed after current sim step (ballistic), resp. in current simstep (euler)
2866  // Call to moveHelper applies speed reduction due to dawdling / lane changing but ensures minimum safe speed
2867  double vNext = myActionStep ? MAX2(getCarFollowModel().moveHelper(this, vSafe), vSafeMin) : vSafe;
2868  // (Leo) to avoid tiny oscillations (< 1e-10) of vNext in a standing vehicle column (observed for ballistic update), we cap off vNext
2869  // (We assure to do this only for vNext<<NUMERICAL_EPS since otherwise this would nullify the workaround for #2995
2870  if (fabs(vNext) < 0.1 * NUMERICAL_EPS * TS) {
2871  vNext = 0.;
2872  }
2873 #ifdef DEBUG_EXEC_MOVE
2874  if (DEBUG_COND) {
2875  std::cout << SIMTIME << " moveHelper vSafe=" << vSafe << " vSafeMin=" << (vSafeMin == -std::numeric_limits<double>::max() ? "-Inf" : toString(vSafeMin))
2876  << " vNext=" << vNext << " (i.e. accel=" << SPEED2ACCEL(vNext - getSpeed()) << "\n";
2877  }
2878 #endif
2879 
2880  // vNext may be higher than vSafe without implying a bug:
2881  // - when approaching a green light that suddenly switches to yellow
2882  // - when using unregulated junctions
2883  // - when using tau < step-size
2884  // - when using unsafe car following models
2885  // - when using TraCI and some speedMode / laneChangeMode settings
2886  //if (vNext > vSafe + NUMERICAL_EPS) {
2887  // WRITE_WARNING("vehicle '" + getID() + "' cannot brake hard enough to reach safe speed "
2888  // + toString(vSafe, 4) + ", moving at " + toString(vNext, 4) + " instead. time="
2889  // + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
2890  //}
2891 
2893  vNext = MAX2(vNext, 0.);
2894  } else {
2895  // (Leo) Ballistic: negative vNext can be used to indicate a stop within next step.
2896  }
2897 
2898 #ifndef NO_TRACI
2899  // Check for speed advices from the traci client
2900  processTraCISpeedControl(vSafe, vNext);
2901 #endif
2902 
2903  setBrakingSignals(vNext);
2904  updateWaitingTime(vNext);
2905 
2906  // update position and speed
2907  updateState(vNext);
2908 
2909  // Lanes, which the vehicle touched at some moment of the executed simstep
2910  std::vector<MSLane*> passedLanes;
2911  // Whether the vehicle did move to another lane
2912  bool moved = false;
2913  // Reason for a possible emergency stop
2914  std::string emergencyReason = " for unknown reasons";
2915  processLaneAdvances(passedLanes, moved, emergencyReason);
2916 
2917  updateTimeLoss(vNext);
2919 
2920  if (!hasArrived() && !myLane->getEdge().isVaporizing()) {
2921  if (myState.myPos > myLane->getLength()) {
2922  WRITE_WARNING("Vehicle '" + getID() + "' performs emergency stop at the end of lane '" + myLane->getID()
2923  + "'" + emergencyReason
2924  + " (decel=" + toString(myAcceleration - myState.mySpeed)
2925  + ", offset=" + toString(myState.myPos - myLane->getLength())
2926  + "), time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
2929  myState.mySpeed = 0;
2930  myAcceleration = 0;
2931  // reset drive items and link approaches
2933  myLFLinkLanes.clear();
2934  myNextDriveItem = myLFLinkLanes.begin();
2935  }
2936  const MSLane* oldBackLane = getBackLane();
2937  if (getLaneChangeModel().isOpposite()) {
2938  passedLanes.clear(); // ignore back occupation
2939  }
2940 #ifdef DEBUG_ACTIONSTEPS
2941  if DEBUG_COND {
2942  std::cout << SIMTIME << " veh '" << getID() << "' updates further lanes." << std::endl;
2943  }
2944 #endif
2946  // bestLanes need to be updated before lane changing starts. NOTE: This call is also a presumption for updateDriveItems()
2947  updateBestLanes();
2948  if (moved || oldBackLane != getBackLane()) {
2949  if (getLaneChangeModel().getShadowLane() != 0 || getLateralOverlap() > POSITION_EPS) {
2950  // shadow lane must be updated if the front or back lane changed
2951  // either if we already have a shadowLane or if there is lateral overlap
2953  }
2954  // The vehicles target lane must be also be updated if the front or back lane changed
2956  }
2957  setBlinkerInformation(); // needs updated bestLanes
2958  //change the blue light only for emergency vehicles SUMOVehicleClass
2959  if (myType->getVehicleClass() == SVC_EMERGENCY) {
2960  setEmergencyBlueLight(MSNet::getInstance()->getCurrentTimeStep());
2961  }
2962  // State needs to be reset for all vehicles before the next call to MSEdgeControl::changeLanes
2963  if (myActionStep) {
2964  // check (#2681): Can this be skipped?
2966  } else {
2967 #ifdef DEBUG_ACTIONSTEPS
2968  if DEBUG_COND {
2969  std::cout << SIMTIME << " veh '" << getID() << "' skips LCM->prepareStep()." << std::endl;
2970  }
2971 #endif
2972  }
2973  myAngle = computeAngle();
2974  }
2975 
2976 #ifdef DEBUG_EXEC_MOVE
2977  if (DEBUG_COND) {
2978  std::cout << SIMTIME << " executeMove finished veh=" << getID() << " lane=" << myLane->getID() << " myPos=" << getPositionOnLane() << " myPosLat=" << getLateralPositionOnLane() << "\n";
2979  gDebugFlag1 = false; // See MSLink_DEBUG_OPENED
2980  }
2981 #endif
2982  if (getLaneChangeModel().isOpposite()) {
2983  // transform back to the opposite-direction lane
2984  if (myLane->getOpposite() == 0) {
2985  WRITE_WARNING("Unexpected end of opposite lane for vehicle '" + getID() + " at lane '" + myLane->getID() + "', time=" +
2986  time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
2988  } else {
2990  myLane = myLane->getOpposite();
2992  }
2993  }
2995  return moved;
2996 }
2997 
2998 
2999 void
3000 MSVehicle::updateState(double vNext) {
3001  // update position and speed
3002  double deltaPos; // positional change
3004  // euler
3005  deltaPos = SPEED2DIST(vNext);
3006  } else {
3007  // ballistic
3008  deltaPos = getDeltaPos(SPEED2ACCEL(vNext - myState.mySpeed));
3009  }
3010 
3011  // the *mean* acceleration during the next step (probably most appropriate for emission calculation)
3012  // NOTE: for the ballistic update vNext may be negative, indicating a stop.
3013  myAcceleration = SPEED2ACCEL(MAX2(vNext, 0.) - myState.mySpeed);
3014 
3015 #ifdef DEBUG_EXEC_MOVE
3016  if (DEBUG_COND) {
3017  std::cout << SIMTIME << " updateState() for veh '" << getID() << "': deltaPos=" << deltaPos
3018  << " pos=" << myState.myPos << " newPos=" << myState.myPos + deltaPos << std::endl;
3019  }
3020 #endif
3021 
3023  myState.mySpeed = MAX2(vNext, 0.);
3024 
3025 #ifndef NO_TRACI
3026  if (myInfluencer != 0 && myInfluencer->isRemoteControlled()) {
3027  deltaPos = myInfluencer->implicitDeltaPosRemote(this);
3028  }
3029 #endif
3030 
3031  if (getLaneChangeModel().isOpposite()) {
3032  // transform to the forward-direction lane, move and then transform back
3034  myLane = myLane->getOpposite();
3035  }
3036  myState.myPos += deltaPos;
3037  myState.myLastCoveredDist = deltaPos;
3038 
3040 }
3041 
3042 
3043 const MSLane*
3045  if (myFurtherLanes.size() > 0) {
3046  return myFurtherLanes.back();
3047  } else {
3048  return myLane;
3049  }
3050 }
3051 
3052 
3053 double
3054 MSVehicle::updateFurtherLanes(std::vector<MSLane*>& furtherLanes, std::vector<double>& furtherLanesPosLat,
3055  const std::vector<MSLane*>& passedLanes) {
3056 #ifdef DEBUG_FURTHER
3057  if (DEBUG_COND) std::cout << SIMTIME
3058  << " updateFurtherLanes oldFurther=" << toString(furtherLanes)
3059  << " oldFurtherPosLat=" << toString(furtherLanesPosLat)
3060  << " passed=" << toString(passedLanes)
3061  << "\n";
3062 #endif
3063  for (std::vector<MSLane*>::iterator i = furtherLanes.begin(); i != furtherLanes.end(); ++i) {
3064  (*i)->resetPartialOccupation(this);
3065  }
3066 
3067  std::vector<MSLane*> newFurther;
3068  std::vector<double> newFurtherPosLat;
3069  double backPosOnPreviousLane = myState.myPos - getLength();
3070  if (passedLanes.size() > 1) {
3071  // There are candidates for further lanes. (passedLanes[-1] is the current lane, or current shadow lane in context of updateShadowLanes())
3072  std::vector<MSLane*>::const_iterator fi = furtherLanes.begin();
3073  std::vector<double>::const_iterator fpi = furtherLanesPosLat.begin();
3074  for (auto pi = passedLanes.rbegin() + 1; pi != passedLanes.rend() && backPosOnPreviousLane < 0; ++pi) {
3075  // As long as vehicle back reaches into passed lane, add it to the further lanes
3076  newFurther.push_back(*pi);
3077  backPosOnPreviousLane += (*pi)->setPartialOccupation(this);
3078  if (fi != furtherLanes.end() && *pi == *fi) {
3079  // Lateral position on this lane is already known. Assume constant and use old value.
3080  newFurtherPosLat.push_back(*fpi);
3081  ++fi;
3082  ++fpi;
3083  } else {
3084  // The lane *pi was not in furtherLanes before.
3085  // If it is downstream, we assume as lateral position the current position
3086  // If it is a new lane upstream (can appear as shadow further in case of LC-maneuvering, e.g.)
3087  // we assign the last known lateral position.
3088  if (newFurtherPosLat.size() == 0) {
3089  newFurtherPosLat.push_back(myState.myPosLat);
3090  } else {
3091  newFurtherPosLat.push_back(newFurtherPosLat.back());
3092  }
3093  }
3094 #ifdef DEBUG_FURTHER
3095  if (DEBUG_COND) {
3096  std::cout << SIMTIME << " updateFurtherLanes \n"
3097  << " further lane '" << (*pi)->getID() << "' backPosOnPreviousLane=" << backPosOnPreviousLane
3098  << std::endl;
3099  }
3100 #endif
3101  }
3102  furtherLanes = newFurther;
3103  furtherLanesPosLat = newFurtherPosLat;
3104  } else {
3105  furtherLanes.clear();
3106  furtherLanesPosLat.clear();
3107  }
3108 #ifdef DEBUG_FURTHER
3109  if (DEBUG_COND) std::cout
3110  << " newFurther=" << toString(furtherLanes)
3111  << " newFurtherPosLat=" << toString(furtherLanesPosLat)
3112  << " newBackPos=" << backPosOnPreviousLane
3113  << "\n";
3114 #endif
3115  return backPosOnPreviousLane;
3116 }
3117 
3118 
3119 double
3121 #ifdef DEBUG_FURTHER
3122  if (DEBUG_COND) {
3123  std::cout << SIMTIME
3124  << " getBackPositionOnLane veh=" << getID()
3125  << " lane=" << Named::getIDSecure(lane)
3126  << " myLane=" << myLane->getID()
3127  << " further=" << toString(myFurtherLanes)
3128  << " furtherPosLat=" << toString(myFurtherLanesPosLat)
3129  << "\n shadowLane=" << Named::getIDSecure(getLaneChangeModel().getShadowLane())
3130  << " shadowFurther=" << toString(getLaneChangeModel().getShadowFurtherLanes())
3131  << " shadowFurtherPosLat=" << toString(getLaneChangeModel().getShadowFurtherLanesPosLat())
3132  << "\n targetLane=" << Named::getIDSecure(getLaneChangeModel().getTargetLane())
3133  << " furtherTargets=" << toString(getLaneChangeModel().getFurtherTargetLanes())
3134  << std::endl;
3135  }
3136 #endif
3137  if (lane == myLane
3138  || lane == getLaneChangeModel().getShadowLane()
3139  || lane == getLaneChangeModel().getTargetLane()) {
3140  if (getLaneChangeModel().isOpposite()) {
3141  return myState.myPos + myType->getLength();
3142  } else {
3143  return myState.myPos - myType->getLength();
3144  }
3145  } else if ((myFurtherLanes.size() > 0 && lane == myFurtherLanes.back())
3146  || (getLaneChangeModel().getShadowFurtherLanes().size() > 0 && lane == getLaneChangeModel().getShadowFurtherLanes().back())
3147  || (getLaneChangeModel().getFurtherTargetLanes().size() > 0 && lane == getLaneChangeModel().getFurtherTargetLanes().back())) {
3148  return myState.myBackPos;
3149  } else {
3150  //if (DEBUG_COND) std::cout << SIMTIME << " veh=" << getID() << " myFurtherLanes=" << toString(myFurtherLanes) << "\n";
3151  double leftLength = myType->getLength() - myState.myPos;
3152 
3153  std::vector<MSLane*>::const_iterator i = myFurtherLanes.begin();
3154  while (leftLength > 0 && i != myFurtherLanes.end()) {
3155  leftLength -= (*i)->getLength();
3156  //if (DEBUG_COND) std::cout << " comparing i=" << (*i)->getID() << " lane=" << lane->getID() << "\n";
3157  if (*i == lane) {
3158  return -leftLength;
3159  }
3160  ++i;
3161  }
3162  //if (DEBUG_COND) std::cout << SIMTIME << " veh=" << getID() << " myShadowFurtherLanes=" << toString(getLaneChangeModel().getShadowFurtherLanes()) << "\n";
3163  leftLength = myType->getLength() - myState.myPos;
3164  i = getLaneChangeModel().getShadowFurtherLanes().begin();
3165  while (leftLength > 0 && i != getLaneChangeModel().getShadowFurtherLanes().end()) {
3166  leftLength -= (*i)->getLength();
3167  //if (DEBUG_COND) std::cout << " comparing i=" << (*i)->getID() << " lane=" << lane->getID() << "\n";
3168  if (*i == lane) {
3169  return -leftLength;
3170  }
3171  ++i;
3172  }
3173  //if (DEBUG_COND) std::cout << SIMTIME << " veh=" << getID() << " myFurtherTargetLanes=" << toString(getLaneChangeModel().getFurtherTargetLanes()) << "\n";
3174  leftLength = myType->getLength() - myState.myPos;
3175  i = getFurtherLanes().begin();
3176  const std::vector<MSLane*> furtherTargetLanes = getLaneChangeModel().getFurtherTargetLanes();
3177  auto j = furtherTargetLanes.begin();
3178  while (leftLength > 0 && j != furtherTargetLanes.end()) {
3179  leftLength -= (*i)->getLength();
3180  // if (DEBUG_COND) std::cout << " comparing i=" << (*i)->getID() << " lane=" << lane->getID() << "\n";
3181  if (*j == lane) {
3182  return -leftLength;
3183  }
3184  ++i;
3185  ++j;
3186  }
3187  WRITE_WARNING("Request backPos of vehicle '" + getID() + "' for invalid lane '" + Named::getIDSecure(lane)
3188  + "' time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".")
3189  assert(false);
3190  return myState.myBackPos;
3191  }
3192 }
3193 
3194 
3195 double
3197  return getBackPositionOnLane(lane) + myType->getLength();
3198 }
3199 
3200 
3201 bool
3202 MSVehicle::isFrontOnLane(const MSLane* lane) const {
3203  return lane == myLane || lane == getLaneChangeModel().getShadowLane();
3204 }
3205 
3206 
3207 double
3208 MSVehicle::getSpaceTillLastStanding(const MSLane* l, bool& foundStopped) const {
3209  double lengths = 0;
3210  const MSLane::VehCont& vehs = l->getVehiclesSecure();
3211  for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
3212  if ((*i)->getSpeed() < SUMO_const_haltingSpeed && !(*i)->getLane()->getEdge().isRoundabout()
3213  && (*i) != this
3214  // @todo recheck
3215  && (*i)->isFrontOnLane(l)) {
3216  foundStopped = true;
3217  const double ret = (*i)->getPositionOnLane() - (*i)->getVehicleType().getLengthWithGap() - lengths;
3218  l->releaseVehicles();
3219  return ret;
3220  }
3221  lengths += (*i)->getVehicleType().getLengthWithGap();
3222  }
3223  l->releaseVehicles();
3224  return l->getLength() - lengths;
3225 }
3226 
3227 
3228 void
3229 MSVehicle::checkRewindLinkLanes(const double lengthsInFront, DriveItemVector& lfLinks) const {
3231  bool hadVehicle = false;
3232  double seenSpace = -lengthsInFront;
3233 
3234  bool foundStopped = false;
3235  // compute available space until a stopped vehicle is found
3236  // this is the sum of non-interal lane length minus in-between vehicle lenghts
3237  for (int i = 0; i < (int)lfLinks.size(); ++i) {
3238  // skip unset links
3239  DriveProcessItem& item = lfLinks[i];
3240  if (item.myLink == 0 || foundStopped) {
3241  if (!foundStopped) {
3242  item.availableSpace += seenSpace;
3243  } else {
3244  item.availableSpace = seenSpace;
3245  }
3246  item.hadVehicle = hadVehicle;
3247  continue;
3248  }
3249  // get the next lane, determine whether it is an internal lane
3250  const MSLane* approachedLane = item.myLink->getViaLane();
3251  if (approachedLane != 0) {
3252  if (keepClear(item.myLink)) {
3253  seenSpace = seenSpace - approachedLane->getBruttoVehLenSum();
3254  hadVehicle |= approachedLane->getVehicleNumber() != 0;
3255  if (approachedLane == myLane) {
3256  seenSpace += getVehicleType().getLengthWithGap();
3257  }
3258  } else {
3259  seenSpace = seenSpace + getSpaceTillLastStanding(approachedLane, foundStopped);// - approachedLane->getBruttoVehLenSum() + approachedLane->getLength();
3260  hadVehicle |= approachedLane->getVehicleNumber() != 0;
3261  }
3262  item.availableSpace = seenSpace;
3263  item.hadVehicle = hadVehicle;
3264 #ifdef DEBUG_CHECKREWINDLINKLANES
3265  if (DEBUG_COND) std::cout
3266  << SIMTIME
3267  << " veh=" << getID()
3268  << " approached=" << approachedLane->getID()
3269  << " approachedBrutto=" << approachedLane->getBruttoVehLenSum()
3270  << " avail=" << item.availableSpace
3271  << " seenSpace=" << seenSpace
3272  << " hadVehicle=" << item.hadVehicle
3273  << " lengthsInFront=" << lengthsInFront
3274  << "\n";
3275 #endif
3276  continue;
3277  }
3278  approachedLane = item.myLink->getLane();
3279  const MSVehicle* last = approachedLane->getLastAnyVehicle();
3280  if (last == 0 || last == this) {
3281  seenSpace += approachedLane->getLength();
3282  item.availableSpace = seenSpace;
3283  } else if (!last->isFrontOnLane(approachedLane)) {
3286  item.availableSpace = MAX2(seenSpace, seenSpace + last->getBackPositionOnLane(approachedLane) + last->getCarFollowModel().brakeGap(last->getSpeed()));
3287  hadVehicle = true;
3289  seenSpace = seenSpace + getSpaceTillLastStanding(approachedLane, foundStopped);// - approachedLane->getBruttoVehLenSum() + approachedLane->getLength();
3291  if (last->myHaveToWaitOnNextLink) {
3292  foundStopped = true;
3293  }
3294 #ifdef DEBUG_CHECKREWINDLINKLANES
3295  if (DEBUG_COND) std::cout
3296  << SIMTIME
3297  << " veh=" << getID()
3298  << " approached=" << approachedLane->getID()
3299  << " lastPoc=" << last->getID()
3300  << " avail=" << item.availableSpace
3301  << " seenSpace=" << seenSpace
3302  << " foundStopped=" << foundStopped
3303  << "\n";
3304 #endif
3305  } else {
3306 
3307  if (last->signalSet(VEH_SIGNAL_BRAKELIGHT)) {
3308  const double lastBrakeGap = last->getCarFollowModel().brakeGap(last->getSpeed());
3309  const double lastGap = last->getBackPositionOnLane(approachedLane) + lastBrakeGap - last->getSpeed() * last->getCarFollowModel().getHeadwayTime()
3310  // gap of last up to the next intersection
3311  - last->getVehicleType().getMinGap();
3312  item.availableSpace = MAX2(seenSpace, seenSpace + lastGap);
3313  seenSpace += getSpaceTillLastStanding(approachedLane, foundStopped);// - approachedLane->getBruttoVehLenSum() + approachedLane->getLength();
3314  } else {
3315  seenSpace += getSpaceTillLastStanding(approachedLane, foundStopped);
3316  item.availableSpace = seenSpace;
3317  }
3318  if (last->myHaveToWaitOnNextLink) {
3319  foundStopped = true;
3320  }
3321  hadVehicle = true;
3322 #ifdef DEBUG_CHECKREWINDLINKLANES
3323  if (DEBUG_COND) std::cout
3324  << SIMTIME
3325  << " veh=" << getID()
3326  << " approached=" << approachedLane->getID()
3327  << " last=" << last->getID()
3328  << " lastHasToWait=" << last->myHaveToWaitOnNextLink
3329  << " lastBrakeLight=" << last->signalSet(VEH_SIGNAL_BRAKELIGHT)
3330  << " lastBrakeGap=" << last->getCarFollowModel().brakeGap(last->getSpeed())
3331  << " lastGap=" << (last->getBackPositionOnLane(approachedLane) + last->getCarFollowModel().brakeGap(last->getSpeed()) - last->getSpeed() * last->getCarFollowModel().getHeadwayTime()
3332  // gap of last up to the next intersection
3333  - last->getVehicleType().getMinGap())
3334  << " avail=" << item.availableSpace
3335  << " seenSpace=" << seenSpace
3336  << " foundStopped=" << foundStopped
3337  << "\n";
3338 #endif
3339  }
3340  item.hadVehicle = hadVehicle;
3341  }
3342 
3343  // check which links allow continuation and add pass available to the previous item
3344  for (int i = ((int)lfLinks.size() - 1); i > 0; --i) {
3345  DriveProcessItem& item = lfLinks[i - 1];
3346  const bool canLeaveJunction = item.myLink->getViaLane() == 0 || lfLinks[i].mySetRequest;
3347  const bool opened = item.myLink != 0 && canLeaveJunction && (item.myLink->havePriority() ||
3348 #ifndef NO_TRACI
3350 #endif
3351  item.myLink->opened(item.myArrivalTime, item.myArrivalSpeed,
3354  bool allowsContinuation = item.myLink == 0 || item.myLink->isCont() || !lfLinks[i].hadVehicle || opened;
3355  if (!opened && item.myLink != 0) {
3356  if (i > 1) {
3357  DriveProcessItem& item2 = lfLinks[i - 2];
3358  if (item2.myLink != 0 && item2.myLink->isCont()) {
3359  allowsContinuation = true;
3360  }
3361  }
3362  }
3363  if (allowsContinuation) {
3364  item.availableSpace = lfLinks[i].availableSpace;
3365  }
3366  }
3367 
3368  // find removalBegin
3369  int removalBegin = -1;
3370  for (int i = 0; hadVehicle && i < (int)lfLinks.size() && removalBegin < 0; ++i) {
3371  // skip unset links
3372  const DriveProcessItem& item = lfLinks[i];
3373  if (item.myLink == 0) {
3374  continue;
3375  }
3376  /*
3377  double impatienceCorrection = MAX2(0., double(double(myWaitingTime)));
3378  if (seenSpace<getVehicleType().getLengthWithGap()-impatienceCorrection/10.&&nextSeenNonInternal!=0) {
3379  removalBegin = lastLinkToInternal;
3380  }
3381  */
3382 
3383  const double leftSpace = item.availableSpace - getVehicleType().getLengthWithGap();
3384 #ifdef DEBUG_CHECKREWINDLINKLANES
3385  if (DEBUG_COND) std::cout
3386  << SIMTIME
3387  << " veh=" << getID()
3388  << " link=" << (item.myLink == 0 ? "NULL" : item.myLink->getViaLaneOrLane()->getID())
3389  << " avail=" << item.availableSpace
3390  << " leftSpace=" << leftSpace
3391  << "\n";
3392 #endif
3393  if (leftSpace < 0/* && item.myLink->willHaveBlockedFoe()*/) {
3394  double impatienceCorrection = 0;
3395  /*
3396  if(item.myLink->getState()==LINKSTATE_MINOR) {
3397  impatienceCorrection = MAX2(0., STEPS2TIME(myWaitingTime));
3398  }
3399  */
3400  // may ignore keepClear rules
3401  if (leftSpace < -impatienceCorrection / 10. && keepClear(item.myLink)) {
3402  removalBegin = i;
3403  }
3404  //removalBegin = i;
3405  }
3406  }
3407  // abort requests
3408  if (removalBegin != -1 && !(removalBegin == 0 && myLane->getEdge().isInternal())) {
3409  while (removalBegin < (int)(lfLinks.size())) {
3410  const double brakeGap = getCarFollowModel().brakeGap(myState.mySpeed, getCarFollowModel().getMaxDecel(), 0.);
3411  lfLinks[removalBegin].myVLinkPass = lfLinks[removalBegin].myVLinkWait;
3412  if (lfLinks[removalBegin].myDistance >= brakeGap || (lfLinks[removalBegin].myDistance > 0 && myState.mySpeed < ACCEL2SPEED(getCarFollowModel().getMaxDecel()))) {
3413  lfLinks[removalBegin].mySetRequest = false;
3414  }
3415  ++removalBegin;
3416  }
3417  }
3418  }
3419  for (DriveItemVector::iterator i = lfLinks.begin(); i != lfLinks.end(); ++i) {
3420  if ((*i).myLink != 0) {
3421  if ((*i).myLink->getState() == LINKSTATE_ALLWAY_STOP) {
3422  (*i).myArrivalTime += (SUMOTime)RandHelper::rand((int)2); // tie braker
3423  }
3424  (*i).myLink->setApproaching(this, (*i).myArrivalTime, (*i).myArrivalSpeed, (*i).getLeaveSpeed(),
3425  (*i).mySetRequest, (*i).myArrivalTimeBraking, (*i).myArrivalSpeedBraking, getWaitingTime(), (*i).myDistance);
3426  }
3427  }
3428  if (getLaneChangeModel().getShadowLane() != 0) {
3429  // register on all shadow links
3430  for (DriveItemVector::iterator i = lfLinks.begin(); i != lfLinks.end(); ++i) {
3431  if ((*i).myLink != 0) {
3432  MSLink* parallelLink = (*i).myLink->getParallelLink(getLaneChangeModel().getShadowDirection());
3433  if (parallelLink != 0) {
3434  parallelLink->setApproaching(this, (*i).myArrivalTime, (*i).myArrivalSpeed, (*i).getLeaveSpeed(),
3435  (*i).mySetRequest, (*i).myArrivalTimeBraking, (*i).myArrivalSpeedBraking, getWaitingTime(), (*i).myDistance);
3437  }
3438  }
3439  }
3440  }
3441 }
3442 
3443 
3444 void
3446  for (MoveReminderCont::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end();) {
3447  // skip the reminder if it is a lane reminder but not for my lane (indicated by rem->second > 0.)
3448  if (rem->first->getLane() != 0 && rem->second > 0.) {
3449 #ifdef _DEBUG
3450  if (myTraceMoveReminders) {
3451  traceMoveReminder("notifyEnter_skipped", rem->first, rem->second, true);
3452  }
3453 #endif
3454  ++rem;
3455  } else {
3456  if (rem->first->notifyEnter(*this, reason, enteredLane)) {
3457 #ifdef _DEBUG
3458  if (myTraceMoveReminders) {
3459  traceMoveReminder("notifyEnter", rem->first, rem->second, true);
3460  }
3461 #endif
3462  ++rem;
3463  } else {
3464 #ifdef _DEBUG
3465  if (myTraceMoveReminders) {
3466  traceMoveReminder("notifyEnter", rem->first, rem->second, false);
3467  }
3468 // std::cout << SIMTIME << " Vehicle '" << getID() << "' erases MoveReminder (with offset " << rem->second << ")" << std::endl;
3469 #endif
3470  rem = myMoveReminders.erase(rem);
3471  }
3472  }
3473  }
3474 }
3475 
3476 
3477 bool
3478 MSVehicle::enterLaneAtMove(MSLane* enteredLane, bool onTeleporting) {
3479  myAmOnNet = !onTeleporting;
3480  // vaporizing edge?
3481  /*
3482  if (enteredLane->getEdge().isVaporizing()) {
3483  // yep, let's do the vaporization...
3484  myLane = enteredLane;
3485  return true;
3486  }
3487  */
3488  // Adjust MoveReminder offset to the next lane
3489  adaptLaneEntering2MoveReminder(*enteredLane);
3490  // set the entered lane as the current lane
3491  myLane = enteredLane;
3492  myLastBestLanesEdge = 0;
3493 
3494  // internal edges are not a part of the route...
3495  if (!enteredLane->getEdge().isInternal()) {
3496  ++myCurrEdge;
3497  }
3498  if (!onTeleporting) {
3500  } else {
3501  // normal move() isn't called so reset position here. must be done
3502  // before calling reminders
3503  myState.myPos = 0;
3506  }
3507  // update via
3508  if (myParameter->via.size() > 0 && myLane->getEdge().getID() == myParameter->via.front()) {
3509  myParameter->via.erase(myParameter->via.begin());
3510  }
3511  return hasArrived();
3512 }
3513 
3514 
3515 void
3517  myAmOnNet = true;
3518  myLane = enteredLane;
3520  // need to update myCurrentLaneInBestLanes
3521  updateBestLanes();
3522  // switch to and activate the new lane's reminders
3523  // keep OldLaneReminders
3524  for (std::vector< MSMoveReminder* >::const_iterator rem = enteredLane->getMoveReminders().begin(); rem != enteredLane->getMoveReminders().end(); ++rem) {
3525  addReminder(*rem);
3526  }
3528  MSLane* lane = myLane;
3529  double leftLength = getVehicleType().getLength() - myState.myPos;
3530  for (int i = 0; i < (int)myFurtherLanes.size(); i++) {
3531  if (lane != 0) {
3532  lane = lane->getLogicalPredecessorLane(myFurtherLanes[i]->getEdge());
3533  }
3534  if (lane != 0) {
3535 #ifdef DEBUG_FURTHER
3536  if (DEBUG_COND) {
3537  std::cout << SIMTIME << " enterLaneAtLaneChange \n";
3538  }
3539 #endif
3540  myFurtherLanes[i]->resetPartialOccupation(this);
3541  myFurtherLanes[i] = lane;
3543 #ifdef DEBUG_FURTHER
3544  if (DEBUG_COND) {
3545  std::cout << SIMTIME << " enterLaneAtLaneChange \n";
3546  }
3547 #endif
3548  leftLength -= (lane)->setPartialOccupation(this);
3549  } else {
3550  // keep the old values, but ensure there is no shadow
3553  }
3554  }
3555  }
3556 #ifdef DEBUG_FURTHER
3557  if (DEBUG_COND) {
3558  std::cout << SIMTIME << " enterLaneAtLaneChange new furtherLanes=" << toString(myFurtherLanes) << "\n";
3559  }
3560 #endif
3561  myAngle = computeAngle();
3562 }
3563 
3564 
3565 void
3566 MSVehicle::enterLaneAtInsertion(MSLane* enteredLane, double pos, double speed, double posLat, MSMoveReminder::Notification notification) {
3567  myState = State(pos, speed, posLat, pos - getVehicleType().getLength());
3568  if (myDeparture == NOT_YET_DEPARTED) {
3569  onDepart();
3570  }
3572  assert(myState.myPos >= 0);
3573  assert(myState.mySpeed >= 0);
3574  myLane = enteredLane;
3575  myAmOnNet = true;
3576  // schedule action for the next timestep
3578  if (notification != MSMoveReminder::NOTIFICATION_TELEPORT) {
3579  // set and activate the new lane's reminders, teleports already did that at enterLaneAtMove
3580  for (std::vector< MSMoveReminder* >::const_iterator rem = enteredLane->getMoveReminders().begin(); rem != enteredLane->getMoveReminders().end(); ++rem) {
3581  addReminder(*rem);
3582  }
3583  activateReminders(notification, enteredLane);
3584  }
3585  // build the list of lanes the vehicle is lapping into
3586  if (!myLaneChangeModel->isOpposite()) {
3587  double leftLength = myType->getLength() - pos;
3588  MSLane* clane = enteredLane;
3589  while (leftLength > 0) {
3590  clane = clane->getLogicalPredecessorLane();
3591  if (clane == 0 || clane == myLane) {
3592  break;
3593  }
3594  myFurtherLanes.push_back(clane);
3596  leftLength -= (clane)->setPartialOccupation(this);
3597  }
3598  myState.myBackPos = -leftLength;
3599  } else {
3600  // clear partial occupation
3601  for (std::vector<MSLane*>::iterator i = myFurtherLanes.begin(); i != myFurtherLanes.end(); ++i) {
3602 #ifdef DEBUG_FURTHER
3603  if (DEBUG_COND) {
3604  std::cout << SIMTIME << " enterLaneAtInsertion \n";
3605  }
3606 #endif
3607  (*i)->resetPartialOccupation(this);
3608  }
3609  myFurtherLanes.clear();
3610  myFurtherLanesPosLat.clear();
3611  }
3615  }
3616  myAngle = computeAngle();
3617  if (getLaneChangeModel().isOpposite()) {
3618  myAngle += M_PI;
3619  }
3620 }
3621 
3622 
3623 void
3624 MSVehicle::leaveLane(const MSMoveReminder::Notification reason, const MSLane* approachedLane) {
3625  for (MoveReminderCont::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end();) {
3626  if (rem->first->notifyLeave(*this, myState.myPos + rem->second, reason, approachedLane)) {
3627 #ifdef _DEBUG
3628  if (myTraceMoveReminders) {
3629  traceMoveReminder("notifyLeave", rem->first, rem->second, true);
3630  }
3631 #endif
3632  ++rem;
3633  } else {
3634 #ifdef _DEBUG
3635  if (myTraceMoveReminders) {
3636  traceMoveReminder("notifyLeave", rem->first, rem->second, false);
3637  }
3638 #endif
3639  rem = myMoveReminders.erase(rem);
3640  }
3641  }
3643  // @note. In case of lane change, myFurtherLanes and partial occupation
3644  // are handled in enterLaneAtLaneChange()
3645  for (std::vector<MSLane*>::iterator i = myFurtherLanes.begin(); i != myFurtherLanes.end(); ++i) {
3646 #ifdef DEBUG_FURTHER
3647  if (DEBUG_COND) {
3648  std::cout << SIMTIME << " leaveLane \n";
3649  }
3650 #endif
3651  (*i)->resetPartialOccupation(this);
3652  }
3653  myFurtherLanes.clear();
3654  myFurtherLanesPosLat.clear();
3655  }
3656  if (reason >= MSMoveReminder::NOTIFICATION_TELEPORT) {
3657  myAmOnNet = false;
3658  myWaitingTime = 0;
3659  }
3661  WRITE_WARNING("Vehicle '" + getID() + "' aborts stop.");
3662  }
3664  while (!myStops.empty() && myStops.front().edge == myCurrEdge && &myStops.front().lane->getEdge() == &myLane->getEdge()) {
3665  WRITE_WARNING("Vehicle '" + getID() + "' skips stop on lane '" + myStops.front().lane->getID()
3666  + "' time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".")
3667  myStops.pop_front();
3668  }
3669  }
3670 }
3671 
3672 
3675  return *myLaneChangeModel;
3676 }
3677 
3678 
3681  return *myLaneChangeModel;
3682 }
3683 
3684 
3685 const std::vector<MSVehicle::LaneQ>&
3687  return *myBestLanes.begin();
3688 }
3689 
3690 
3691 void
3692 MSVehicle::updateBestLanes(bool forceRebuild, const MSLane* startLane) {
3693 #ifdef DEBUG_BESTLANES
3694  if (DEBUG_COND) {
3695  std::cout << SIMTIME << " updateBestLanes veh=" << getID() << " startLane1=" << Named::getIDSecure(startLane) << " myLane=" << Named::getIDSecure(myLane) << "\n";
3696  }
3697 #endif
3698  if (startLane == 0) {
3699  startLane = myLane;
3700  }
3701  assert(startLane != 0);
3702  if (getLaneChangeModel().isOpposite()) {
3703  // depending on the calling context, startLane might be the forward lane
3704  // or the reverse-direction lane. In the latter case we need to
3705  // transform it to the forward lane.
3706  bool startLaneIsOpposite = (startLane->isInternal()
3707  ? & (startLane->getLinkCont()[0]->getLane()->getEdge()) != *(myCurrEdge + 1)
3708  : &startLane->getEdge() != *myCurrEdge);
3709  if (startLaneIsOpposite) {
3710  startLane = startLane->getOpposite();
3711  assert(startLane != 0);
3712  }
3713  }
3714  if (myBestLanes.size() > 0 && !forceRebuild && myLastBestLanesEdge == &startLane->getEdge()) {
3716  return;
3717  }
3718  if (startLane->getEdge().isInternal()) {
3719  if (myBestLanes.size() == 0 || forceRebuild) {
3720  // rebuilt from previous non-internal lane (may backtrack twice if behind an internal junction)
3721  updateBestLanes(true, startLane->getLogicalPredecessorLane());
3722  }
3723  if (myLastBestLanesInternalLane == startLane && !forceRebuild) {
3724  return;
3725  }
3726  // adapt best lanes to fit the current internal edge:
3727  // keep the entries that are reachable from this edge
3728  const MSEdge* nextEdge = startLane->getNextNormal();
3729  assert(!nextEdge->isInternal());
3730  for (std::vector<std::vector<LaneQ> >::iterator it = myBestLanes.begin(); it != myBestLanes.end();) {
3731  std::vector<LaneQ>& lanes = *it;
3732  assert(lanes.size() > 0);
3733  if (&(lanes[0].lane->getEdge()) == nextEdge) {
3734  // keep those lanes which are successors of internal lanes from the edge of startLane
3735  std::vector<LaneQ> oldLanes = lanes;
3736  lanes.clear();
3737  const std::vector<MSLane*>& sourceLanes = startLane->getEdge().getLanes();
3738  for (std::vector<MSLane*>::const_iterator it_source = sourceLanes.begin(); it_source != sourceLanes.end(); ++it_source) {
3739  for (std::vector<LaneQ>::iterator it_lane = oldLanes.begin(); it_lane != oldLanes.end(); ++it_lane) {
3740  if ((*it_source)->getLinkCont()[0]->getLane() == (*it_lane).lane) {
3741  lanes.push_back(*it_lane);
3742  break;
3743  }
3744  }
3745  }
3746  assert(lanes.size() == startLane->getEdge().getLanes().size());
3747  // patch invalid bestLaneOffset and updated myCurrentLaneInBestLanes
3748  for (int i = 0; i < (int)lanes.size(); ++i) {
3749  if (i + lanes[i].bestLaneOffset < 0) {
3750  lanes[i].bestLaneOffset = -i;
3751  }
3752  if (i + lanes[i].bestLaneOffset >= (int)lanes.size()) {
3753  lanes[i].bestLaneOffset = (int)lanes.size() - i - 1;
3754  }
3755  assert(i + lanes[i].bestLaneOffset >= 0);
3756  assert(i + lanes[i].bestLaneOffset < (int)lanes.size());
3757  if (lanes[i].bestContinuations[0] != 0) {
3758  // patch length of bestContinuation to match expectations (only once)
3759  lanes[i].bestContinuations.insert(lanes[i].bestContinuations.begin(), (MSLane*)0);
3760  }
3761  if (startLane->getLinkCont()[0]->getLane() == lanes[i].lane) {
3762  myCurrentLaneInBestLanes = lanes.begin() + i;
3763  }
3764  assert(&(lanes[i].lane->getEdge()) == nextEdge);
3765  }
3766  myLastBestLanesInternalLane = startLane;
3768  return;
3769  } else {
3770  // remove passed edges
3771  it = myBestLanes.erase(it);
3772  }
3773  }
3774  assert(false); // should always find the next edge
3775  }
3776  // start rebuilding
3777  myLastBestLanesEdge = &startLane->getEdge();
3778  myBestLanes.clear();
3779 
3780  // get information about the next stop
3781  MSRouteIterator nextStopEdge = myRoute->end();
3782  const MSLane* nextStopLane = 0;
3783  double nextStopPos = 0;
3784  if (!myStops.empty()) {
3785  const Stop& nextStop = myStops.front();
3786  nextStopLane = nextStop.lane;
3787  nextStopEdge = nextStop.edge;
3788  nextStopPos = nextStop.pars.startPos;
3789  }
3790  if (myParameter->arrivalLaneProcedure == ARRIVAL_LANE_GIVEN && nextStopEdge == myRoute->end()) {
3791  nextStopEdge = (myRoute->end() - 1);
3792  nextStopLane = (*nextStopEdge)->getLanes()[myArrivalLane];
3793  nextStopPos = myArrivalPos;
3794  }
3795  if (nextStopEdge != myRoute->end()) {
3796  // make sure that the "wrong" lanes get a penalty. (penalty needs to be
3797  // large enough to overcome a magic threshold in MSLCM_DK2004.cpp:383)
3798  nextStopPos = MAX2(POSITION_EPS, MIN2((double)nextStopPos, (double)(nextStopLane->getLength() - 2 * POSITION_EPS)));
3799  if (nextStopLane->isInternal()) {
3800  nextStopPos += (*nextStopEdge)->getLength();
3801  }
3802  }
3803 
3804  // go forward along the next lanes;
3805  int seen = 0;
3806  double seenLength = 0;
3807  bool progress = true;
3808  for (MSRouteIterator ce = myCurrEdge; progress;) {
3809  std::vector<LaneQ> currentLanes;
3810  const std::vector<MSLane*>* allowed = 0;
3811  const MSEdge* nextEdge = 0;
3812  if (ce != myRoute->end() && ce + 1 != myRoute->end()) {
3813  nextEdge = *(ce + 1);
3814  allowed = (*ce)->allowedLanes(*nextEdge, myType->getVehicleClass());
3815  }
3816  const std::vector<MSLane*>& lanes = (*ce)->getLanes();
3817  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
3818  LaneQ q;
3819  MSLane* cl = *i;
3820  q.lane = cl;
3821  q.bestContinuations.push_back(cl);
3822  q.bestLaneOffset = 0;
3823  q.length = cl->allowsVehicleClass(myType->getVehicleClass()) ? cl->getLength() : 0;
3824  q.currentLength = q.length;
3825  q.allowsContinuation = allowed == 0 || find(allowed->begin(), allowed->end(), cl) != allowed->end();
3826  q.occupation = 0;
3827  q.nextOccupation = 0;
3828  currentLanes.push_back(q);
3829  }
3830  //
3831  if (nextStopEdge == ce && !nextStopLane->isInternal()) {
3832  progress = false;
3833  for (std::vector<LaneQ>::iterator q = currentLanes.begin(); q != currentLanes.end(); ++q) {
3834  if (nextStopLane != 0 && nextStopLane != (*q).lane) {
3835  (*q).allowsContinuation = false;
3836  (*q).length = nextStopPos;
3837  (*q).currentLength = (*q).length;
3838  }
3839  }
3840  }
3841 
3842  myBestLanes.push_back(currentLanes);
3843  ++seen;
3844  seenLength += currentLanes[0].lane->getLength();
3845  ++ce;
3846  progress &= (seen <= 4 || seenLength < 3000);
3847  progress &= seen <= 8;
3848  progress &= ce != myRoute->end();
3849  /*
3850  if(progress) {
3851  progress &= (currentLanes.size()!=1||(*ce)->getLanes().size()!=1);
3852  }
3853  */
3854  }
3855 
3856  // we are examining the last lane explicitly
3857  if (myBestLanes.size() != 0) {
3858  double bestLength = -1;
3859  int bestThisIndex = 0;
3860  int index = 0;
3861  std::vector<LaneQ>& last = myBestLanes.back();
3862  for (std::vector<LaneQ>::iterator j = last.begin(); j != last.end(); ++j, ++index) {
3863  if ((*j).length > bestLength) {
3864  bestLength = (*j).length;
3865  bestThisIndex = index;
3866  }
3867  }
3868  index = 0;
3869  for (std::vector<LaneQ>::iterator j = last.begin(); j != last.end(); ++j, ++index) {
3870  if ((*j).length < bestLength) {
3871  (*j).bestLaneOffset = bestThisIndex - index;
3872  }
3873  }
3874  }
3875 #ifdef DEBUG_BESTLANES
3876  if (DEBUG_COND) {
3877  std::cout << " last edge:\n";
3878  std::vector<LaneQ>& laneQs = myBestLanes.back();
3879  for (std::vector<LaneQ>::iterator j = laneQs.begin(); j != laneQs.end(); ++j) {
3880  std::cout << " lane=" << (*j).lane->getID() << " length=" << (*j).length << " bestOffset=" << (*j).bestLaneOffset << "\n";
3881  }
3882  }
3883 #endif
3884  // go backward through the lanes
3885  // track back best lane and compute the best prior lane(s)
3886  for (std::vector<std::vector<LaneQ> >::reverse_iterator i = myBestLanes.rbegin() + 1; i != myBestLanes.rend(); ++i) {
3887  std::vector<LaneQ>& nextLanes = (*(i - 1));
3888  std::vector<LaneQ>& clanes = (*i);
3889  MSEdge& cE = clanes[0].lane->getEdge();
3890  int index = 0;
3891  double bestConnectedLength = -1;
3892  double bestLength = -1;
3893  for (std::vector<LaneQ>::iterator j = nextLanes.begin(); j != nextLanes.end(); ++j, ++index) {
3894  if ((*j).lane->isApproachedFrom(&cE) && bestConnectedLength < (*j).length) {
3895  bestConnectedLength = (*j).length;
3896  }
3897  if (bestLength < (*j).length) {
3898  bestLength = (*j).length;
3899  }
3900  }
3901  // compute index of the best lane (highest length and least offset from the best next lane)
3902  int bestThisIndex = 0;
3903  if (bestConnectedLength > 0) {
3904  index = 0;
3905  for (std::vector<LaneQ>::iterator j = clanes.begin(); j != clanes.end(); ++j, ++index) {
3906  LaneQ bestConnectedNext;
3907  bestConnectedNext.length = -1;
3908  if ((*j).allowsContinuation) {
3909  for (std::vector<LaneQ>::const_iterator m = nextLanes.begin(); m != nextLanes.end(); ++m) {
3910  if ((*m).lane->isApproachedFrom(&cE, (*j).lane)) {
3911  if (bestConnectedNext.length < (*m).length || (bestConnectedNext.length == (*m).length && abs(bestConnectedNext.bestLaneOffset) > abs((*m).bestLaneOffset))) {
3912  bestConnectedNext = *m;
3913  }
3914  }
3915  }
3916  if (bestConnectedNext.length == bestConnectedLength && abs(bestConnectedNext.bestLaneOffset) < 2) {
3917  (*j).length += bestLength;
3918  } else {
3919  (*j).length += bestConnectedNext.length;
3920  }
3921  (*j).bestLaneOffset = bestConnectedNext.bestLaneOffset;
3922  }
3923  copy(bestConnectedNext.bestContinuations.begin(), bestConnectedNext.bestContinuations.end(), back_inserter((*j).bestContinuations));
3924  if (clanes[bestThisIndex].length < (*j).length
3925  || (clanes[bestThisIndex].length == (*j).length && abs(clanes[bestThisIndex].bestLaneOffset) > abs((*j).bestLaneOffset))
3926  || (clanes[bestThisIndex].length == (*j).length && abs(clanes[bestThisIndex].bestLaneOffset) == abs((*j).bestLaneOffset) &&
3927  nextLinkPriority(clanes[bestThisIndex].bestContinuations) < nextLinkPriority((*j).bestContinuations))
3928  ) {
3929  bestThisIndex = index;
3930  }
3931  }
3932 #ifdef DEBUG_BESTLANES
3933  if (DEBUG_COND) {
3934  std::cout << " edge=" << cE.getID() << "\n";
3935  std::vector<LaneQ>& laneQs = clanes;
3936  for (std::vector<LaneQ>::iterator j = laneQs.begin(); j != laneQs.end(); ++j) {
3937  std::cout << " lane=" << (*j).lane->getID() << " length=" << (*j).length << " bestOffset=" << (*j).bestLaneOffset << "\n";
3938  }
3939  }
3940 #endif
3941 
3942  } else {
3943  // only needed in case of disconnected routes
3944  int bestNextIndex = 0;
3945  int bestDistToNeeded = (int) clanes.size();
3946  index = 0;
3947  for (std::vector<LaneQ>::iterator j = clanes.begin(); j != clanes.end(); ++j, ++index) {
3948  if ((*j).allowsContinuation) {
3949  int nextIndex = 0;
3950  for (std::vector<LaneQ>::const_iterator m = nextLanes.begin(); m != nextLanes.end(); ++m, ++nextIndex) {
3951  if ((*m).lane->isApproachedFrom(&cE, (*j).lane)) {
3952  if (bestDistToNeeded > abs((*m).bestLaneOffset)) {
3953  bestDistToNeeded = abs((*m).bestLaneOffset);
3954  bestThisIndex = index;
3955  bestNextIndex = nextIndex;
3956  }
3957  }
3958  }
3959  }
3960  }
3961  clanes[bestThisIndex].length += nextLanes[bestNextIndex].length;
3962  copy(nextLanes[bestNextIndex].bestContinuations.begin(), nextLanes[bestNextIndex].bestContinuations.end(), back_inserter(clanes[bestThisIndex].bestContinuations));
3963 
3964  }
3965  // set bestLaneOffset for all lanes
3966  index = 0;
3967  for (std::vector<LaneQ>::iterator j = clanes.begin(); j != clanes.end(); ++j, ++index) {
3968  if ((*j).length < clanes[bestThisIndex].length
3969  || ((*j).length == clanes[bestThisIndex].length && abs((*j).bestLaneOffset) > abs(clanes[bestThisIndex].bestLaneOffset))
3970  || (nextLinkPriority((*j).bestContinuations)) < nextLinkPriority(clanes[bestThisIndex].bestContinuations)
3971  ) {
3972  (*j).bestLaneOffset = bestThisIndex - index;
3973  if ((nextLinkPriority((*j).bestContinuations)) < nextLinkPriority(clanes[bestThisIndex].bestContinuations)) {
3974  // try to move away from the lower-priority lane before it ends
3975  (*j).length = (*j).currentLength;
3976  }
3977  } else {
3978  (*j).bestLaneOffset = 0;
3979  }
3980  }
3981  }
3983 #ifdef DEBUG_BESTLANES
3984  if (DEBUG_COND) {
3985  std::cout << SIMTIME << " veh=" << getID() << " bestCont=" << toString(getBestLanesContinuation()) << "\n";
3986  }
3987 #endif
3988  return;
3989 }
3990 
3991 
3992 int
3993 MSVehicle::nextLinkPriority(const std::vector<MSLane*>& conts) {
3994  if (conts.size() < 2) {
3995  return -1;
3996  } else {
3997  MSLink* link = MSLinkContHelper::getConnectingLink(*conts[0], *conts[1]);
3998  if (link != 0) {
3999  return link->havePriority() ? 1 : 0;
4000  } else {
4001  // disconnected route
4002  return -1;
4003  }
4004  }
4005 }
4006 
4007 
4008 void
4010  std::vector<LaneQ>& currLanes = *myBestLanes.begin();
4011  std::vector<LaneQ>::iterator i;
4012  for (i = currLanes.begin(); i != currLanes.end(); ++i) {
4013  double nextOccupation = 0;
4014  for (std::vector<MSLane*>::const_iterator j = (*i).bestContinuations.begin() + 1; j != (*i).bestContinuations.end(); ++j) {
4015  nextOccupation += (*j)->getBruttoVehLenSum();
4016  }
4017  (*i).nextOccupation = nextOccupation;
4018  if ((*i).lane == startLane) {
4020  }
4021  }
4022 }
4023 
4024 
4025 const std::vector<MSLane*>&
4027  if (myBestLanes.empty() || myBestLanes[0].empty()) {
4028  return myEmptyLaneVector;
4029  }
4030  return (*myCurrentLaneInBestLanes).bestContinuations;
4031 }
4032 
4033 
4034 const std::vector<MSLane*>&
4036  const MSLane* lane = l;
4037  // XXX: shouldn't this be a "while" to cover more than one internal lane? (Leo) Refs. #2575
4038  if (lane->getEdge().isInternal()) {
4039  // internal edges are not kept inside the bestLanes structure
4040  lane = lane->getLinkCont()[0]->getLane();
4041  }
4042  if (myBestLanes.size() == 0) {
4043  return myEmptyLaneVector;
4044  }
4045  for (std::vector<LaneQ>::const_iterator i = myBestLanes[0].begin(); i != myBestLanes[0].end(); ++i) {
4046  if ((*i).lane == lane) {
4047  return (*i).bestContinuations;
4048  }
4049  }
4050  return myEmptyLaneVector;
4051 }
4052 
4053 
4054 int
4056  if (myBestLanes.empty() || myBestLanes[0].empty()) {
4057  return 0;
4058  } else {
4059  return (*myCurrentLaneInBestLanes).bestLaneOffset;
4060  }
4061 }
4062 
4063 
4064 void
4065 MSVehicle::adaptBestLanesOccupation(int laneIndex, double density) {
4066  std::vector<MSVehicle::LaneQ>& preb = myBestLanes.front();
4067  assert(laneIndex < (int)preb.size());
4068  preb[laneIndex].occupation = density + preb[laneIndex].nextOccupation;
4069 }
4070 
4071 
4072 void
4074  if (MSGlobals::gLaneChangeDuration > 0 && !getLaneChangeModel().isChangingLanes()) {
4075  myState.myPosLat = 0;
4076  }
4077 }
4078 
4079 
4080 double
4081 MSVehicle::getDistanceToPosition(double destPos, const MSEdge* destEdge) const {
4082  double distance = std::numeric_limits<double>::max();
4083  if (isOnRoad() && destEdge != NULL) {
4084  if (&myLane->getEdge() == *myCurrEdge) {
4085  // vehicle is on a normal edge
4086  distance = myRoute->getDistanceBetween(getPositionOnLane(), destPos, *myCurrEdge, destEdge);
4087  } else {
4088  // vehicle is on inner junction edge
4089  distance = myLane->getLength() - getPositionOnLane();
4090  distance += myRoute->getDistanceBetween(0, destPos, *(myCurrEdge + 1), destEdge);
4091  }
4092  }
4093  return distance;
4094 }
4095 
4096 
4097 std::pair<const MSVehicle* const, double>
4098 MSVehicle::getLeader(double dist) const {
4099  if (myLane == 0) {
4100  return std::make_pair(static_cast<const MSVehicle*>(0), -1);
4101  }
4102  if (dist == 0) {
4104  }
4105  const MSVehicle* lead = 0;
4106  const MSLane::VehCont& vehs = myLane->getVehiclesSecure();
4107  // vehicle might be outside the road network
4108  MSLane::VehCont::const_iterator it = std::find(vehs.begin(), vehs.end(), this);
4109  if (it != vehs.end() && it + 1 != vehs.end()) {
4110  lead = *(it + 1);
4111  }
4112  if (lead != 0) {
4113  std::pair<const MSVehicle* const, double> result(
4116  return result;
4117  }
4118  const double seen = myLane->getLength() - getPositionOnLane();
4119  const std::vector<MSLane*>& bestLaneConts = getBestLanesContinuation(myLane);
4120  std::pair<const MSVehicle* const, double> result = myLane->getLeaderOnConsecutive(dist, seen, getSpeed(), *this, bestLaneConts);
4122  return result;
4123 }
4124 
4125 
4126 double
4128  // calling getLeader with 0 would induce a dist calculation but we only want to look for the leaders on the current lane
4129  std::pair<const MSVehicle* const, double> leaderInfo = getLeader(-1);
4130  if (leaderInfo.first == 0 || getSpeed() == 0) {
4131  return -1;
4132  }
4133  return (leaderInfo.second + getVehicleType().getMinGap()) / getSpeed();
4134 }
4135 
4136 
4137 double
4140 }
4141 
4142 
4143 double
4146 }
4147 
4148 
4149 double
4152 }
4153 
4154 
4155 double
4158 }
4159 
4160 
4161 double
4164 }
4165 
4166 
4167 double
4170 }
4171 
4172 
4173 double
4176 }
4177 
4178 
4179 double
4182 }
4183 
4184 
4185 void
4187  if (myPersonDevice == 0) {
4189  myMoveReminders.push_back(std::make_pair(myPersonDevice, 0.));
4190  }
4192  if (myStops.size() > 0 && myStops.front().reached && myStops.front().triggered && myStops.front().numExpectedPerson > 0) {
4193  myStops.front().numExpectedPerson -= (int)myStops.front().pars.awaitedPersons.count(person->getID());
4194  if (myStops.front().numExpectedPerson == 0) {
4195  myStops.front().duration = 0;
4196  }
4197  }
4198 }
4199 
4200 void
4202  if (myContainerDevice == 0) {
4204  myMoveReminders.push_back(std::make_pair(myContainerDevice, 0.));
4205  }
4206  myContainerDevice->addTransportable(container);
4207  if (myStops.size() > 0 && myStops.front().reached && myStops.front().pars.containerTriggered && myStops.front().numExpectedContainer > 0) {
4208  myStops.front().numExpectedContainer -= (int)myStops.front().pars.awaitedContainers.count(container->getID());
4209  if (myStops.front().numExpectedContainer == 0) {
4210  myStops.front().duration = 0;
4211  }
4212  }
4213 }
4214 
4215 
4216 void
4218  const bool isPerson = dynamic_cast<MSPerson*>(t) != 0;
4220  if (device != 0) {
4221  device->removeTransportable(t);
4222  }
4223 }
4224 
4225 
4226 const std::vector<MSTransportable*>&
4228  if (myPersonDevice == 0) {
4230  } else {
4232  }
4233 }
4234 
4235 
4236 const std::vector<MSTransportable*>&
4238  if (myContainerDevice == 0) {
4240  } else {
4242  }
4243 }
4244 
4245 
4246 int
4248  int boarded = myPersonDevice == 0 ? 0 : myPersonDevice->size();
4249  return boarded + myParameter->personNumber;
4250 }
4251 
4252 int
4254  int loaded = myContainerDevice == 0 ? 0 : myContainerDevice->size();
4255  return loaded + myParameter->containerNumber;
4256 }
4257 
4258 
4259 void
4262  int state = getLaneChangeModel().getOwnState();
4263  // do not set blinker for sublane changes or when blocked from changing to the right
4264  const bool blinkerManoeuvre = (((state & LCA_SUBLANE) == 0) && (
4265  (state & LCA_KEEPRIGHT) == 0 || (state & LCA_BLOCKED) == 0));
4266  if ((state & LCA_LEFT) != 0 && blinkerManoeuvre) {
4268  } else if ((state & LCA_RIGHT) != 0 && blinkerManoeuvre) {
4270  } else if (getLaneChangeModel().isChangingLanes()) {
4271  if (getLaneChangeModel().getLaneChangeDirection() == 1) {
4273  } else {
4275  }
4276  } else {
4277  const MSLane* lane = getLane();
4278  MSLinkCont::const_iterator link = MSLane::succLinkSec(*this, 1, *lane, getBestLanesContinuation());
4279  if (link != lane->getLinkCont().end() && lane->getLength() - getPositionOnLane() < lane->getVehicleMaxSpeed(this) * (double) 7.) {
4280  switch ((*link)->getDirection()) {
4281  case LINKDIR_TURN:
4282  case LINKDIR_LEFT:
4283  case LINKDIR_PARTLEFT:
4285  break;
4286  case LINKDIR_RIGHT:
4287  case LINKDIR_PARTRIGHT:
4289  break;
4290  default:
4291  break;
4292  }
4293  }
4294  }
4295  if (myInfluencer != 0 && myInfluencer->getSignals() >= 0) {
4297  myInfluencer->setSignals(-1); // overwrite computed signals only once
4298  }
4299 }
4300 
4301 void
4303  if (currentTime % 1000 == 0) {
4306  } else {
4308  }
4309  }
4310 }
4311 
4312 
4313 int
4315  std::vector<MSLane*>::const_iterator laneP = std::find(myLane->getEdge().getLanes().begin(), myLane->getEdge().getLanes().end(), myLane);
4316  return (int) std::distance(myLane->getEdge().getLanes().begin(), laneP);
4317 }
4318 
4319 
4320 void
4321 MSVehicle::setTentativeLaneAndPosition(MSLane* lane, double pos, double posLat) {
4322  assert(lane != 0);
4323  myLane = lane;
4324  myState.myPos = pos;
4325  myState.myPosLat = posLat;
4327 }
4328 
4329 
4330 double
4332  return myState.myPosLat + 0.5 * myLane->getWidth() - 0.5 * getVehicleType().getWidth();
4333 }
4334 
4335 
4336 double
4338  return getCenterOnEdge(lane) - 0.5 * getVehicleType().getWidth();
4339 }
4340 
4341 
4342 double
4344  if (lane == 0 || &lane->getEdge() == &myLane->getEdge()) {
4345  return myLane->getRightSideOnEdge() + myState.myPosLat + 0.5 * myLane->getWidth();
4346  } else {
4347  assert(myFurtherLanes.size() == myFurtherLanesPosLat.size());
4348  for (int i = 0; i < (int)myFurtherLanes.size(); ++i) {
4349  if (myFurtherLanes[i] == lane) {
4350 #ifdef DEBUG_FURTHER
4351  if (DEBUG_COND) std::cout << " getCenterOnEdge veh=" << getID() << " lane=" << lane->getID() << " i=" << i << " furtherLat=" << myFurtherLanesPosLat[i]
4352  << " result=" << lane->getRightSideOnEdge() + myFurtherLanesPosLat[i] + 0.5 * lane->getWidth()
4353  << "\n";
4354 #endif
4355  return lane->getRightSideOnEdge() + myFurtherLanesPosLat[i] + 0.5 * lane->getWidth();
4356  }
4357  }
4358  //if (DEBUG_COND) std::cout << SIMTIME << " veh=" << getID() << " myShadowFurtherLanes=" << toString(getLaneChangeModel().getShadowFurtherLanes()) << "\n";
4359  const std::vector<MSLane*>& shadowFurther = getLaneChangeModel().getShadowFurtherLanes();
4360  for (int i = 0; i < (int)shadowFurther.size(); ++i) {
4361  //if (DEBUG_COND) std::cout << " comparing i=" << (*i)->getID() << " lane=" << lane->getID() << "\n";
4362  if (shadowFurther[i] == lane) {
4363  assert(getLaneChangeModel().getShadowLane() != 0);
4364  return (lane->getRightSideOnEdge() + getLaneChangeModel().getShadowFurtherLanesPosLat()[i] + 0.5 * lane->getWidth()
4366  }
4367  }
4368  assert(false);
4369  throw ProcessError("Request lateral pos of vehicle '" + getID() + "' for invalid lane '" + Named::getIDSecure(lane) + "'");
4370  }
4371 }
4372 
4373 
4374 double
4375 MSVehicle::getLatOffset(const MSLane* lane) const {
4376  assert(lane != 0);
4377  if (&lane->getEdge() == &myLane->getEdge()) {
4378  return myLane->getRightSideOnEdge() - lane->getRightSideOnEdge();
4379  } else {
4380  // Check whether the lane is a further lane for the vehicle
4381  for (int i = 0; i < (int)myFurtherLanes.size(); ++i) {
4382  if (myFurtherLanes[i] == lane) {
4383 #ifdef DEBUG_FURTHER
4384  if (DEBUG_COND) {
4385  std::cout << " getLatOffset veh=" << getID() << " lane=" << lane->getID() << " i=" << i << " posLat=" << myState.myPosLat << " furtherLat=" << myFurtherLanesPosLat[i] << "\n";
4386  }
4387 #endif
4389  }
4390  }
4391 #ifdef DEBUG_FURTHER
4392  if (DEBUG_COND) {
4393  std::cout << SIMTIME << " veh=" << getID() << " myShadowFurtherLanes=" << toString(getLaneChangeModel().getShadowFurtherLanes()) << "\n";
4394  }
4395 #endif
4396  // Check whether the lane is a "shadow further lane" for the vehicle
4397  const std::vector<MSLane*>& shadowFurther = getLaneChangeModel().getShadowFurtherLanes();
4398  for (int i = 0; i < (int)shadowFurther.size(); ++i) {
4399  if (shadowFurther[i] == lane) {
4400 #ifdef DEBUG_FURTHER
4401  if (DEBUG_COND) std::cout << " getLatOffset veh=" << getID()
4402  << " shadowLane=" << Named::getIDSecure(getLaneChangeModel().getShadowLane())
4403  << " lane=" << lane->getID()
4404  << " i=" << i
4405  << " posLat=" << myState.myPosLat
4406  << " shadowPosLat=" << getLatOffset(getLaneChangeModel().getShadowLane())
4407  << " shadowFurtherLat=" << getLaneChangeModel().getShadowFurtherLanesPosLat()[i]
4408  << "\n";
4409 #endif
4411  }
4412  }
4413  // Check whether the vehicle issued a maneuverReservation on the lane.
4414  assert(&getLaneChangeModel().getTargetLane()->getEdge() == &myLane->getEdge()); // should have been handled in (&lane->getEdge() == &myLane->getEdge())-block
4415  const std::vector<MSLane*>& furtherTargets = getLaneChangeModel().getFurtherTargetLanes();
4416  for (int i = 0; i < (int)myFurtherLanes.size(); ++i) {
4417  // Further target lanes are just neighboring lanes of the vehicle's further lanes, @see MSAbstractLaneChangeModel::updateTargetLane()
4418  MSLane* targetLane = furtherTargets[i];
4419  if (targetLane == lane) {
4420  const double targetDir = getLaneChangeModel().getManeuverDist() < 0 ? -1. : 1.;
4421  const double latOffset = myFurtherLanesPosLat[i] - myState.myPosLat + targetDir * 0.5 * (myFurtherLanes[i]->getWidth() + targetLane->getWidth());
4422 #ifdef DEBUG_TARGET_LANE
4423  if (DEBUG_COND) {
4424  std::cout << " getLatOffset veh=" << getID()
4425  << " wrt targetLane=" << Named::getIDSecure(getLaneChangeModel().getTargetLane())
4426  << "\n i=" << i
4427  << " posLat=" << myState.myPosLat
4428  << " furtherPosLat=" << myFurtherLanesPosLat[i]
4429  << " maneuverDist=" << getLaneChangeModel().getManeuverDist()
4430  << " targetDir=" << targetDir
4431  << " latOffset=" << latOffset
4432  << std::endl;
4433  }
4434 #endif
4435  return latOffset;
4436  }
4437  }
4438  assert(false);
4439  throw ProcessError("Request lateral offset of vehicle '" + getID() + "' for invalid lane '" + Named::getIDSecure(lane) + "'");
4440  }
4441 }
4442 
4443 
4444 double
4445 MSVehicle::lateralDistanceToLane(const int offset) const {
4446  // compute the distance when changing to the neighboring lane
4447  // (ensure we do not lap into the line behind neighLane since there might be unseen blockers)
4448  assert(offset == 0 || offset == 1 || offset == -1);
4449  assert(myLane != nullptr);
4450  assert(myLane->getParallelLane(offset) != nullptr);
4451  const double halfCurrentLaneWidth = 0.5 * myLane->getWidth();
4452  const double halfVehWidth = 0.5 * (getWidth() + NUMERICAL_EPS);
4453  const double latPos = getLateralPositionOnLane();
4454  double leftLimit = halfCurrentLaneWidth - halfVehWidth - latPos;
4455  double rightLimit = -halfCurrentLaneWidth + halfVehWidth - latPos;
4456  double latLaneDist = 0; // minimum distance to move the vehicle fully onto the new lane
4457  if (offset == 0) {
4458  if (latPos + halfVehWidth > halfCurrentLaneWidth) {
4459  // correct overlapping left
4460  latLaneDist = halfCurrentLaneWidth - latPos - halfVehWidth;
4461  } else if (latPos - halfVehWidth < - halfCurrentLaneWidth) {
4462  // correct overlapping left
4463  latLaneDist = halfCurrentLaneWidth - latPos + halfVehWidth;
4464  }
4465  } else if (offset == -1) {
4466  latLaneDist = rightLimit - (getWidth() + NUMERICAL_EPS);
4467  } else if (offset == 1) {
4468  latLaneDist = leftLimit + (getWidth() + NUMERICAL_EPS);
4469  }
4470 #ifdef DEBUG_ACTIONSTEPS
4471  if DEBUG_COND {
4472  std::cout << SIMTIME
4473  << " veh=" << getID()
4474  << " halfCurrentLaneWidth=" << halfCurrentLaneWidth
4475  << " halfVehWidth=" << halfVehWidth
4476  << " latPos=" << latPos
4477  << " latLaneDist=" << latLaneDist
4478  << " leftLimit=" << leftLimit
4479  << " rightLimit=" << rightLimit
4480  << "\n";
4481  }
4482 #endif
4483  return latLaneDist;
4484 }
4485 
4486 
4487 double
4488 MSVehicle::getLateralOverlap(double posLat) const {
4489  return (fabs(posLat) + 0.5 * getVehicleType().getWidth()
4490  - 0.5 * myLane->getWidth());
4491 }
4492 
4493 
4494 double
4497 }
4498 
4499 void
4501  for (DriveItemVector::iterator i = lfLinks.begin(); i != lfLinks.end(); ++i) {
4502  if ((*i).myLink != 0) {
4503  (*i).myLink->removeApproaching(this);
4504  }
4505  }
4506  // unregister on all shadow links
4508 }
4509 
4510 
4511 bool
4513  // the following links are unsafe:
4514  // - zipper links if they are close enough and have approaching vehicles in the relevant time range
4515  // - unprioritized links if the vehicle is currently approaching a prioritzed link and unable to stop in time
4516  double seen = myLane->getLength() - getPositionOnLane();
4517  const double dist = getCarFollowModel().brakeGap(getSpeed(), getCarFollowModel().getMaxDecel(), 0);
4518  if (seen < dist) {
4519  const std::vector<MSLane*>& bestLaneConts = getBestLanesContinuation(lane);
4520  int view = 1;
4521  MSLinkCont::const_iterator link = MSLane::succLinkSec(*this, view, *lane, bestLaneConts);
4522  DriveItemVector::const_iterator di = myLFLinkLanes.begin();
4523  while (!lane->isLinkEnd(link) && seen <= dist) {
4524  if (!lane->getEdge().isInternal()
4525  && (((*link)->getState() == LINKSTATE_ZIPPER && seen < MSLink::ZIPPER_ADAPT_DIST)
4526  || !(*link)->havePriority())) {
4527  // find the drive item corresponding to this link
4528  bool found = false;
4529  while (di != myLFLinkLanes.end() && !found) {
4530  if ((*di).myLink != 0) {
4531  const MSLane* diPredLane = (*di).myLink->getLaneBefore();
4532  if (diPredLane != 0) {
4533  if (&diPredLane->getEdge() == &lane->getEdge()) {
4534  found = true;
4535  }
4536  }
4537  }
4538  if (!found) {
4539  di++;
4540  }
4541  }
4542  if (found) {
4543  const SUMOTime leaveTime = (*link)->getLeaveTime((*di).myArrivalTime, (*di).myArrivalSpeed,
4544  (*di).getLeaveSpeed(), getVehicleType().getLength());
4545  if ((*link)->hasApproachingFoe((*di).myArrivalTime, leaveTime, (*di).myArrivalSpeed, getCarFollowModel().getMaxDecel())) {
4546  //std::cout << SIMTIME << " veh=" << getID() << " aborting changeTo=" << Named::getIDSecure(bestLaneConts.front()) << " linkState=" << toString((*link)->getState()) << " seen=" << seen << " dist=" << dist << "\n";
4547  return true;
4548  }
4549  }
4550  // no drive item is found if the vehicle aborts it's request within dist
4551  }
4552  lane = (*link)->getViaLaneOrLane();
4553  if (!lane->getEdge().isInternal()) {
4554  view++;
4555  }
4556  seen += lane->getLength();
4557  link = MSLane::succLinkSec(*this, view, *lane, bestLaneConts);
4558  }
4559  }
4560  return false;
4561 }
4562 
4563 
4566  PositionVector centerLine;
4567  centerLine.push_back(getPosition());
4568  centerLine.push_back(getBackPosition());
4569  centerLine.move2side(0.5 * myType->getWidth());
4570  PositionVector result = centerLine;
4571  centerLine.move2side(-myType->getWidth());
4572  result.append(centerLine.reverse(), POSITION_EPS);
4573  return result;
4574 }
4575 
4576 
4579  // XXX implement more types
4580  switch (myType->getGuiShape()) {
4581  case SVS_PASSENGER:
4582  case SVS_PASSENGER_SEDAN:
4584  case SVS_PASSENGER_WAGON:
4585  case SVS_PASSENGER_VAN: {
4586  PositionVector result;
4587  PositionVector centerLine;
4588  centerLine.push_back(getPosition());
4589  centerLine.push_back(getBackPosition());
4590  PositionVector line1 = centerLine;
4591  PositionVector line2 = centerLine;
4592  line1.move2side(0.3 * myType->getWidth());
4593  line2.move2side(0.5 * myType->getWidth());
4594  line2.scaleRelative(0.8);
4595  result.push_back(line1[0]);
4596  result.push_back(line2[0]);
4597  result.push_back(line2[1]);
4598  result.push_back(line1[1]);
4599  line1.move2side(-0.6 * myType->getWidth());
4600  line2.move2side(-1.0 * myType->getWidth());
4601  result.push_back(line1[1]);
4602  result.push_back(line2[1]);
4603  result.push_back(line2[0]);
4604  result.push_back(line1[0]);
4605  return result;
4606  }
4607  default:
4608  return getBoundingBox();
4609  }
4610 }
4611 
4612 
4613 bool
4614 MSVehicle::onFurtherEdge(const MSEdge* edge) const {
4615  for (std::vector<MSLane*>::const_iterator i = myFurtherLanes.begin(); i != myFurtherLanes.end(); ++i) {
4616  if (&(*i)->getEdge() == edge) {
4617  return true;
4618  }
4619  }
4620  return false;
4621 }
4622 
4623 
4624 #ifndef NO_TRACI
4625 bool
4626 MSVehicle::addTraciStop(MSLane* const lane, const double startPos, const double endPos, const SUMOTime duration, const SUMOTime until,
4627  const bool parking, const bool triggered, const bool containerTriggered, std::string& errorMsg) {
4628  //if the stop exists update the duration
4629  for (std::list<Stop>::iterator iter = myStops.begin(); iter != myStops.end(); iter++) {
4630  if (iter->lane == lane && fabs(iter->pars.endPos - endPos) < POSITION_EPS) {
4631  if (duration == 0 && !iter->reached) {
4632  myStops.erase(iter);
4633  // XXX also erase from myParameter->stops ?
4634  updateBestLanes(true);
4635  } else {
4636  iter->duration = duration;
4637  }
4638  return true;
4639  }
4640  }
4641 
4643  newStop.lane = lane->getID();
4644  newStop.startPos = startPos;
4645  newStop.endPos = endPos;
4646  newStop.duration = duration;
4647  newStop.until = until;
4648  newStop.triggered = triggered;
4649  newStop.containerTriggered = containerTriggered;
4650  newStop.parking = parking;
4651  newStop.index = STOP_INDEX_FIT;
4653  if (triggered) {
4654  newStop.parametersSet |= STOP_TRIGGER_SET;
4655  }
4656  if (containerTriggered) {
4658  }
4659  if (parking) {
4660  newStop.parametersSet |= STOP_PARKING_SET;
4661  }
4662  const bool result = addStop(newStop, errorMsg);
4663  if (result) {
4665  myParameter->stops.push_back(newStop);
4666  }
4667  if (myLane != 0) {
4668  updateBestLanes(true);
4669  }
4670  return result;
4671 }
4672 
4673 
4674 bool
4675 MSVehicle::addTraciStopAtStoppingPlace(const std::string& stopId, const SUMOTime duration, const SUMOTime until, const bool parking,
4676  const bool triggered, const bool containerTriggered, const SumoXMLTag stoppingPlaceType, std::string& errorMsg) {
4677  //if the stop exists update the duration
4678  for (std::list<Stop>::iterator iter = myStops.begin(); iter != myStops.end(); iter++) {
4679  Named* stop = 0;
4680  switch (stoppingPlaceType) {
4681  case SUMO_TAG_BUS_STOP:
4682  stop = iter->busstop;
4683  break;
4685  stop = iter->containerstop;
4686  break;
4688  stop = iter->chargingStation;
4689  break;
4690  case SUMO_TAG_PARKING_AREA:
4691  stop = iter->parkingarea;
4692  break;
4693  default:
4694  throw ProcessError("Invalid Stopping place type '" + toString(stoppingPlaceType) + "'");
4695  }
4696  if (stop != 0 && stop->getID() == stopId) {
4697  if (duration == 0 && !iter->reached) {
4698  myStops.erase(iter);
4699  } else {
4700  iter->duration = duration;
4701  }
4702  return true;
4703  }
4704  }
4705 
4707  switch (stoppingPlaceType) {
4708  case SUMO_TAG_BUS_STOP:
4709  newStop.busstop = stopId;
4710  break;
4712  newStop.containerstop = stopId;
4713  break;
4715  newStop.chargingStation = stopId;
4716  break;
4717  case SUMO_TAG_PARKING_AREA:
4718  newStop.parkingarea = stopId;
4719  break;
4720  default:
4721  throw ProcessError("Invalid stopping place type '" + toString(stoppingPlaceType) + "'");
4722  }
4723  MSStoppingPlace* bs = MSNet::getInstance()->getStoppingPlace(stopId, stoppingPlaceType);
4724  if (bs == 0) {
4725  errorMsg = "The " + toString(stoppingPlaceType) + " '" + stopId + "' is not known for vehicle '" + getID() + "'";
4726  return false;
4727  }
4728  newStop.duration = duration;
4729  newStop.until = until;
4730  newStop.triggered = triggered;
4731  newStop.containerTriggered = containerTriggered;
4732  newStop.parking = parking;
4733  newStop.index = STOP_INDEX_FIT;
4734  newStop.lane = bs->getLane().getID();
4735  newStop.endPos = bs->getEndLanePosition();
4736  newStop.startPos = bs->getBeginLanePosition();
4737  if (triggered) {
4738  newStop.parametersSet |= STOP_TRIGGER_SET;
4739  }
4740  if (containerTriggered) {
4742  }
4743  if (parking) {
4744  newStop.parametersSet |= STOP_PARKING_SET;
4745  }
4746  const bool result = addStop(newStop, errorMsg);
4747  if (myLane != 0) {
4748  updateBestLanes(true);
4749  }
4750  return result;
4751 }
4752 
4753 
4754 bool
4756  if (isStopped()) {
4760  }
4764  }
4765  // we have waited long enough and fulfilled any passenger-requirements
4766  if (myStops.front().busstop != 0) {
4767  // inform bus stop about leaving it
4768  myStops.front().busstop->leaveFrom(this);
4769  }
4770  // we have waited long enough and fulfilled any container-requirements
4771  if (myStops.front().containerstop != 0) {
4772  // inform container stop about leaving it
4773  myStops.front().containerstop->leaveFrom(this);
4774  }
4775  if (myStops.front().parkingarea != 0) {
4776  // inform parking area about leaving it
4777  myStops.front().parkingarea->leaveFrom(this);
4778  }
4779  // the current stop is no longer valid
4781  MSDevice_Vehroutes* vehroutes = static_cast<MSDevice_Vehroutes*>(getDevice(typeid(MSDevice_Vehroutes)));
4782  if (vehroutes != 0) {
4783  vehroutes->stopEnded(myStops.front());
4784  }
4785  if (MSStopOut::active()) {
4786  MSStopOut::getInstance()->stopEnded(this, myStops.front());
4787  }
4788  if (myStops.front().collision && MSLane::getCollisionAction() == MSLane::COLLISION_ACTION_WARN) {
4789  myCollisionImmunity = TIME2STEPS(5); // leave the conflict area
4790  }
4791  myStops.pop_front();
4792  // do not count the stopping time towards gridlock time.
4793  // Other outputs use an independent counter and are not affected.
4794  myWaitingTime = 0;
4795  // maybe the next stop is on the same edge; let's rebuild best lanes
4796  updateBestLanes(true);
4797  // continue as wished...
4799  return true;
4800  }
4801  return false;
4802 }
4803 
4804 
4807  return myStops.front();
4808 }
4809 
4810 
4813  if (myInfluencer == 0) {
4814  myInfluencer = new Influencer();
4815  }
4816  return *myInfluencer;
4817 }
4818 
4819 
4820 const MSVehicle::Influencer*
4822  return myInfluencer;
4823 }
4824 
4825 
4826 double
4828  if (myInfluencer != 0 && myInfluencer->getOriginalSpeed() != -1) {
4829  return myInfluencer->getOriginalSpeed();
4830  }
4831  return myState.mySpeed;
4832 }
4833 
4834 
4835 int
4837  if (hasInfluencer()) {
4839  MSNet::getInstance()->getCurrentTimeStep(),
4840  myLane->getEdge(),
4841  getLaneIndex(),
4842  state);
4843  }
4844  return state;
4845 }
4846 
4847 
4848 void
4850  myCachedPosition = xyPos;
4851 }
4852 
4853 #endif
4854 
4855 bool
4857  return myInfluencer != 0 && myInfluencer->isRemoteControlled();
4858 }
4859 
4860 
4861 bool
4864 }
4865 
4866 
4867 bool
4868 MSVehicle::keepClear(const MSLink* link) const {
4869  if (link->hasFoes() && link->keepClear() /* && item.myLink->willHaveBlockedFoe()*/) {
4870  const double keepClearTime = getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_IGNORE_KEEPCLEAR_TIME, -1);
4871  //std::cout << SIMTIME << " veh=" << getID() << " keepClearTime=" << keepClearTime << " accWait=" << getAccumulatedWaitingSeconds() << " keepClear=" << (keepClearTime < 0 || getAccumulatedWaitingSeconds() < keepClearTime) << "\n";
4872  return keepClearTime < 0 || getAccumulatedWaitingSeconds() < keepClearTime;
4873  } else {
4874  return false;
4875  }
4876 }
4877 
4878 
4879 bool
4880 MSVehicle::ignoreRed(const MSLink* link, bool canBrake) const {
4882  return true;
4883  }
4884  const double ignoreRedTime = getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_DRIVE_AFTER_RED_TIME, -1);
4885 #ifdef DEBUG_IGNORE_RED
4886  if (DEBUG_COND) {
4887  std::cout << SIMTIME << " veh=" << getID() << " link=" << link->getViaLaneOrLane()->getID() << " state=" << toString(link->getState()) << "\n";
4888  }
4889 #endif
4890  if (ignoreRedTime < 0) {
4891  return false;
4892  } else if (link->haveYellow()) {
4893  // always drive at yellow when ignoring red
4894  return true;
4895  } else if (link->haveRed()) {
4896  assert(link->getTLLogic() != 0);
4897  const double redDuration = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep() - link->getLastStateChange());
4898 #ifdef DEBUG_IGNORE_RED
4899  if (DEBUG_COND) {
4900  std::cout
4901  // << SIMTIME << " veh=" << getID() << " link=" << link->getViaLaneOrLane()->getID()
4902  << " ignoreRedTime=" << ignoreRedTime
4903  << " spentRed=" << redDuration
4904  << " canBrake=" << canBrake << "\n";
4905  }
4906 #endif
4907  // when activating ignoreRed behavior, vehicles will always drive if they cannot brake
4908  return !canBrake || ignoreRedTime > redDuration;
4909  } else {
4910  return false;
4911  }
4912 }
4913 
4914 
4915 bool
4917  // either on an internal lane that was entered via minor link
4918  // or on approach to minor link below visibility distance
4919  if (myLane == 0) {
4920  return false;
4921  }
4922  if (myLane->getEdge().isInternal()) {
4923  return !myLane->getIncomingLanes().front().viaLink->havePriority();
4924  } else if (myLFLinkLanes.size() > 0 && myLFLinkLanes.front().myLink != 0) {
4925  MSLink* link = myLFLinkLanes.front().myLink;
4926  return !link->havePriority() && myLFLinkLanes.front().myDistance <= link->getFoeVisibilityDistance();
4927  }
4928  return false;
4929 }
4930 
4931 
4932 void
4935  // here starts the vehicle internal part (see loading)
4936  std::vector<std::string> internals;
4937  internals.push_back(toString(myDeparture));
4938  internals.push_back(toString(distance(myRoute->begin(), myCurrEdge)));
4939  internals.push_back(toString(myDepartPos));
4940  internals.push_back(toString(myWaitingTime));
4941  internals.push_back(toString(myLastActionTime));
4942  out.writeAttr(SUMO_ATTR_STATE, internals);
4946  // save stops and parameters
4947  for (std::list<Stop>::const_iterator it = myStops.begin(); it != myStops.end(); ++it) {
4948  it->write(out);
4949  }
4950  myParameter->writeParams(out);
4951  for (std::vector<MSDevice*>::const_iterator dev = myDevices.begin(); dev != myDevices.end(); ++dev) {
4952  (*dev)->saveState(out);
4953  }
4954  out.closeTag();
4955 }
4956 
4957 void
4958 MSVehicle::loadState(const SUMOSAXAttributes& attrs, const SUMOTime offset) {
4959  if (!attrs.hasAttribute(SUMO_ATTR_POSITION)) {
4960  throw ProcessError("Error: Invalid vehicles in state (may be a meso state)!");
4961  }
4962  int routeOffset;
4963  std::istringstream bis(attrs.getString(SUMO_ATTR_STATE));
4964  bis >> myDeparture;
4965  bis >> routeOffset;
4966  bis >> myDepartPos;
4967  bis >> myWaitingTime;
4968  bis >> myLastActionTime;
4969  if (hasDeparted()) {
4970  myCurrEdge += routeOffset;
4971  myDeparture -= offset;
4972  }
4976 
4977  // no need to reset myCachedPosition here since state loading happens directly after creation
4978 }
4979 
4980 /****************************************************************************/
const std::vector< IncomingLaneInfo > & getIncomingLanes() const
Definition: MSLane.h:752
double myPos
the stored position
Definition: MSVehicle.h:140
int getRoutePosition() const
Definition: MSVehicle.cpp:802
bool gDebugFlag1
global utility flags for debugging
Definition: StdDefs.cpp:32
bool getRespectJunctionPriority() const
Returns whether junction priority rules shall be respected.
Definition: MSVehicle.h:1399
void adaptToLeader(const std::pair< const MSVehicle *, double > leaderInfo, const double seen, DriveProcessItem *const lastLink, const MSLane *const lane, double &v, double &vLinkPass, double distToCrossing=-1) const
Definition: MSVehicle.cpp:2123
double myLatDist
The requested lateral change.
Definition: MSVehicle.h:1480
A lane area vehicles can halt at.
Definition: MSParkingArea.h:65
void adaptToLeaders(const MSLeaderInfo &ahead, double latOffset, const double seen, DriveProcessItem *const lastLink, const MSLane *const lane, double &v, double &vLinkPass) const
Definition: MSVehicle.cpp:2078
const int STOP_CONTAINER_TRIGGER_SET
const std::vector< MSTransportable * > & getTransportables() const
Returns the list of transportables using this vehicle.
const MSLane * myLastBestLanesInternalLane
Definition: MSVehicle.h:1695
The link is a partial left direction.
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
Drive process items represent bounds on the safe velocity corresponding to the upcoming links...
Definition: MSVehicle.h:1759
double getLengthWithGap() const
Get vehicle&#39;s length including the minimum gap [m].
double computeAngle() const
compute the current vehicle angle
Definition: MSVehicle.cpp:1038
static double gLateralResolution
Definition: MSGlobals.h:91
double getFuelConsumption() const
Returns fuel consumption of the current state.
Definition: MSVehicle.cpp:4168
#define DIST2SPEED(x)
Definition: SUMOTime.h:56
const std::vector< double > & getShadowFurtherLanesPosLat() const
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:260
MSLane * getLogicalPredecessorLane() const
get the most likely precedecessor lane (sorted using by_connections_to_sorter). The result is cached ...
Definition: MSLane.cpp:2256
static bool active()
Definition: MSStopOut.h:63
double getAccumulatedWaitingSeconds() const
Returns the number of seconds waited (speed was lesser than 0.1m/s) within the last millisecs...
Definition: MSVehicle.h:670
int getSignals() const
Definition: MSVehicle.h:1455
double getVehicleMaxSpeed(const SUMOVehicle *const veh) const
Returns the lane&#39;s maximum speed, given a vehicle&#39;s speed limit adaptation.
Definition: MSLane.h:475
SumoXMLTag
Numbers representing SUMO-XML - element names.
SUMOVehicleShape getGuiShape() const
Get this vehicle type&#39;s shape.
double brakeGap(const double speed) const
Returns the distance the vehicle needs to halt including driver&#39;s reaction time tau (i...
Definition: MSCFModel.h:289
void addWaiting(const MSEdge *const edge, SUMOVehicle *vehicle)
Adds a vehicle to the list of waiting vehiclse to a given edge.
double getNOxEmissions() const
Returns NOx emission of the current state.
Definition: MSVehicle.cpp:4156
bool enterLaneAtMove(MSLane *enteredLane, bool onTeleporting=false)
Update when the vehicle enters a new lane in the move step.
Definition: MSVehicle.cpp:3478
bool ignoreRed(const MSLink *link, bool canBrake) const
decide whether a red (or yellow light) may be ignore
Definition: MSVehicle.cpp:4880
SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT() const
Definition: MSVehicle.cpp:549
virtual double freeSpeed(const MSVehicle *const veh, double speed, double seen, double maxSpeed, const bool onInsertion=false) const
Computes the vehicle&#39;s safe speed without a leader.
Definition: MSCFModel.cpp:223
double getLength() const
Returns the vehicle&#39;s length.
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:607
double myAngle
the angle in radians (
Definition: MSVehicle.h:1744
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:83
SUMOTime getDeparture() const
Returns this vehicle&#39;s real departure time.
int size() const
Return the number of passengers / containers.
double getJMParam(const SumoXMLAttr attr, const double defaultValue) const
Returns the named value from the map, or the default if it is not contained there.
double getBeginLanePosition() const
Returns the begin position of this stop.
bool isRemoteControlled() const
Returns the information whether the vehicle is fully controlled via TraCI.
Definition: MSVehicle.cpp:4856
bool hasPersons() const
Returns whether persons are simulated.
Definition: MSNet.h:323
double getElectricityConsumption() const
Returns electricity consumption of the current state.
Definition: MSVehicle.cpp:4174
virtual int addLeader(const MSVehicle *veh, bool beyond, double latOffset=0)
double backPos() const
back Position of this state
Definition: MSVehicle.h:128
void remove(MSVehicle *veh)
Remove a vehicle from this transfer object.
MSEdgeWeightsStorage * myEdgeWeights
Definition: MSVehicle.h:1903
MoveReminderCont myMoveReminders
Currently relevant move reminders.
The action is due to the default of keeping right "Rechtsfahrgebot".
PositionVector getBoundingPoly() const
get bounding polygon
Definition: MSVehicle.cpp:4578
#define SPEED2DIST(x)
Definition: SUMOTime.h:54
const ConstMSEdgeVector & getEdges() const
Definition: MSRoute.h:127
The action is done to help someone else.
static int nextLinkPriority(const std::vector< MSLane *> &conts)
get a numerical value for the priority of the upcoming link
Definition: MSVehicle.cpp:3993
SUMOTime getWaitingTime() const
Returns the SUMOTime waited (speed was lesser than 0.1m/s)
Definition: MSVehicle.h:628
const MSEdge * getNextNormal() const
Returns the lane&#39;s follower if it is an internal lane, the edge of the lane otherwise.
Definition: MSLane.cpp:1611
const MSEdge * myLastBestLanesEdge
Definition: MSVehicle.h:1694
std::string containerstop
(Optional) container stop if one is assigned to the stop
LaneChangeMode
modes for resolving conflicts between external control (traci) and vehicle control over lane changing...
Definition: MSVehicle.h:1196
void enterLaneAtInsertion(MSLane *enteredLane, double pos, double speed, double posLat, MSMoveReminder::Notification notification)
Update when the vehicle enters a new lane in the emit step.
Definition: MSVehicle.cpp:3566
MSAbstractLaneChangeModel * myLaneChangeModel
Definition: MSVehicle.h:1692
void append(const PositionVector &v, double sameThreshold=2.0)
bool myAmOnNet
Whether the vehicle is on the network (not parking, teleported, vaporized, or arrived) ...
Definition: MSVehicle.h:1733
LaneChangeMode myRightDriveLC
changing to the rightmost lane
Definition: MSVehicle.h:1518
virtual bool hasPedestrians(const MSLane *lane)
whether the given lane has pedestrians on it
Definition: MSPModel.h:90
std::pair< MSVehicle *const, double > getOppositeLeader(const MSVehicle *ego, double dist, bool oppositeDir) const
Definition: MSLane.cpp:3052
std::vector< std::vector< LaneQ > > myBestLanes
Definition: MSVehicle.h:1702
bool parking
whether the vehicle is removed from the net while stopping
std::vector< MSLane * > myFurtherLanes
The information into which lanes the vehicle laps into.
Definition: MSVehicle.h:1725
State myState
This Vehicles driving state (pos and speed)
Definition: MSVehicle.h:1679
bool hasDeparted() const
Returns whether this vehicle has already departed.
double myOriginalSpeed
The velocity before influence.
Definition: MSVehicle.h:1477
void release() const
deletes the route if there are no further references to it
Definition: MSRoute.cpp:104
#define ACCEL2SPEED(x)
Definition: SUMOTime.h:60
Stop & getNextStop()
Definition: MSVehicle.cpp:4806
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition: MSNet.cpp:863
A lane area vehicles can halt at.
bool replaceParkingArea(MSParkingArea *parkingArea, std::string &errorMsg)
replace the current parking area stop with a new stop with merge duration
Definition: MSVehicle.cpp:1247
void enter(SUMOVehicle *what, double beg, double end)
Called if a vehicle enters this stop.
DriveItemVector myLFLinkLanes
Definition: MSVehicle.h:1814
bool resumeFromStopping()
Definition: MSVehicle.cpp:4755
bool myAmRegisteredAsWaitingForPerson
Whether this vehicle is registered as waiting for a person (for deadlock-recognition) ...
Definition: MSVehicle.h:1736
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:564
SUMOTime duration
The stopping duration.
ArrivalLaneDefinition arrivalLaneProcedure
Information how the vehicle shall choose the lane to arrive on.
The speed is given.
int bestLaneOffset
The (signed) number of lanes to be crossed to get to the lane which allows to continue the drive...
Definition: MSVehicle.h:811
virtual double minNextSpeed(double speed, const MSVehicle *const veh=0) const
Returns the minimum speed given the current speed (depends on the numerical update scheme and its ste...
Definition: MSCFModel.cpp:210
double myTimeLoss
the time loss in seconds due to driving with less than maximum speed
Definition: MSVehicle.h:1676
void setBlinkerInformation()
sets the blue flashing light for emergency vehicles
Definition: MSVehicle.cpp:4260
SUMOTime myLastActionTime
Action offset (actions are taken at time myActionOffset + N*getActionStepLength()) Initialized to 0...
Definition: MSVehicle.h:1685
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition: Position.h:249
void addContainer(MSTransportable *container)
Adds a container.
Definition: MSVehicle.cpp:4201
SUMOTime getMemorySize() const
Definition: MSVehicle.h:196
The vehicle arrived at a junction.
virtual double followSpeed(const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel) const =0
Computes the vehicle&#39;s follow speed (no dawdling)
int getShadowDirection() const
return the direction in which the current shadow lane lies
int getPersonNumber() const
Returns the number of persons.
Definition: MSVehicle.cpp:4247
double getManeuverDist() const
Returns the remaining unblocked distance for the current maneuver. (only used by sublane model) ...
std::pair< const MSVehicle *const, double > getLeader(double dist=0) const
Returns the leader of the vehicle looking for a fixed distance.
Definition: MSVehicle.cpp:4098
const SUMOVehicleParameter::Stop pars
The stop parameter.
Definition: MSVehicle.h:917
int myRoutingMode
routing mode (see TraCIConstants.h)
Definition: MSVehicle.h:1529
SUMOTime duration
The stopping duration.
Definition: MSVehicle.h:919
DepartLaneDefinition departLaneProcedure
Information how the vehicle shall choose the lane to depart from.
void updateTimeLoss(double vNext)
Updates the vehicle&#39;s time loss.
Definition: MSVehicle.cpp:2707
std::string getDescription() const
get a short description for showing in the gui
Definition: MSVehicle.cpp:577
bool onFurtherEdge(const MSEdge *edge) const
whether this vehicle has its back (and no its front) on the given edge
Definition: MSVehicle.cpp:4614
void enter(SUMOVehicle *what, double beg, double end)
Called if a vehicle enters this stop.
const double SUMO_const_laneWidth
Definition: StdDefs.h:49
void planMove(const SUMOTime t, const MSLeaderInfo &ahead, const double lengthsInFront)
Compute safe velocities for the upcoming lanes based on positions and speeds from the last time step...
Definition: MSVehicle.cpp:1637
The position is given.
The car-following model abstraction.
Definition: MSCFModel.h:59
MSParkingArea * parkingarea
(Optional) parkingArea if one is assigned to the stop
Definition: MSVehicle.h:913
MSStoppingPlace * busstop
(Optional) bus stop if one is assigned to the stop
Definition: MSVehicle.h:909
double getPositionOnLane() const
Get the vehicle&#39;s position along the lane.
Definition: MSVehicle.h:402
bool triggered
whether an arriving person lets the vehicle continue
Definition: MSVehicle.h:921
bool myConsiderMaxAcceleration
Whether the maximum acceleration shall be regarded.
Definition: MSVehicle.h:1489
static double rand(std::mt19937 *rng=0)
Returns a random real number in [0, 1)
Definition: RandHelper.h:64
const SUMOVehicleParameter & getParameter() const
Returns the vehicle&#39;s parameter (including departure definition)
#define INVALID
double myPosLat
the stored lateral position
Definition: MSVehicle.h:146
int getBestLaneOffset() const
Definition: MSVehicle.cpp:4055
double myArrivalPos
The position on the destination lane where the vehicle stops.
The link is a 180 degree turn.
virtual void clear()
discard all information
bool reached
Information whether the stop has been reached.
Definition: MSVehicle.h:925
Notification
Definition of a vehicle state.
double getLastFreePos(const SUMOVehicle &forVehicle) const
Returns the last free position on this stop.
double getDistanceBetween(double fromPos, double toPos, const MSEdge *fromEdge, const MSEdge *toEdge, bool includeInternal=true) const
Compute the distance between 2 given edges on this route, including the length of internal lanes...
Definition: MSRoute.cpp:280
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:59
std::vector< const MSLane * > getOutgoingLanes() const
get the list of outgoing lanes
Definition: MSLane.cpp:2347
Wants go to the right.
virtual MSVehicle * removeVehicle(MSVehicle *remVehicle, MSMoveReminder::Notification notification, bool notify=true)
Definition: MSLane.cpp:1944
MSDevice_Transportable * myPersonDevice
The passengers this vehicle may have.
Definition: MSVehicle.h:1716
#define STOPPING_PLACE_OFFSET
Definition: MSVehicle.cpp:102
Changes the wished vehicle speed / lanes.
Definition: MSVehicle.h:1329
static MSDevice_Transportable * buildVehicleDevices(SUMOVehicle &v, std::vector< MSDevice *> &into, const bool isContainer)
Build devices for the given vehicle, if needed.
lane can change or stay
double lateralDistanceToLane(const int offset) const
Get the minimal lateral distance required to move fully onto the lane at given offset.
Definition: MSVehicle.cpp:4445
const std::vector< MSLane * > * allowedLanes(const MSEdge &destination, SUMOVehicleClass vclass=SVC_IGNORING) const
Get the allowed lanes to reach the destination-edge.
Definition: MSEdge.cpp:295
bool addTraciStopAtStoppingPlace(const std::string &stopId, const SUMOTime duration, const SUMOTime until, const bool parking, const bool triggered, const bool containerTriggered, const SumoXMLTag stoppingPlaceType, std::string &errorMsg)
Definition: MSVehicle.cpp:4675
bool myRespectJunctionPriority
Whether the junction priority rules are respected.
Definition: MSVehicle.h:1495
double getLeaveSpeed() const
Definition: MSVehicle.h:1806
virtual VehicleVariables * createVehicleVariables() const
Returns model specific values which are stored inside a vehicle and must be used with casting...
Definition: MSCFModel.h:194
void registerEmergencyStop()
register emergency stop
virtual double maxNextSpeed(double speed, const MSVehicle *const veh) const
Returns the maximum speed given the current speed.
Definition: MSCFModel.cpp:204
bool isRoundabout() const
Definition: MSEdge.h:619
State & operator=(const State &state)
Assignment operator.
Definition: MSVehicle.cpp:133
const std::vector< MSLane * > & getLanes() const
Returns this edge&#39;s lanes.
Definition: MSEdge.h:167
double angleTo2D(const Position &other) const
returns the angle in the plane of the vector pointing from here to the other position ...
Definition: Position.h:259
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:167
T MAX2(T a, T b)
Definition: StdDefs.h:73
vehicle doesn&#39;t want to change
Definition: MSVehicle.h:224
TraciLaneChangePriority
modes for prioritizing traci lane change requests
Definition: MSVehicle.h:1204
SUMOTime DELTA_T
Definition: SUMOTime.cpp:39
double getLength() const
Returns the lane&#39;s length.
Definition: MSLane.h:497
virtual const VehCont & getVehiclesSecure() const
Returns the vehicles container; locks it for microsimulation.
Definition: MSLane.h:392
const PositionVector & getShape() const
Returns this lane&#39;s shape.
Definition: MSLane.h:439
const MSRoute * myRoute
This vehicle&#39;s route.
#define DEBUG_COND
Definition: MSVehicle.cpp:99
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition: Named.h:58
PositionVector getBoundingBox() const
get bounding rectangle
Definition: MSVehicle.cpp:4565
bool isLinkEnd(MSLinkCont::const_iterator &i) const
Definition: MSLane.cpp:1758
const MSRoute & getRoute() const
Returns the current route.
bool isStoppedOnLane() const
Definition: MSVehicle.cpp:1337
MSLink * getLinkTo(const MSLane *) const
returns the link to the given lane or 0, if it is not connected
Definition: MSLane.cpp:1881
The vehicle got vaporized.
Position getPosition(const double offset=0) const
Return current position (x/y, cartesian)
Definition: MSVehicle.cpp:901
PositionVector reverse() const
reverse position vector
double rotationAtOffset(double pos) const
Returns the rotation at the given length.
SUMOTime until
The time at which the vehicle may continue its journey.
bool addStop(const SUMOVehicleParameter::Stop &stopPar, std::string &errorMsg, SUMOTime untilOffset=0, bool collision=false, MSRouteIterator *searchStart=0)
Adds a stop.
Definition: MSVehicle.cpp:1103
bool checkActionStep(const SUMOTime t)
Returns whether the vehicle is supposed to take action in the current simulation step Updates myActio...
Definition: MSVehicle.cpp:1604
double getRightSideOnLane() const
Get the vehicle&#39;s lateral position on the lane:
Definition: MSVehicle.cpp:4331
void adaptBestLanesOccupation(int laneIndex, double density)
update occupation from MSLaneChanger
Definition: MSVehicle.cpp:4065
WaitingTimeCollector myWaitingTimeCollector
Definition: MSVehicle.h:1673
const int STOP_INDEX_FIT
This is an uncontrolled, right-before-left link.
render as a sedan passenger vehicle ("Stufenheck")
void removeWaiting(const MSEdge *const edge, SUMOVehicle *vehicle)
Removes a vehicle from the list of waiting vehicles to a given edge.
bool executeMove()
Executes planned vehicle movements with regards to right-of-way.
Definition: MSVehicle.cpp:2819
double getSafeFollowSpeed(const std::pair< const MSVehicle *, double > leaderInfo, const double seen, const MSLane *const lane, double distToCrossing) const
compute safe speed for following the given leader
Definition: MSVehicle.cpp:2225
std::vector< const MSEdge * > ConstMSEdgeVector
Definition: MSEdge.h:78
std::set< std::string > awaitedPersons
IDs of persons the vehicle has to wait for until departing.
static double computeNoise(SUMOEmissionClass c, double v, double a)
Returns the noise produced by the a vehicle of the given type at the given speed. ...
SUMOTime myMemorySize
the maximal memory to store
Definition: MSVehicle.h:207
#define RAD2DEG(x)
Definition: GeomHelper.h:45
ArrivalSpeedDefinition arrivalSpeedProcedure
Information how the vehicle&#39;s end speed shall be chosen.
int myArrivalLane
The destination lane where the vehicle stops.
const SUMOVehicleParameter * myParameter
This vehicle&#39;s parameter.
const std::string & getID() const
Returns the id.
Definition: Named.h:65
#define TIME2STEPS(x)
Definition: SUMOTime.h:66
double myLastCoveredDist
Definition: MSVehicle.h:160
const std::vector< MSMoveReminder *> & getMoveReminders() const
Return the list of this lane&#39;s move reminders.
Definition: MSLane.h:232
The base class for microscopic and mesoscopic vehicles.
Definition: MSBaseVehicle.h:55
#define TS
Definition: SUMOTime.h:51
bool myHaveToWaitOnNextLink
Definition: MSVehicle.h:1741
A storage for edge travel times and efforts.
int getSpeedMode() const
return the current speed mode
Definition: MSVehicle.cpp:283
SUMOTime timeToBoardNextPerson
The time at which the vehicle is able to board another person.
Definition: MSVehicle.h:931
double nextOccupation
As occupation, but without the first lane.
Definition: MSVehicle.h:809
double length
The overall length which may be driven when using this lane without a lane change.
Definition: MSVehicle.h:803
Wants go to the left.
This is an uncontrolled, all-way stop link.
The action is due to the wish to be faster (tactical lc)
bool wasRemoteControlled(SUMOTime lookBack=DELTA_T) const
Returns the information whether the vehicle is fully controlled via TraCI within the lookBack time...
Definition: MSVehicle.cpp:4862
#define SPEED2ACCEL(x)
Definition: SUMOTime.h:62
double getWidth() const
Returns the lane&#39;s width.
Definition: MSLane.h:513
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list...
bool hasArrived() const
Returns whether this vehicle has already arived (reached the arrivalPosition on its final edge) ...
Definition: MSVehicle.cpp:723
used by the sublane model
void enterLaneAtLaneChange(MSLane *enteredLane)
Update when the vehicle enters a new lane in the laneChange step.
Definition: MSVehicle.cpp:3516
Position getPositionAlongBestLanes(double offset) const
Return the (x,y)-position, which the vehicle would reach if it continued along its best continuation ...
Definition: MSVehicle.cpp:933
This is an uncontrolled, zipper-merge link.
The link is a (hard) left direction.
std::string parkingarea
(Optional) parking area if one is assigned to the stop
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:199
The simulated network and simulation perfomer.
Definition: MSNet.h:90
void planMoveInternal(const SUMOTime t, MSLeaderInfo ahead, DriveItemVector &lfLinks, double &myStopDist) const
Definition: MSVehicle.cpp:1706
The speed is given.
The car-following model and parameter.
Definition: MSVehicleType.h:72
void checkLinkLeader(const MSLink *link, const MSLane *lane, double seen, DriveProcessItem *const lastLink, double &v, double &vLinkPass, double &vLinkWait, bool &setRequest, bool isShadowLink=false) const
checks for link leaders on the given link
Definition: MSVehicle.cpp:2159
virtual void saveState(OutputDevice &out)
Saves the (common) state of a vehicle.
bool containerTriggered
whether an arriving container lets the vehicle continue
Definition: MSVehicle.h:923
WaitingTimeCollector(SUMOTime memory=MSGlobals::gWaitingTimeMemory)
Constructor.
Definition: MSVehicle.cpp:164
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:3674
bool isVaporizing() const
Returns whether vehicles on this edge shall be vaporized.
Definition: MSEdge.h:371
bool isStoppedInRange(double pos) const
return whether the given position is within range of the current stop
Definition: MSVehicle.cpp:1370
#define SIMTIME
Definition: SUMOTime.h:71
MSCFModel::VehicleVariables * myCFVariables
The per vehicle variables of the car following model.
Definition: MSVehicle.h:1906
double implicitDeltaPosRemote(const MSVehicle *veh)
return the change in longitudinal position that is implicit in the new remote position ...
Definition: MSVehicle.cpp:533
The lane is given.
bool isVehicleSpecific() const
Returns whether this type belongs to a single vehicle only (was modified)
bool isFrontOnLane(const MSLane *lane) const
Returns the information whether the front of the vehicle is on the given lane.
Definition: MSVehicle.cpp:3202
int getLaneIndex() const
Definition: MSVehicle.cpp:4314
virtual std::string getString(int id) const =0
Returns the string-value of the named (by its enum-value) attribute.
double getBackPositionOnLane() const
Get the vehicle&#39;s position relative to its current lane.
Definition: MSVehicle.h:431
Right blinker lights are switched on.
Definition: MSVehicle.h:1162
std::vector< Stop > stops
List of the stops the vehicle will make, TraCI may add entries here.
virtual MSTransportableControl & getContainerControl()
Returns the container control.
Definition: MSNet.cpp:776
void writeParams(OutputDevice &out) const
const ConstMSEdgeVector getStopEdges() const
Returns the list of still pending stop edges.
Definition: MSVehicle.cpp:1594
static CollisionAction getCollisionAction()
Definition: MSLane.h:1069
The vehicles starts to stop.
Definition: MSNet.h:500
double getMaxAccel() const
Get the vehicle type&#39;s maximum acceleration [m/s^2].
Definition: MSCFModel.h:203
Needs to stay on the current lane.
double getMaxSpeed() const
Returns the maximum speed.
void calculateArrivalParams()
(Re-)Calculates the arrival position and lane from the vehicle parameters
std::vector< std::pair< SUMOTime, int > > myLaneTimeLine
The lane usage time line to apply.
Definition: MSVehicle.h:1474
double influenceSpeed(SUMOTime currentTime, double speed, double vSafe, double vMin, double vMax)
Applies stored velocity information on the speed to use.
Definition: MSVehicle.cpp:304
The state of a link.
double changeRequestRemainingSeconds(const SUMOTime currentTime) const
Return the remaining number of seconds of the current laneTimeLine assuming one exists.
Definition: MSVehicle.cpp:430
std::vector< double > myFurtherLanesPosLat
lateral positions on further lanes
Definition: MSVehicle.h:1727
bool signalSet(int which) const
Returns whether the given signal is on.
Definition: MSVehicle.h:1240
bool getEmergencyBrakeRedLight() const
Returns whether red lights shall be a reason to brake.
Definition: MSVehicle.h:1407
WaitingTimeCollector & operator=(const WaitingTimeCollector &wt)
Assignment operator.
Definition: MSVehicle.cpp:169
bool isInternal() const
Definition: MSLane.cpp:1774
std::string busstop
(Optional) bus stop if one is assigned to the stop
bool operator!=(const State &state)
Operator !=.
Definition: MSVehicle.cpp:145
static std::vector< MSTransportable * > myEmptyTransportableVector
Definition: MSVehicle.h:1710
double getDistanceToPosition(double destPos, const MSEdge *destEdge) const
Definition: MSVehicle.cpp:4081
double departSpeed
(optional) The initial speed of the vehicle
A road/street connecting two junctions.
Definition: MSEdge.h:80
bool isOnRoad() const
Returns the information whether the vehicle is on a road (is simulated)
Definition: MSVehicle.h:586
void leaveLane(const MSMoveReminder::Notification reason, const MSLane *approachedLane=0)
Update of members if vehicle leaves a new lane in the lane change step or at arrival.
Definition: MSVehicle.cpp:3624
void setSpeedTimeLine(const std::vector< std::pair< SUMOTime, double > > &speedTimeLine)
Sets a new velocity timeline.
Definition: MSVehicle.cpp:266
double getLatOffset(const MSLane *lane) const
Get the offset that that must be added to interpret myState.myPosLat for the given lane...
Definition: MSVehicle.cpp:4375
double getEndLanePosition() const
Returns the end position of this stop.
The vehicle changes lanes (micro only)
LaneChangeModel getLaneChangeModel() const
MSLane * lane
The described lane.
Definition: MSVehicle.h:801
double getBruttoVehLenSum() const
Returns the sum of lengths of vehicles, including their minGaps, which were on the lane during the la...
Definition: MSLane.h:899
void setSpeedMode(int speedMode)
Sets speed-constraining behaviors.
Definition: MSVehicle.cpp:438
static double naviDegree(const double angle)
Definition: GeomHelper.cpp:186
const MSCFModel & getCarFollowModel() const
Returns the vehicle&#39;s car following model definition.
Definition: MSVehicle.h:882
const int STOP_START_SET
double getCO2Emissions() const
Returns CO2 emission of the current state.
Definition: MSVehicle.cpp:4138
Left blinker lights are switched on.
Definition: MSVehicle.h:1164
double myDepartPos
The real depart position.
DepartSpeedDefinition departSpeedProcedure
Information how the vehicle&#39;s initial speed shall be chosen.
void setSublaneChange(double latDist)
Sets a new sublane-change request.
Definition: MSVehicle.cpp:278
void setAngle(double angle, bool straightenFurther=false)
Set a custom vehicle angle in rad, optionally updates furtherLanePosLat.
Definition: MSVehicle.cpp:1024
blocked in all directions
const MSCFModel & getCarFollowModel() const
Returns the vehicle type&#39;s car following model definition (const version)
The vehicle got a new route.
Definition: MSNet.h:494
Position validatePosition(Position result, double offset=0) const
ensure that a vehicle-relative position is not invalid
Definition: MSVehicle.cpp:995
vehicle want&#39;s to change to right lane
Definition: MSVehicle.h:228
void updateState(double vNext)
updates the vehicles state, given a next value for its speed. This value can be negative in case of t...
Definition: MSVehicle.cpp:3000
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:55
#define DIST_TO_STOPLINE_EXPECT_PRIORITY
Definition: MSVehicle.cpp:107
double getLateralOverlap() const
return the amount by which the vehicle extends laterally outside it&#39;s primary lane ...
Definition: MSVehicle.cpp:4495
The action is urgent (to be defined by lc-model)
double updateFurtherLanes(std::vector< MSLane *> &furtherLanes, std::vector< double > &furtherLanesPosLat, const std::vector< MSLane *> &passedLanes)
update a vector of further lanes and return the new backPos
Definition: MSVehicle.cpp:3054
Representation of a vehicle.
Definition: SUMOVehicle.h:66
SUMOTime myLastRemoteAccess
Definition: MSVehicle.h:1507
render as a hatchback passenger vehicle ("Fliessheck")
Stores the waiting intervals over the previous seconds (memory is to be specified in ms...
Definition: MSVehicle.h:168
static bool gCheckRoutes
Definition: MSGlobals.h:85
double startPos
The stopping position start.
DepartPosDefinition departPosProcedure
Information how the vehicle shall choose the departure position.
Encapsulated SAX-Attributes.
std::set< std::string > awaitedContainers
IDs of containers the vehicle has to wait for until departing.
static MSPModel * getModel()
Definition: MSPModel.cpp:65
SUMOTime myCollisionImmunity
amount of time for which the vehicle is immune from collisions
Definition: MSVehicle.h:1750
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition: MSNet.cpp:768
void adaptLeaveSpeed(const double v)
Definition: MSVehicle.h:1799
double implicitSpeedRemote(const MSVehicle *veh, double oldSpeed)
return the speed that is implicit in the new remote position
Definition: MSVehicle.cpp:518
ChangeRequest
Requests set via TraCI.
Definition: MSVehicle.h:222
std::string chargingStation
(Optional) charging station if one is assigned to the stop
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:45
SUMOTime getActionStepLength() const
Returns the vehicle&#39;s action step length in millisecs, i.e. the interval between two action points...
Definition: MSVehicle.h:508
double getCenterOnEdge() const
Definition: MSLane.h:968
MSRouteIterator edge
The edge in the route to stop at.
Definition: MSVehicle.h:905
TraciLaneChangePriority myTraciLaneChangePriority
flags for determining the priority of traci lane change requests
Definition: MSVehicle.h:1523
double posLat() const
Lateral Position of this state (m relative to the centerline of the lane).
Definition: MSVehicle.h:123
A list of positions.
void updateBestLanes(bool forceRebuild=false, const MSLane *startLane=0)
computes the best lanes to use in order to continue the route
Definition: MSVehicle.cpp:3692
bool replaceRoute(const MSRoute *route, bool onInit=false, int offset=0, bool addStops=true, bool removeStops=true)
Replaces the current route by the given one.
Definition: MSVehicle.cpp:732
static void clear()
Clears the dictionary.
Definition: MSEdge.cpp:783
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the best sequence of lanes to continue the route starting at myLane.
Definition: MSVehicle.cpp:4026
void registerOneWaiting(const bool isPerson)
increases the count of vehicles waiting for a transport to allow recognition of person / container re...
Position myCachedPosition
Definition: MSVehicle.h:1752
const MSEdge * getEdge() const
Returns the edge the vehicle is currently at.
double getSpaceTillLastStanding(const MSLane *l, bool &foundStopped) const
Definition: MSVehicle.cpp:3208
const MSLeaderInfo & getLastVehicleInformation(const MSVehicle *ego, double latOffset, double minPos=0, bool allowCached=true) const
Returns the last vehicles on the lane.
Definition: MSLane.cpp:968
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:306
const std::set< MSTransportable * > & getPersons() const
Returns this edge&#39;s persons set.
Definition: MSEdge.h:176
double getCenterOnEdge(const MSLane *lane=0) const
Get the vehicle&#39;s lateral position on the edge of the given lane (or its current edge if lane == 0) ...
Definition: MSVehicle.cpp:4343
double currentLength
The length which may be driven on this lane.
Definition: MSVehicle.h:805
int getVehicleNumber() const
Returns the number of vehicles on this lane (for which this lane is responsible)
Definition: MSLane.h:365
bool triggered
whether an arriving person lets the vehicle continue
const std::vector< MSLane * > & getFurtherLanes() const
Definition: MSVehicle.h:780
std::list< Stop > myStops
The vehicle&#39;s list of stops.
Definition: MSVehicle.h:1713
ConstMSEdgeVector::const_iterator MSRouteIterator
Definition: MSRoute.h:64
const int STOP_INDEX_END
void removeVType(const MSVehicleType *vehType)
bool hasContainers() const
Returns whether containers are simulated.
Definition: MSNet.h:339
int parametersSet
Information for the output which parameter were set.
int getCapacity() const
Returns the area capacity.
bool collision
Whether this stop was triggered by a collision.
Definition: MSVehicle.h:935
bool myConsiderMaxDeceleration
Whether the maximum deceleration shall be regarded.
Definition: MSVehicle.h:1492
#define STEPS2TIME(x)
Definition: SUMOTime.h:64
MSLane * myLane
The lane the vehicle is on.
Definition: MSVehicle.h:1690
bool myAmRegisteredAsWaitingForContainer
Whether this vehicle is registered as waiting for a container (for deadlock-recognition) ...
Definition: MSVehicle.h:1739
bool loadAnyWaiting(MSEdge *edge, MSVehicle *vehicle, MSVehicle::Stop *stop)
load any applicable containers Loads any container that is waiting on that edge for the given vehicle...
void getSubLanes(const MSVehicle *veh, double latOffset, int &rightmost, int &leftmost) const
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic, in MSLink and GNEInternalLane.
Influencer * myInfluencer
An instance of a velocity/lane influencing instance; built in "getInfluencer".
Definition: MSVehicle.h:1910
void resetRoutePosition(int index)
Definition: MSVehicle.cpp:808
std::vector< LaneQ >::iterator myCurrentLaneInBestLanes
Definition: MSVehicle.h:1707
void postProcessRemoteControl(MSVehicle *v)
Definition: MSVehicle.cpp:483
void processTraCISpeedControl(double vSafe, double &vNext)
Check for speed advices from the traci client and adjust the speed vNext in the current (euler) / aft...
Definition: MSVehicle.cpp:2449
double getDeltaPos(double accel)
calculates the distance covered in the next integration step given an acceleration and assuming the c...
Definition: MSVehicle.cpp:2248
void forceVehicleInsertion(MSVehicle *veh, double pos, MSMoveReminder::Notification notification, double posLat=0)
Inserts the given vehicle at the given position.
Definition: MSLane.cpp:940
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:253
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself ...
Definition: MSEdge.cpp:690
bool keepClear(const MSLink *link) const
decide whether the given link must be kept clear
Definition: MSVehicle.cpp:4868
double getMaxSpeed() const
Get vehicle&#39;s maximum speed [m/s].
double getHarmonoise_NoiseEmissions() const
Returns noise emissions of the current state.
Definition: MSVehicle.cpp:4180
MSVehicle()
invalidated default constructor
T MIN2(T a, T b)
Definition: StdDefs.h:67
void resetActionOffset(const SUMOTime timeUntilNextAction=0)
Resets the action offset for the vehicle.
Definition: MSVehicle.cpp:1613
The link is a (hard) right direction.
The action is needed to follow the route (navigational lc)
#define POSITION_EPS
Definition: config.h:175
const std::string & getID() const
returns the id of the transportable
bool replaceRouteEdges(ConstMSEdgeVector &edges, bool onInit=false, bool check=false, bool removeStops=true)
Replaces the current route by the given edges.
double getImpatience() const
Returns this vehicles impatience.
The brake lights are on.
Definition: MSVehicle.h:1168
void write(OutputDevice &dev) const
Write the current stop configuration (used for state saving)
Definition: MSVehicle.cpp:593
void addTransportable(MSTransportable *transportable)
Add a passenger.
A blue emergency light is on.
Definition: MSVehicle.h:1184
A structure representing the best lanes for continuing the current route starting at &#39;lane&#39;...
Definition: MSVehicle.h:799
void loadState(const SUMOSAXAttributes &attrs, const SUMOTime offset)
Loads the state of this vehicle from the given description.
Definition: MSVehicle.cpp:4958
void onRemovalFromNet(const MSMoveReminder::Notification reason)
Called when the vehicle is removed from the network.
Definition: MSVehicle.cpp:709
void stopStarted(const SUMOVehicle *veh, int numPersons, int numContainers)
Definition: MSStopOut.cpp:63
virtual PersonDist nextBlocking(const MSLane *lane, double minPos, double minRight, double maxLeft, double stopTime=0)
returns the next pedestrian beyond minPos that is laterally between minRight and maxLeft or 0 ...
Definition: MSPModel.h:96
double myStopDist
distance to the next stop or -1 if there is none
Definition: MSVehicle.h:1747
bool isStoppedTriggered() const
Returns whether the vehicle is on a triggered stop.
Definition: MSVehicle.cpp:1364
bool hasInfluencer() const
Definition: MSVehicle.h:1543
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:75
double endPos
The stopping position end.
double getMinGap() const
Get the free space in front of vehicles of this class.
SUMOTime collisionStopTime() const
Returns the remaining time a vehicle needs to stop due to a collision. A negative value indicates tha...
Definition: MSVehicle.cpp:1352
render as a van
double getMaxDecel() const
Get the vehicle type&#39;s maximal comfortable deceleration [m/s^2].
Definition: MSCFModel.h:211
void removeTransportable(MSTransportable *p)
Removes a transportable from this stop.
double myAcceleration
The current acceleration after dawdling in m/s.
Definition: MSVehicle.h:1722
MSLane * getOpposite() const
return the opposite direction lane for lane changing or 0
Definition: MSLane.cpp:3012
void fixPosition()
repair errors in vehicle position after changing between internal edges
Definition: MSVehicle.cpp:4073
#define DEG2RAD(x)
Definition: GeomHelper.h:44
bool myActionStep
The flag myActionStep indicates whether the current time step is an action point for the vehicle...
Definition: MSVehicle.h:1682
double myPreviousSpeed
the speed at the begin of the previous time step
Definition: MSVehicle.h:154
render as a passenger vehicle
bool isFringe() const
return whether this edge is at the fringe of the network
Definition: MSEdge.h:645
void setShadowApproachingInformation(MSLink *link) const
set approach information for the shadow vehicle
SUMOTime myWaitingTime
The time the vehicle waits (is not faster than 0.1m/s) in seconds.
Definition: MSVehicle.h:1669
void setRemoteControlled(Position xyPos, MSLane *l, double pos, double posLat, double angle, int edgeOffset, const ConstMSEdgeVector &route, SUMOTime t)
Definition: MSVehicle.cpp:459
LaneChangeMode mySpeedGainLC
lane changing to travel with higher speed
Definition: MSVehicle.h:1516
double maximumSafeStopSpeed(double gap, double currentSpeed, bool onInsertion=false, double headway=-1) const
Returns the maximum next velocity for stopping within gap.
Definition: MSCFModel.cpp:662
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:229
#define CRLL_LOOK_AHEAD
Definition: MSVehicle.cpp:104
double getMinimalArrivalSpeedEuler(double dist, double currentSpeed) const
Computes the minimal possible arrival speed after covering a given distance for Euler update...
Definition: MSCFModel.cpp:439
The link is a partial right direction.
int personNumber
The static number of persons in the vehicle when it departs (not including boarding persons) ...
LaneChangeMode myCooperativeLC
lane changing with the intent to help other vehicles
Definition: MSVehicle.h:1514
const SUMOVTypeParameter & getParameter() const
int getOccupancy() const
Returns the area occupancy.
std::vector< MSVehicle * > VehCont
Container for vehicles.
Definition: MSLane.h:89
const MSLane * lane
The lane to stop at.
Definition: MSVehicle.h:907
bool containerTriggered
whether an arriving container lets the vehicle continue
void move2side(double amount)
move position vector to side using certain ammount
static MSLinkCont::const_iterator succLinkSec(const SUMOVehicle &veh, int nRouteSuccs, const MSLane &succLinkSource, const std::vector< MSLane *> &conts)
Definition: MSLane.cpp:1825
bool allowsContinuation
Whether this lane allows to continue the drive.
Definition: MSVehicle.h:813
const waitingIntervalList & getWaitingIntervals() const
Definition: MSVehicle.h:201
void stopEnded(const SUMOVehicle *veh, const MSVehicle::Stop &stop)
Definition: MSStopOut.cpp:93
Container that holds the vehicles driving state (position+speed).
Definition: MSVehicle.h:93
Base class for objects which have an id.
Definition: Named.h:45
void saveState(OutputDevice &out)
Saves the states of a vehicle.
Definition: MSVehicle.cpp:4933
void processLaneAdvances(std::vector< MSLane *> &passedLanes, bool &moved, std::string &emergencyReason)
This method checks if the vehicle has advanced over one or several lanes along its route and triggers...
Definition: MSVehicle.cpp:2719
double getOriginalSpeed() const
Returns the originally longitudinal speed to use.
Definition: MSVehicle.cpp:337
double getLateralPositionOnLane() const
Get the vehicle&#39;s lateral position on the lane.
Definition: MSVehicle.h:439
double getRightSideOnEdge() const
Definition: MSLane.h:960
void setBrakingSignals(double vNext)
sets the braking lights on/off
Definition: MSVehicle.cpp:2676
std::string lane
The lane to stop at.
bool myEmergencyBrakeRedLight
Whether red lights are a reason to brake.
Definition: MSVehicle.h:1498
Influencer()
Constructor.
Definition: MSVehicle.cpp:242
const int STOP_END_SET
double getCOEmissions() const
Returns CO emission of the current state.
Definition: MSVehicle.cpp:4144
std::vector< std::string > via
List of the via-edges the vehicle must visit.
static MSVehicleTransfer * getInstance()
Returns the instance of this object.
void removePassedDriveItems()
Erase passed drive items from myLFLinkLanes (and unregister approaching information for corresponding...
Definition: MSVehicle.cpp:2462
virtual void drawOutsideNetwork(bool)
register vehicle for drawing while outside the network
Definition: MSVehicle.h:1669
int numExpectedContainer
The number of still expected containers.
Definition: MSVehicle.h:929
double slopeDegreeAtOffset(double pos) const
Returns the slope at the given length.
bool boardAnyWaiting(MSEdge *edge, MSVehicle *vehicle, MSVehicle::Stop *stop)
board any applicable persons Boards any people who wait on that edge for the given vehicle and remove...
void updateOccupancyAndCurrentBestLane(const MSLane *startLane)
updates LaneQ::nextOccupation and myCurrentLaneInBestLanes
Definition: MSVehicle.cpp:4009
std::pair< const MSPerson *, double > PersonDist
Definition: MSPModel.h:43
void setEmergencyBlueLight(SUMOTime currentTime)
sets the blue flashing light for emergency vehicles
Definition: MSVehicle.cpp:4302
const int STOP_PARKING_SET
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
bool addTraciStop(MSLane *const lane, const double startPos, const double endPos, const SUMOTime duration, const SUMOTime until, const bool parking, const bool triggered, const bool containerTriggered, std::string &errorMsg)
Definition: MSVehicle.cpp:4626
virtual std::string toString() const
print a debugging representation
stop for vehicles
double departPos
(optional) The position the vehicle shall depart from
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition: MSLane.cpp:1639
vehicle want&#39;s to change to left lane
Definition: MSVehicle.h:226
int numExpectedPerson
The number of still expected persons.
Definition: MSVehicle.h:927
std::pair< const MSVehicle *, double > CLeaderDist
Definition: MSLeaderInfo.h:41
The vehicle starts or ends parking.
~Influencer()
Destructor.
Definition: MSVehicle.cpp:262
virtual double getFloat(int id) const =0
Returns the double-value of the named (by its enum-value) attribute.
const int STOP_TRIGGER_SET
static double compute(const SUMOEmissionClass c, const EmissionType e, const double v, const double a, const double slope, const std::map< int, double > *param=0)
Returns the amount of the emitted pollutant given the vehicle type and state (in mg/s or ml/s for fue...
void addStops(const bool ignoreStopErrors)
Adds stops to the built vehicle.
Influencer & getInfluencer()
Returns the velocity/lane influencer.
Definition: MSVehicle.cpp:4812
Structure representing possible vehicle parameter.
DriveItemVector::iterator myNextDriveItem
iterator pointing to the next item in myLFLinkLanes
Definition: MSVehicle.h:1820
std::pair< MSVehicle *const, double > getLeaderOnConsecutive(double dist, double seen, double speed, const MSVehicle &veh, const std::vector< MSLane *> &bestLaneConts) const
Returns the immediate leader and the distance to him.
Definition: MSLane.cpp:2107
double getOppositePos(double pos) const
return the corresponding position on the opposite lane
Definition: MSLane.cpp:3021
double occupation
The overall vehicle sum on consecutive lanes which can be passed without a lane change.
Definition: MSVehicle.h:807
LaneChangeMode mySublaneLC
changing to the prefered lateral alignment
Definition: MSVehicle.h:1520
MSDevice * getDevice(const std::type_info &type) const
Returns a device of the given type if it exists or 0.
bool keepStopping(bool afterProcessing=false) const
Returns whether the vehicle is stopped and must continue to do so.
Definition: MSVehicle.cpp:1342
const MSVehicleType & getVehicleType() const
Returns the vehicle&#39;s type definition.
void removeApproachingInformation(DriveItemVector &lfLinks) const
unregister approach from all upcoming links
Definition: MSVehicle.cpp:4500
double processNextStop(double currentVelocity)
Processes stops, returns the velocity needed to reach the stop.
Definition: MSVehicle.cpp:1376
void setNoShadowPartialOccupator(MSLane *lane)
void setTentativeLaneAndPosition(MSLane *lane, double pos, double posLat=0)
set tentative lane and position during insertion to ensure that all cfmodels work (some of them requi...
Definition: MSVehicle.cpp:4321
#define M_PI
Definition: odrSpiral.cpp:40
void processLinkAproaches(double &vSafe, double &vSafeMin, double &vSafeMinDist)
This method iterates through the driveprocess items for the vehicle and adapts the given in/out param...
Definition: MSVehicle.cpp:2270
std::vector< std::pair< SUMOTime, double > > mySpeedTimeLine
The velocity time line to apply.
Definition: MSVehicle.h:1471
MSVehicleType * myType
This vehicle&#39;s type.
void passTime(SUMOTime dt, bool waiting)
Definition: MSVehicle.cpp:204
void workOnMoveReminders(double oldPos, double newPos, double newSpeed)
Processes active move reminder.
Definition: MSVehicle.cpp:839
double getEndPos(const SUMOVehicle &veh) const
return halting position for upcoming stop;
Definition: MSVehicle.cpp:562
virtual double getHeadwayTime() const
Get the driver&#39;s desired headway [s].
Definition: MSCFModel.h:246
The vehicle is blocked being overlapping.
void checkRewindLinkLanes(const double lengthsInFront, DriveItemVector &lfLinks) const
Definition: MSVehicle.cpp:3229
int mySignals
State of things of the vehicle that can be on or off.
Definition: MSVehicle.h:1730
bool isRemoteControlled() const
Definition: MSVehicle.cpp:472
void resetChanged()
reset the flag whether a vehicle already moved to false
ConstMSEdgeVector myRemoteRoute
Definition: MSVehicle.h:1506
std::vector< MSLane * > bestContinuations
Definition: MSVehicle.h:819
MSStoppingPlace * chargingStation
(Optional) charging station if one is assigned to the stop
Definition: MSVehicle.h:915
Definition of vehicle stop (position and duration)
void setRemoteState(Position xyPos)
sets position outside the road network
Definition: MSVehicle.cpp:4849
void scaleRelative(double factor)
enlarges/shrinks the polygon by a factor based at the centroid
MSStoppingPlace * containerstop
(Optional) container stop if one is assigned to the stop
Definition: MSVehicle.h:911
int getLanechangeMode() const
return the current lane change mode
Definition: MSVehicle.cpp:293
void onDepart()
Called when the vehicle is inserted into the network.
double getMinimalArrivalSpeed(double dist, double currentSpeed) const
Computes the minimal possible arrival speed after covering a given distance.
Definition: MSCFModel.cpp:432
double interpolateLanePosToGeometryPos(double lanePos) const
Definition: MSLane.h:455
const MSEdge * getRerouteOrigin() const
Returns the starting point for reroutes (usually the current edge)
Definition: MSVehicle.cpp:1011
const std::string & getID() const
Returns the name of the vehicle type.
double getPMxEmissions() const
Returns PMx emission of the current state.
Definition: MSVehicle.cpp:4162
int index
at which position in the stops list
SUMOTime getMinimalArrivalTime(double dist, double currentSpeed, double arrivalSpeed) const
Computes the minimal time needed to cover a distance given the desired speed at arrival.
Definition: MSCFModel.cpp:331
MSVehicle * getLastAnyVehicle() const
returns the last vehicle that is fully or partially on this lane
Definition: MSLane.cpp:1797
const Position geometryPositionAtOffset(double offset, double lateralOffset=0) const
Definition: MSLane.h:461
The arrival lane is given.
int containerNumber
The static number of containers in the vehicle when it departs.
The vehicle ends to stop.
Definition: MSNet.h:502
void activateReminders(const MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
"Activates" all current move reminder
Definition: MSVehicle.cpp:3445
void addReference() const
increments the reference counter for the route
Definition: MSRoute.cpp:98
void updateActionOffset(const SUMOTime oldActionStepLength, const SUMOTime newActionStepLength)
Process an updated action step length value (only affects the vehicle&#39;s action offset, The actionStepLength is stored in the (singular) vtype)
Definition: MSVehicle.cpp:1618
A device which collects info on the vehicle trip (mainly on departure and arrival) ...
int myNumberReroutes
The number of reroutings.
int getContainerNumber() const
Returns the number of containers.
Definition: MSVehicle.cpp:4253
double getLength() const
Get vehicle&#39;s length [m].
void informVehicleStateListener(const SUMOVehicle *const vehicle, VehicleState to)
Informs all added listeners about a vehicle&#39;s state change.
Definition: MSNet.cpp:849
SUMOTime cumulatedWaitingTime(SUMOTime memory=-1) const
Definition: MSVehicle.cpp:183
void setLaneChangeMode(int value)
Sets lane changing behavior.
Definition: MSVehicle.cpp:448
const MSLane * getBackLane() const
Definition: MSVehicle.cpp:3044
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition: MSLane.h:739
static MSStopOut * getInstance()
Definition: MSStopOut.h:67
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition: StdDefs.h:57
double getTimeGapOnLane() const
Returns the time gap in seconds to the leader of the vehicle on the same lane.
Definition: MSVehicle.cpp:4127
waitingIntervalList myWaitingIntervals
Definition: MSVehicle.h:212
std::vector< DriveProcessItem > DriveItemVector
Container for used Links/visited Lanes during planMove() and executeMove.
Definition: MSVehicle.h:1813
void updateWaitingTime(double vNext)
Updates the vehicle&#39;s waiting time counters (accumulated and consecutive)
Definition: MSVehicle.cpp:2695
void setSignals(int signals)
Definition: MSVehicle.h:1451
const MSEdgeWeightsStorage & getWeightsStorage() const
Returns the vehicle&#39;s internal edge travel times/efforts container.
Definition: MSVehicle.cpp:817
bool isRemoteAffected(SUMOTime t) const
Definition: MSVehicle.cpp:478
The action is due to a TraCI request.
double getBackPositionOnLane(const MSLane *lane) const
Get the vehicle&#39;s position relative to the given lane.
Definition: MSVehicle.cpp:3120
const std::vector< MSLane * > & getShadowFurtherLanes() const
double estimateSpeedAfterDistance(const double dist, const double v, const double accel) const
Definition: MSCFModel.cpp:653
vehicle want&#39;s to keep the current lane
Definition: MSVehicle.h:230
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:70
double speed() const
Speed of this state.
Definition: MSVehicle.h:118
void changedToOpposite()
called when a vehicle changes between lanes in opposite directions
The vehicle needs another parking area.
bool closeTag()
Closes the most recently opened tag.
void switchOffSignal(int signal)
Switches the given signal off.
Definition: MSVehicle.h:1223
static bool gSemiImplicitEulerUpdate
Definition: MSGlobals.h:62
void switchOnSignal(int signal)
Switches the given signal on.
Definition: MSVehicle.h:1215
double getSlope() const
Returns the slope of the road at vehicle&#39;s position.
Definition: MSVehicle.cpp:890
bool passingMinor() const
decide whether the vehicle is passing a minor link or has comitted to do so
Definition: MSVehicle.cpp:4916
void addPerson(MSTransportable *person)
Adds a passenger.
Definition: MSVehicle.cpp:4186
static std::vector< MSLane * > myEmptyLaneVector
Definition: MSVehicle.h:1709
long long int SUMOTime
Definition: TraCIDefs.h:51
MSRouteIterator myCurrEdge
Iterator to current route-edge.
bool isActionStep(SUMOTime t) const
Returns whether the next simulation step will be an action point for the vehicle. ...
Definition: MSVehicle.h:601
bool unsafeLinkAhead(const MSLane *lane) const
whether the vehicle may safely move to the given lane with regard to upcoming links ...
Definition: MSVehicle.cpp:4512
#define NUMERICAL_EPS
Definition: config.h:151
MSEdgeWeightsStorage & _getWeightsStorage() const
Definition: MSVehicle.cpp:829
double arrivalSpeed
(optional) The final speed of the vehicle (not used yet)
MSLane * getShadowLane() const
Returns the lane the vehicle&#39;s shadow is on during continuous/sublane lane change.
void setLaneTimeLine(const std::vector< std::pair< SUMOTime, int > > &laneTimeLine)
Sets a new lane timeline.
Definition: MSVehicle.cpp:273
double getHCEmissions() const
Returns HC emission of the current state.
Definition: MSVehicle.cpp:4150
virtual ~MSVehicle()
Destructor.
Definition: MSVehicle.cpp:685
MSRouteIterator begin() const
Returns the begin of the list of edges to pass.
Definition: MSRoute.cpp:73
const std::vector< MSTransportable * > & getPersons() const
retrieve riding persons
Definition: MSVehicle.cpp:4227
SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT(const MSEdgeVector &prohibited=MSEdgeVector()) const
Definition: MSNet.cpp:897
bool isStopped() const
Returns whether the vehicle is at a stop.
Definition: MSVehicle.cpp:1332
No information given; use default.
const std::vector< MSTransportable * > & getContainers() const
retrieve riding containers
Definition: MSVehicle.cpp:4237
bool willPass(const MSEdge *const edge) const
Returns whether the vehicle wil pass the given edge.
Definition: MSVehicle.cpp:796
MSParkingArea * getNextParkingArea()
get the current parking area stop
Definition: MSVehicle.cpp:1318
const Position getBackPosition() const
Definition: MSVehicle.cpp:1079
const MSLinkCont & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.cpp:1874
double getRightSideOnEdge(const MSLane *lane=0) const
Get the vehicle&#39;s lateral position on the edge of the given lane (or its current edge if lane == 0) ...
Definition: MSVehicle.cpp:4337
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
Definition: MSVehicle.cpp:3686
const MSLane & getLane() const
Returns the lane this stop is located at.
bool isParking() const
Returns whether the vehicle is parking.
Definition: MSVehicle.cpp:1358
double getSpeed() const
Returns the vehicle&#39;s current speed.
Definition: MSVehicle.h:482
State(double pos, double speed, double posLat, double backPos)
Constructor.
Definition: MSVehicle.cpp:155
bool mySpeedAdaptationStarted
Whether influencing the speed has already started.
Definition: MSVehicle.h:1483
static SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT(const MSEdgeVector &prohibited=MSEdgeVector())
return the router instance
double estimateLeaveSpeed(const MSLink *const link, const double vLinkPass) const
estimate leaving speed when accelerating across a link
Definition: MSVehicle.h:1833
double getLastFreePos(const SUMOVehicle &forVehicle) const
Returns the last free position on this stop.
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
Definition: MSVehicle.cpp:4836
public emergency vehicles
render as a wagon passenger vehicle ("Combi")
virtual void releaseVehicles() const
Allows to use the container for microsimulation again.
Definition: MSLane.h:419
void removeTransportable(MSTransportable *transportable)
Remove a passenger (TraCI)
static SUMOTime gLaneChangeDuration
Definition: MSGlobals.h:88
SUMOTime getLastAccessTimeStep() const
Definition: MSVehicle.h:1435
int influenceChangeDecision(const SUMOTime currentTime, const MSEdge &currentEdge, const int currentLaneIndex, int state)
Applies stored LaneChangeMode information and laneTimeLine.
Definition: MSVehicle.cpp:343
SUMOTime timeToLoadNextContainer
The time at which the vehicle is able to load another container.
Definition: MSVehicle.h:933
static MSAbstractLaneChangeModel * build(LaneChangeModel lcm, MSVehicle &vehicle)
Factory method for instantiating new lane changing models.
const std::string & getID() const
Returns the name of the vehicle.
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
void addReminder(MSMoveReminder *rem)
Adds a MoveReminder dynamically.
Representation of a lane in the micro simulation.
Definition: MSLane.h:77
std::vector< MSDevice * > myDevices
The devices this vehicle has.
double myBackPos
the stored back position
Definition: MSVehicle.h:151
SUMOEmissionClass getEmissionClass() const
Get this vehicle type&#39;s emission class.
void adaptLaneEntering2MoveReminder(const MSLane &enteredLane)
Adapts the vehicle&#39;s entering of a new lane.
Definition: MSVehicle.cpp:868
const std::vector< SUMOVehicleParameter::Stop > & getStops() const
Returns the stops.
Definition: MSRoute.cpp:366
Back-at-zero position.
LaneChangeMode myStrategicLC
lane changing which is necessary to follow the current route
Definition: MSVehicle.h:1512
void unregisterOneWaiting(const bool isPerson)
decreases the count of vehicles waiting for a transport to allow recognition of person / container re...
MSRouteIterator end() const
Returns the end of the list of edges to pass.
Definition: MSRoute.cpp:79
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition: ToString.h:236
Interface for lane-change models.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
double mySpeed
the stored speed (should be >=0 at any time)
Definition: MSVehicle.h:143
bool contains(const MSEdge *const edge) const
Definition: MSRoute.h:109
bool myConsiderSafeVelocity
Whether the safe velocity shall be regarded.
Definition: MSVehicle.h:1486
const std::vector< MSLane * > & getFurtherTargetLanes() const
virtual double stopSpeed(const MSVehicle *const veh, const double speed, double gap) const =0
Computes the vehicle&#39;s safe speed for approaching a non-moving obstacle (no dawdling) ...
SUMOTime myDeparture
The real departure time.
void removeTransportable(MSTransportable *t)
removes a person or container
Definition: MSVehicle.cpp:4217
SUMOVehicleClass getVehicleClass() const
Get this vehicle type&#39;s vehicle class.
MSDevice_Transportable * myContainerDevice
The containers this vehicle may have.
Definition: MSVehicle.h:1719
static const SUMOTime NOT_YET_DEPARTED
double getWidth() const
Returns the vehicle&#39;s width.
std::string id
The vehicle&#39;s id.
static const Position INVALID
used to indicate that a position is valid
Definition: Position.h:277
double getSpeedWithoutTraciInfluence() const
Returns the uninfluenced velocity.
Definition: MSVehicle.cpp:4827
The vehicle is being teleported.
MSLane * getParallelLane(int offset) const
Returns the lane with the given offset parallel to this one or 0 if it does not exist.
Definition: MSLane.cpp:1962
void stopEnded(const MSVehicle::Stop &stop)
Definition of vehicle stop (position and duration)
Definition: MSVehicle.h:901
double pos() const
Position of this state.
Definition: MSVehicle.h:113
void endLaneChangeManeuver(const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_LANE_CHANGE)
void updateDriveItems()
Check whether the drive items (myLFLinkLanes) are up to date, and update them if required.
Definition: MSVehicle.cpp:2516
double getWidth() const
Returns the edges&#39;s width (sum over all lanes)
Definition: MSEdge.h:547