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