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