Eclipse 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-2022 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
31 // Representation of a vehicle in the micro simulation
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>
47 #include <utils/common/StdDefs.h>
48 #include <utils/geom/GeomHelper.h>
63 #include "MSEdgeControl.h"
64 #include "MSVehicleControl.h"
65 #include "MSInsertionControl.h"
66 #include "MSVehicleTransfer.h"
67 #include "MSGlobals.h"
68 #include "MSJunctionLogic.h"
69 #include "MSStop.h"
70 #include "MSStoppingPlace.h"
71 #include "MSParkingArea.h"
74 #include "MSMoveReminder.h"
76 #include "MSLane.h"
77 #include "MSJunction.h"
78 #include "MSVehicle.h"
79 #include "MSEdge.h"
80 #include "MSVehicleType.h"
81 #include "MSNet.h"
82 #include "MSRoute.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_SETFURTHER
92 //#define DEBUG_TARGET_LANE
93 //#define DEBUG_STOPS
94 //#define DEBUG_BESTLANES
95 //#define DEBUG_IGNORE_RED
96 //#define DEBUG_ACTIONSTEPS
97 //#define DEBUG_NEXT_TURN
98 //#define DEBUG_TRACI
99 //#define DEBUG_REVERSE_BIDI
100 //#define DEBUG_REPLACE_ROUTE
101 //#define DEBUG_COND (getID() == "v0")
102 //#define DEBUG_COND (true)
103 #define DEBUG_COND (isSelected())
104 //#define DEBUG_COND2(obj) (obj->getID() == "follower")
105 #define DEBUG_COND2(obj) (obj->isSelected())
106 //#define PARALLEL_STOPWATCH
107 
108 
109 #define STOPPING_PLACE_OFFSET 0.5
110 
111 #define CRLL_LOOK_AHEAD 5
112 
113 #define JUNCTION_BLOCKAGE_TIME 5 // s
114 
115 // @todo Calibrate with real-world values / make configurable
116 #define DIST_TO_STOPLINE_EXPECT_PRIORITY 1.0
117 
118 #define NUMERICAL_EPS_SPEED (0.1 * NUMERICAL_EPS * TS)
119 
120 // ===========================================================================
121 // static value definitions
122 // ===========================================================================
123 std::vector<MSLane*> MSVehicle::myEmptyLaneVector;
124 
125 
126 // ===========================================================================
127 // method definitions
128 // ===========================================================================
129 /* -------------------------------------------------------------------------
130  * methods of MSVehicle::State
131  * ----------------------------------------------------------------------- */
133  myPos = state.myPos;
134  mySpeed = state.mySpeed;
135  myPosLat = state.myPosLat;
136  myBackPos = state.myBackPos;
139 }
140 
141 
144  myPos = state.myPos;
145  mySpeed = state.mySpeed;
146  myPosLat = state.myPosLat;
147  myBackPos = state.myBackPos;
148  myPreviousSpeed = state.myPreviousSpeed;
149  myLastCoveredDist = state.myLastCoveredDist;
150  return *this;
151 }
152 
153 
154 bool
156  return (myPos != state.myPos ||
157  mySpeed != state.mySpeed ||
158  myPosLat != state.myPosLat ||
159  myLastCoveredDist != state.myLastCoveredDist ||
160  myPreviousSpeed != state.myPreviousSpeed ||
161  myBackPos != state.myBackPos);
162 }
163 
164 
165 MSVehicle::State::State(double pos, double speed, double posLat, double backPos) :
166  myPos(pos), mySpeed(speed), myPosLat(posLat), myBackPos(backPos), myPreviousSpeed(speed), myLastCoveredDist(SPEED2DIST(speed)) {}
167 
168 
169 
170 /* -------------------------------------------------------------------------
171  * methods of MSVehicle::WaitingTimeCollector
172  * ----------------------------------------------------------------------- */
174 
175 
176 SUMOTime
178  assert(memorySpan <= myMemorySize);
179  if (memorySpan == -1) {
180  memorySpan = myMemorySize;
181  }
182  SUMOTime totalWaitingTime = 0;
183  for (const auto& interval : myWaitingIntervals) {
184  if (interval.second >= memorySpan) {
185  if (interval.first >= memorySpan) {
186  break;
187  } else {
188  totalWaitingTime += memorySpan - interval.first;
189  }
190  } else {
191  totalWaitingTime += interval.second - interval.first;
192  }
193  }
194  return totalWaitingTime;
195 }
196 
197 
198 void
200  auto i = myWaitingIntervals.begin();
201  const auto end = myWaitingIntervals.end();
202  const bool startNewInterval = i == end || (i->first != 0);
203  while (i != end) {
204  i->first += dt;
205  if (i->first >= myMemorySize) {
206  break;
207  }
208  i->second += dt;
209  i++;
210  }
211 
212  // remove intervals beyond memorySize
213  auto d = std::distance(i, end);
214  while (d > 0) {
215  myWaitingIntervals.pop_back();
216  d--;
217  }
218 
219  if (!waiting) {
220  return;
221  } else if (!startNewInterval) {
222  myWaitingIntervals.begin()->first = 0;
223  } else {
224  myWaitingIntervals.push_front(std::make_pair(0, dt));
225  }
226  return;
227 }
228 
229 
230 const std::string
232  std::ostringstream state;
233  state << myMemorySize << " " << myWaitingIntervals.size();
234  for (const auto& interval : myWaitingIntervals) {
235  state << " " << interval.first << " " << interval.second;
236  }
237  return state.str();
238 }
239 
240 
241 void
242 MSVehicle::WaitingTimeCollector::setState(const std::string& state) {
243  std::istringstream is(state);
244  int numIntervals;
245  SUMOTime begin, end;
246  is >> myMemorySize >> numIntervals;
247  while (numIntervals-- > 0) {
248  is >> begin >> end;
249  myWaitingIntervals.emplace_back(begin, end);
250  }
251 }
252 
253 
254 /* -------------------------------------------------------------------------
255  * methods of MSVehicle::Influencer::GapControlState
256  * ----------------------------------------------------------------------- */
257 void
259 // std::cout << "GapControlVehStateListener::vehicleStateChanged() vehicle=" << vehicle->getID() << ", to=" << to << std::endl;
260  switch (to) {
264  // Vehicle left road
265 // Look up reference vehicle in refVehMap and in case deactivate corresponding gap control
266  const MSVehicle* msVeh = static_cast<const MSVehicle*>(vehicle);
267 // std::cout << "GapControlVehStateListener::vehicleStateChanged() vehicle=" << vehicle->getID() << " left the road." << std::endl;
268  if (GapControlState::refVehMap.find(msVeh) != end(GapControlState::refVehMap)) {
269 // std::cout << "GapControlVehStateListener::deactivating ref vehicle=" << vehicle->getID() << std::endl;
270  GapControlState::refVehMap[msVeh]->deactivate();
271  }
272  }
273  break;
274  default:
275  {};
276  // do nothing, vehicle still on road
277  }
278 }
279 
280 std::map<const MSVehicle*, MSVehicle::Influencer::GapControlState*>
282 
285 
287  tauOriginal(-1), tauCurrent(-1), tauTarget(-1), addGapCurrent(-1), addGapTarget(-1),
288  remainingDuration(-1), changeRate(-1), maxDecel(-1), referenceVeh(nullptr), active(false), gapAttained(false), prevLeader(nullptr),
289  lastUpdate(-1), timeHeadwayIncrement(0.0), spaceHeadwayIncrement(0.0) {}
290 
291 
293  deactivate();
294 }
295 
296 void
298 // std::cout << "GapControlState::init()" << std::endl;
299  if (MSNet::hasInstance()) {
300  MSNet::VehicleStateListener* vsl = dynamic_cast<MSNet::VehicleStateListener*>(&vehStateListener);
302  } else {
303  WRITE_ERROR("MSVehicle::Influencer::GapControlState::init(): No MSNet instance found!")
304  }
305 }
306 
307 void
309  MSNet::VehicleStateListener* vsl = dynamic_cast<MSNet::VehicleStateListener*>(&vehStateListener);
311 }
312 
313 void
314 MSVehicle::Influencer::GapControlState::activate(double tauOrig, double tauNew, double additionalGap, double dur, double rate, double decel, const MSVehicle* refVeh) {
316  WRITE_ERROR("No gap control available for meso.")
317  } else {
318  // always deactivate control before activating (triggers clean-up of refVehMap)
319 // std::cout << "activate gap control with refVeh=" << (refVeh==nullptr? "NULL" : refVeh->getID()) << std::endl;
320  tauOriginal = tauOrig;
321  tauCurrent = tauOrig;
322  tauTarget = tauNew;
323  addGapCurrent = 0.0;
324  addGapTarget = additionalGap;
325  remainingDuration = dur;
326  changeRate = rate;
327  maxDecel = decel;
328  referenceVeh = refVeh;
329  active = true;
330  gapAttained = false;
331  prevLeader = nullptr;
332  lastUpdate = SIMSTEP - DELTA_T;
333  timeHeadwayIncrement = changeRate * TS * (tauTarget - tauOriginal);
334  spaceHeadwayIncrement = changeRate * TS * addGapTarget;
335 
336  if (referenceVeh != nullptr) {
337  // Add refVeh to refVehMap
338  GapControlState::refVehMap[referenceVeh] = this;
339  }
340  }
341 }
342 
343 void
345  active = false;
346  if (referenceVeh != nullptr) {
347  // Remove corresponding refVehMapEntry if appropriate
348  GapControlState::refVehMap.erase(referenceVeh);
349  referenceVeh = nullptr;
350  }
351 }
352 
353 
354 /* -------------------------------------------------------------------------
355  * methods of MSVehicle::Influencer
356  * ----------------------------------------------------------------------- */
358  myGapControlState(nullptr),
359  myOriginalSpeed(-1),
360  myLatDist(0),
375  myTraCISignals(-1)
376 {}
377 
378 
380 
381 void
383  GapControlState::init();
384 }
385 
386 void
388  GapControlState::cleanup();
389 }
390 
391 void
392 MSVehicle::Influencer::setSpeedTimeLine(const std::vector<std::pair<SUMOTime, double> >& speedTimeLine) {
393  mySpeedAdaptationStarted = true;
394  mySpeedTimeLine = speedTimeLine;
395 }
396 
397 void
398 MSVehicle::Influencer::activateGapController(double originalTau, double newTimeHeadway, double newSpaceHeadway, double duration, double changeRate, double maxDecel, MSVehicle* refVeh) {
399  if (myGapControlState == nullptr) {
400  myGapControlState = std::make_shared<GapControlState>();
401  }
402  myGapControlState->activate(originalTau, newTimeHeadway, newSpaceHeadway, duration, changeRate, maxDecel, refVeh);
403 }
404 
405 void
407  if (myGapControlState != nullptr && myGapControlState->active) {
408  myGapControlState->deactivate();
409  }
410 }
411 
412 void
413 MSVehicle::Influencer::setLaneTimeLine(const std::vector<std::pair<SUMOTime, int> >& laneTimeLine) {
414  myLaneTimeLine = laneTimeLine;
415 }
416 
417 
418 void
420  for (auto& item : myLaneTimeLine) {
421  item.second += indexShift;
422  }
423 }
424 
425 
426 void
428  myLatDist = latDist;
429 }
430 
431 int
433  return (1 * myConsiderSafeVelocity +
434  2 * myConsiderMaxAcceleration +
435  4 * myConsiderMaxDeceleration +
436  8 * myRespectJunctionPriority +
437  16 * myEmergencyBrakeRedLight +
438  32 * !myRespectJunctionLeaderPriority // inverted!
439  );
440 }
441 
442 
443 int
445  return (1 * myStrategicLC +
446  4 * myCooperativeLC +
447  16 * mySpeedGainLC +
448  64 * myRightDriveLC +
449  256 * myTraciLaneChangePriority +
450  1024 * mySublaneLC);
451 }
452 
453 SUMOTime
455  SUMOTime duration = -1;
456  for (std::vector<std::pair<SUMOTime, int>>::iterator i = myLaneTimeLine.begin(); i != myLaneTimeLine.end(); ++i) {
457  if (duration < 0) {
458  duration = i->first;
459  } else {
460  duration -= i->first;
461  }
462  }
463  return -duration;
464 }
465 
466 SUMOTime
468  if (!myLaneTimeLine.empty()) {
469  return myLaneTimeLine.back().first;
470  } else {
471  return -1;
472  }
473 }
474 
475 
476 double
477 MSVehicle::Influencer::influenceSpeed(SUMOTime currentTime, double speed, double vSafe, double vMin, double vMax) {
478  // remove leading commands which are no longer valid
479  while (mySpeedTimeLine.size() == 1 || (mySpeedTimeLine.size() > 1 && currentTime > mySpeedTimeLine[1].first)) {
480  mySpeedTimeLine.erase(mySpeedTimeLine.begin());
481  }
482 
483  if (!(mySpeedTimeLine.size() < 2 || currentTime < mySpeedTimeLine[0].first)) {
484  // Speed advice is active -> compute new speed according to speedTimeLine
485  if (!mySpeedAdaptationStarted) {
486  mySpeedTimeLine[0].second = speed;
487  mySpeedAdaptationStarted = true;
488  }
489  currentTime += DELTA_T;
490  const double td = STEPS2TIME(currentTime - mySpeedTimeLine[0].first) / STEPS2TIME(mySpeedTimeLine[1].first + DELTA_T - mySpeedTimeLine[0].first);
491  speed = mySpeedTimeLine[0].second - (mySpeedTimeLine[0].second - mySpeedTimeLine[1].second) * td;
492  if (myConsiderSafeVelocity) {
493  speed = MIN2(speed, vSafe);
494  }
495  if (myConsiderMaxAcceleration) {
496  speed = MIN2(speed, vMax);
497  }
498  if (myConsiderMaxDeceleration) {
499  speed = MAX2(speed, vMin);
500  }
501  }
502  return speed;
503 }
504 
505 double
506 MSVehicle::Influencer::gapControlSpeed(SUMOTime currentTime, const SUMOVehicle* veh, double speed, double vSafe, double vMin, double vMax) {
507 #ifdef DEBUG_TRACI
508  if DEBUG_COND2(veh) {
509  std::cout << currentTime << " Influencer::gapControlSpeed(): speed=" << speed
510  << ", vSafe=" << vSafe
511  << ", vMin=" << vMin
512  << ", vMax=" << vMax
513  << std::endl;
514  }
515 #endif
516  double gapControlSpeed = speed;
517  if (myGapControlState != nullptr && myGapControlState->active) {
518  // Determine leader and the speed that would be chosen by the gap controller
519  const double currentSpeed = veh->getSpeed();
520  const MSVehicle* msVeh = dynamic_cast<const MSVehicle*>(veh);
521  assert(msVeh != nullptr);
522  const double desiredTargetTimeSpacing = myGapControlState->tauTarget * currentSpeed;
523  std::pair<const MSVehicle*, double> leaderInfo;
524  if (myGapControlState->referenceVeh == nullptr) {
525  // No reference vehicle specified -> use current leader as reference
526  leaderInfo = msVeh->getLeader(MAX2(desiredTargetTimeSpacing, myGapControlState->addGapCurrent) + 20.);
527  } else {
528  // Control gap wrt reference vehicle
529  const MSVehicle* leader = myGapControlState->referenceVeh;
530  double dist = msVeh->getDistanceToPosition(leader->getPositionOnLane(), leader->getEdge()) - leader->getLength();
531  if (dist > 100000) {
532  // Reference vehicle was not found downstream the ego's route
533  // Maybe, it is behind the ego vehicle
534  dist = - leader->getDistanceToPosition(msVeh->getPositionOnLane(), msVeh->getEdge()) - leader->getLength();
535 #ifdef DEBUG_TRACI
536  if DEBUG_COND2(veh) {
537  if (dist < -100000) {
538  // also the ego vehicle is not ahead of the reference vehicle -> no CF-relation
539  std::cout << " Ego and reference vehicle are not in CF relation..." << std::endl;
540  } else {
541  std::cout << " Reference vehicle is behind ego..." << std::endl;
542  }
543  }
544 #endif
545  }
546  leaderInfo = std::make_pair(leader, dist - msVeh->getVehicleType().getMinGap());
547  }
548  const double fakeDist = MAX2(0.0, leaderInfo.second - myGapControlState->addGapCurrent);
549 #ifdef DEBUG_TRACI
550  if DEBUG_COND2(veh) {
551  const double desiredCurrentSpacing = myGapControlState->tauCurrent * currentSpeed;
552  std::cout << " Gap control active:"
553  << " currentSpeed=" << currentSpeed
554  << ", desiredTargetTimeSpacing=" << desiredTargetTimeSpacing
555  << ", desiredCurrentSpacing=" << desiredCurrentSpacing
556  << ", leader=" << (leaderInfo.first == nullptr ? "NULL" : leaderInfo.first->getID())
557  << ", dist=" << leaderInfo.second
558  << ", fakeDist=" << fakeDist
559  << ",\n tauOriginal=" << myGapControlState->tauOriginal
560  << ", tauTarget=" << myGapControlState->tauTarget
561  << ", tauCurrent=" << myGapControlState->tauCurrent
562  << std::endl;
563  }
564 #endif
565  if (leaderInfo.first != nullptr) {
566  if (myGapControlState->prevLeader != nullptr && myGapControlState->prevLeader != leaderInfo.first) {
567  // TODO: The leader changed. What to do?
568  }
569  // Remember leader
570  myGapControlState->prevLeader = leaderInfo.first;
571 
572  // Calculate desired following speed assuming the alternative headway time
573  MSCFModel* cfm = (MSCFModel*) & (msVeh->getVehicleType().getCarFollowModel());
574  const double origTau = cfm->getHeadwayTime();
575  cfm->setHeadwayTime(myGapControlState->tauCurrent);
576  gapControlSpeed = MIN2(gapControlSpeed,
577  cfm->followSpeed(msVeh, currentSpeed, fakeDist, leaderInfo.first->getSpeed(), leaderInfo.first->getCurrentApparentDecel(), leaderInfo.first));
578  cfm->setHeadwayTime(origTau);
579 #ifdef DEBUG_TRACI
580  if DEBUG_COND2(veh) {
581  std::cout << " -> gapControlSpeed=" << gapControlSpeed;
582  if (myGapControlState->maxDecel > 0) {
583  std::cout << ", with maxDecel bound: " << MAX2(gapControlSpeed, currentSpeed - TS * myGapControlState->maxDecel);
584  }
585  std::cout << std::endl;
586  }
587 #endif
588  if (myGapControlState->maxDecel > 0) {
589  gapControlSpeed = MAX2(gapControlSpeed, currentSpeed - TS * myGapControlState->maxDecel);
590  }
591  }
592 
593  // Update gap controller
594  // Check (1) if the gap control has established the desired gap,
595  // and (2) if it has maintained active for the given duration afterwards
596  if (myGapControlState->lastUpdate < currentTime) {
597 #ifdef DEBUG_TRACI
598  if DEBUG_COND2(veh) {
599  std::cout << " Updating GapControlState." << std::endl;
600  }
601 #endif
602  if (myGapControlState->tauCurrent == myGapControlState->tauTarget && myGapControlState->addGapCurrent == myGapControlState->addGapTarget) {
603  if (!myGapControlState->gapAttained) {
604  // Check if the desired gap was established (add the POSITION_EPS to avoid infinite asymptotic behavior without having established the gap)
605  myGapControlState->gapAttained = leaderInfo.first == nullptr || leaderInfo.second > MAX2(desiredTargetTimeSpacing, myGapControlState->addGapTarget) - POSITION_EPS;
606 #ifdef DEBUG_TRACI
607  if DEBUG_COND2(veh) {
608  if (myGapControlState->gapAttained) {
609  std::cout << " Target gap was established." << std::endl;
610  }
611  }
612 #endif
613  } else {
614  // Count down remaining time if desired gap was established
615  myGapControlState->remainingDuration -= TS;
616 #ifdef DEBUG_TRACI
617  if DEBUG_COND2(veh) {
618  std::cout << " Gap control remaining duration: " << myGapControlState->remainingDuration << std::endl;
619  }
620 #endif
621  if (myGapControlState->remainingDuration <= 0) {
622 #ifdef DEBUG_TRACI
623  if DEBUG_COND2(veh) {
624  std::cout << " Gap control duration expired, deactivating control." << std::endl;
625  }
626 #endif
627  // switch off gap control
628  myGapControlState->deactivate();
629  }
630  }
631  } else {
632  // Adjust current headway values
633  myGapControlState->tauCurrent = MIN2(myGapControlState->tauCurrent + myGapControlState->timeHeadwayIncrement, myGapControlState->tauTarget);
634  myGapControlState->addGapCurrent = MIN2(myGapControlState->addGapCurrent + myGapControlState->spaceHeadwayIncrement, myGapControlState->addGapTarget);
635  }
636  }
637  if (myConsiderSafeVelocity) {
638  gapControlSpeed = MIN2(gapControlSpeed, vSafe);
639  }
640  if (myConsiderMaxAcceleration) {
641  gapControlSpeed = MIN2(gapControlSpeed, vMax);
642  }
643  if (myConsiderMaxDeceleration) {
644  gapControlSpeed = MAX2(gapControlSpeed, vMin);
645  }
646  return MIN2(speed, gapControlSpeed);
647  } else {
648  return speed;
649  }
650 }
651 
652 double
654  return myOriginalSpeed;
655 }
656 
657 void
659  myOriginalSpeed = speed;
660 }
661 
662 
663 int
664 MSVehicle::Influencer::influenceChangeDecision(const SUMOTime currentTime, const MSEdge& currentEdge, const int currentLaneIndex, int state) {
665  // remove leading commands which are no longer valid
666  while (myLaneTimeLine.size() == 1 || (myLaneTimeLine.size() > 1 && currentTime > myLaneTimeLine[1].first)) {
667  myLaneTimeLine.erase(myLaneTimeLine.begin());
668  }
669  ChangeRequest changeRequest = REQUEST_NONE;
670  // do nothing if the time line does not apply for the current time
671  if (myLaneTimeLine.size() >= 2 && currentTime >= myLaneTimeLine[0].first) {
672  const int destinationLaneIndex = myLaneTimeLine[1].second;
673  if (destinationLaneIndex < (int)currentEdge.getLanes().size()) {
674  if (currentLaneIndex > destinationLaneIndex) {
675  changeRequest = REQUEST_RIGHT;
676  } else if (currentLaneIndex < destinationLaneIndex) {
677  changeRequest = REQUEST_LEFT;
678  } else {
679  changeRequest = REQUEST_HOLD;
680  }
681  } else if (currentEdge.getLanes().back()->getOpposite() != nullptr) { // change to opposite direction driving
682  changeRequest = REQUEST_LEFT;
683  state = state | LCA_TRACI;
684  }
685  }
686  // check whether the current reason shall be canceled / overridden
687  if ((state & LCA_WANTS_LANECHANGE_OR_STAY) != 0) {
688  // flags for the current reason
689  LaneChangeMode mode = LC_NEVER;
690  if ((state & LCA_TRACI) != 0 && myLatDist != 0) {
691  // security checks
692  if ((myTraciLaneChangePriority == LCP_ALWAYS)
693  || (myTraciLaneChangePriority == LCP_NOOVERLAP && (state & LCA_OVERLAPPING) == 0)) {
694  state &= ~(LCA_BLOCKED | LCA_OVERLAPPING);
695  }
696  // continue sublane change manoeuvre
697  return state;
698  } else if ((state & LCA_STRATEGIC) != 0) {
699  mode = myStrategicLC;
700  } else if ((state & LCA_COOPERATIVE) != 0) {
701  mode = myCooperativeLC;
702  } else if ((state & LCA_SPEEDGAIN) != 0) {
703  mode = mySpeedGainLC;
704  } else if ((state & LCA_KEEPRIGHT) != 0) {
705  mode = myRightDriveLC;
706  } else if ((state & LCA_SUBLANE) != 0) {
707  mode = mySublaneLC;
708  } else if ((state & LCA_TRACI) != 0) {
709  mode = LC_NEVER;
710  } else {
711  WRITE_WARNING("Lane change model did not provide a reason for changing (state=" + toString(state) + ", time=" + time2string(currentTime) + "\n");
712  }
713  if (mode == LC_NEVER) {
714  // cancel all lcModel requests
716  state &= ~LCA_URGENT;
717  } else if (mode == LC_NOCONFLICT && changeRequest != REQUEST_NONE) {
718  if (
719  ((state & LCA_LEFT) != 0 && changeRequest != REQUEST_LEFT) ||
720  ((state & LCA_RIGHT) != 0 && changeRequest != REQUEST_RIGHT) ||
721  ((state & LCA_STAY) != 0 && changeRequest != REQUEST_HOLD)) {
722  // cancel conflicting lcModel request
724  state &= ~LCA_URGENT;
725  }
726  } else if (mode == LC_ALWAYS) {
727  // ignore any TraCI requests
728  return state;
729  }
730  }
731  // apply traci requests
732  if (changeRequest == REQUEST_NONE) {
733  return state;
734  } else {
735  state |= LCA_TRACI;
736  // security checks
737  if ((myTraciLaneChangePriority == LCP_ALWAYS)
738  || (myTraciLaneChangePriority == LCP_NOOVERLAP && (state & LCA_OVERLAPPING) == 0)) {
739  state &= ~(LCA_BLOCKED | LCA_OVERLAPPING);
740  }
741  if (changeRequest != REQUEST_HOLD && myTraciLaneChangePriority != LCP_OPPORTUNISTIC) {
742  state |= LCA_URGENT;
743  }
744  switch (changeRequest) {
745  case REQUEST_HOLD:
746  return state | LCA_STAY;
747  case REQUEST_LEFT:
748  return state | LCA_LEFT;
749  case REQUEST_RIGHT:
750  return state | LCA_RIGHT;
751  default:
752  throw ProcessError("should not happen");
753  }
754  }
755 }
756 
757 
758 double
760  assert(myLaneTimeLine.size() >= 2);
761  assert(currentTime >= myLaneTimeLine[0].first);
762  return STEPS2TIME(myLaneTimeLine[1].first - currentTime);
763 }
764 
765 
766 void
768  myConsiderSafeVelocity = ((speedMode & 1) != 0);
769  myConsiderMaxAcceleration = ((speedMode & 2) != 0);
770  myConsiderMaxDeceleration = ((speedMode & 4) != 0);
771  myRespectJunctionPriority = ((speedMode & 8) != 0);
772  myEmergencyBrakeRedLight = ((speedMode & 16) != 0);
773  myRespectJunctionLeaderPriority = ((speedMode & 32) == 0); // inverted!
774 }
775 
776 
777 void
779  myStrategicLC = (LaneChangeMode)(value & (1 + 2));
780  myCooperativeLC = (LaneChangeMode)((value & (4 + 8)) >> 2);
781  mySpeedGainLC = (LaneChangeMode)((value & (16 + 32)) >> 4);
782  myRightDriveLC = (LaneChangeMode)((value & (64 + 128)) >> 6);
783  myTraciLaneChangePriority = (TraciLaneChangePriority)((value & (256 + 512)) >> 8);
784  mySublaneLC = (LaneChangeMode)((value & (1024 + 2048)) >> 10);
785 }
786 
787 
788 void
789 MSVehicle::Influencer::setRemoteControlled(Position xyPos, MSLane* l, double pos, double posLat, double angle, int edgeOffset, const ConstMSEdgeVector& route, SUMOTime t) {
790  myRemoteXYPos = xyPos;
791  myRemoteLane = l;
792  myRemotePos = pos;
793  myRemotePosLat = posLat;
794  myRemoteAngle = angle;
795  myRemoteEdgeOffset = edgeOffset;
796  myRemoteRoute = route;
797  myLastRemoteAccess = t;
798 }
799 
800 
801 bool
803  return myLastRemoteAccess == MSNet::getInstance()->getCurrentTimeStep();
804 }
805 
806 
807 bool
809  return myLastRemoteAccess >= t - TIME2STEPS(10);
810 }
811 
812 void
814  const bool wasOnRoad = v->isOnRoad();
815  const bool withinLane = myRemoteLane != nullptr && fabs(myRemotePosLat) < 0.5 * (myRemoteLane->getWidth() + v->getVehicleType().getWidth());
816  const bool keepLane = wasOnRoad && v->getLane() == myRemoteLane;
817  if (v->isOnRoad() && !(keepLane && withinLane)) {
818  if (myRemoteLane != nullptr && &v->getLane()->getEdge() == &myRemoteLane->getEdge()) {
819  // correct odometer which gets incremented via onRemovalFromNet->leaveLane
820  v->myOdometer -= v->getLane()->getLength();
821  }
824  }
825  if (myRemoteRoute.size() != 0) {
826  v->replaceRouteEdges(myRemoteRoute, -1, 0, "traci:moveToXY", true);
827  }
828  v->myCurrEdge = v->getRoute().begin() + myRemoteEdgeOffset;
829  if (myRemoteLane != nullptr && myRemotePos > myRemoteLane->getLength()) {
830  myRemotePos = myRemoteLane->getLength();
831  }
832  if (myRemoteLane != nullptr && withinLane) {
833  if (keepLane) {
834  v->myState.myPos = myRemotePos;
835  v->myState.myPosLat = myRemotePosLat;
836  } else {
840  myRemoteLane->forceVehicleInsertion(v, myRemotePos, notify, myRemotePosLat);
841  v->updateBestLanes();
842  }
843  if (!wasOnRoad) {
844  v->drawOutsideNetwork(false);
845  }
846  //std::cout << "on road network p=" << myRemoteXYPos << " a=" << myRemoteAngle << " l=" << Named::getIDSecure(myRemoteLane) << " pos=" << myRemotePos << " posLat=" << myRemotePosLat << "\n";
847  } else {
848  if (v->getDeparture() == NOT_YET_DEPARTED) {
849  v->onDepart();
850  }
851  v->drawOutsideNetwork(true);
852  // see updateState
853  double vNext = v->processTraCISpeedControl(
854  v->getVehicleType().getMaxSpeed(), v->getSpeed());
855  v->setBrakingSignals(vNext);
856  v->updateWaitingTime(vNext);
857  v->myState.myPreviousSpeed = v->getSpeed();
858  v->myAcceleration = SPEED2ACCEL(vNext - v->getSpeed());
859  v->myState.mySpeed = vNext;
860  //std::cout << "outside network p=" << myRemoteXYPos << " a=" << myRemoteAngle << " l=" << Named::getIDSecure(myRemoteLane) << "\n";
861  }
862  // ensure that the position is correct (i.e. when the lanePosition is ambiguous at corners)
863  v->setRemoteState(myRemoteXYPos);
864  v->setAngle(GeomHelper::fromNaviDegree(myRemoteAngle));
865 }
866 
867 
868 double
870  if (veh->getPosition() == Position::INVALID) {
871  return oldSpeed;
872  }
873  double dist = veh->getPosition().distanceTo2D(myRemoteXYPos);
874  if (myRemoteLane != nullptr) {
875  // if the vehicles is frequently placed on a new edge, the route may
876  // consist only of a single edge. In this case the new edge may not be
877  // on the route so distAlongRoute will be double::max.
878  // In this case we still want a sensible speed value
879  const double distAlongRoute = veh->getDistanceToPosition(myRemotePos, &myRemoteLane->getEdge());
880  if (distAlongRoute != std::numeric_limits<double>::max()) {
881  dist = distAlongRoute;
882  }
883  }
884  //std::cout << SIMTIME << " veh=" << veh->getID() << " oldPos=" << veh->getPosition() << " traciPos=" << myRemoteXYPos << " dist=" << dist << "\n";
885  const double minSpeed = myConsiderMaxDeceleration ?
886  veh->getCarFollowModel().minNextSpeedEmergency(oldSpeed, veh) : 0;
887  const double maxSpeed = (myRemoteLane != nullptr
888  ? myRemoteLane->getVehicleMaxSpeed(veh)
889  : (veh->getLane() != nullptr
890  ? veh->getLane()->getVehicleMaxSpeed(veh)
891  : veh->getVehicleType().getMaxSpeed()));
892  return MIN2(maxSpeed, MAX2(minSpeed, DIST2SPEED(dist)));
893 }
894 
895 double
897  double dist = 0;
898  if (myRemoteLane == nullptr) {
899  dist = veh->getPosition().distanceTo2D(myRemoteXYPos);
900  } else {
901  // if the vehicles is frequently placed on a new edge, the route may
902  // consist only of a single edge. In this case the new edge may not be
903  // on the route so getDistanceToPosition will return double::max.
904  // In this case we would rather not move the vehicle in executeMove
905  // (updateState) as it would result in emergency braking
906  dist = veh->getDistanceToPosition(myRemotePos, &myRemoteLane->getEdge());
907  }
908  if (DIST2SPEED(dist) > veh->getMaxSpeed()) {
909  return 0;
910  } else {
911  return dist;
912  }
913 }
914 
915 
916 /* -------------------------------------------------------------------------
917  * MSVehicle-methods
918  * ----------------------------------------------------------------------- */
920  MSVehicleType* type, const double speedFactor) :
921  MSBaseVehicle(pars, route, type, speedFactor),
922  myWaitingTime(0),
924  myTimeLoss(0),
925  myState(0, 0, 0, 0),
926  myDriverState(nullptr),
927  myActionStep(true),
928  myLastActionTime(0),
929  myLane(nullptr),
930  myLaneChangeModel(nullptr),
931  myLastBestLanesEdge(nullptr),
933  myAcceleration(0),
935  mySignals(0),
936  myAmOnNet(false),
937  myAmIdling(false),
940  myHaveToWaitOnNextLink(false),
941  myAngle(0),
942  myStopDist(std::numeric_limits<double>::max()),
948  myInfluencer(nullptr) {
950  myNextDriveItem = myLFLinkLanes.begin();
951 }
952 
953 
955  for (std::vector<MSLane*>::iterator i = myFurtherLanes.begin(); i != myFurtherLanes.end(); ++i) {
956  (*i)->resetPartialOccupation(this);
957  }
958  if (myLaneChangeModel != nullptr) {
962  // still needed when calling resetPartialOccupation (getShadowLane) and when removing
963  // approach information from parallel links
964  delete myLaneChangeModel;
965  }
966  myFurtherLanes.clear();
967  myFurtherLanesPosLat.clear();
968  //
969  if (myType->isVehicleSpecific()) {
971  }
972  delete myInfluencer;
973  delete myCFVariables;
974 }
975 
976 
977 void
979 #ifdef DEBUG_ACTIONSTEPS
980  if (DEBUG_COND) {
981  std::cout << SIMTIME << " Removing vehicle '" << getID() << "' (reason: " << toString(reason) << ")" << std::endl;
982  }
983 #endif
986  leaveLane(reason);
987 }
988 
989 
990 void
995 }
996 
997 
998 // ------------ interaction with the route
999 bool
1001  // note: not a const method because getDepartLane may call updateBestLanes
1002  if (!(*myCurrEdge)->isTazConnector()) {
1004  if ((*myCurrEdge)->getDepartLane(*this) == nullptr) {
1005  msg = "Invalid departlane definition for vehicle '" + getID() + "'.";
1006  if (myParameter->departLane >= (int)(*myCurrEdge)->getLanes().size()) {
1008  } else {
1010  }
1011  return false;
1012  }
1013  } else {
1014  if ((*myCurrEdge)->allowedLanes(getVClass()) == nullptr) {
1015  msg = "Vehicle '" + getID() + "' is not allowed to depart on any lane of edge '" + (*myCurrEdge)->getID() + "'.";
1017  return false;
1018  }
1019  }
1021  msg = "Departure speed for vehicle '" + getID() + "' is too high for the vehicle type '" + myType->getID() + "'.";
1023  return false;
1024  }
1025  }
1027  return true;
1028 }
1029 
1030 
1031 bool
1033  return hasArrivedInternal(false);
1034 }
1035 
1036 
1037 bool
1038 MSVehicle::hasArrivedInternal(bool oppositeTransformed) const {
1039  return ((myCurrEdge == myRoute->end() - 1 || (myParameter->arrivalEdge >= 0 && getRoutePosition() >= myParameter->arrivalEdge))
1040  && (myStops.empty() || myStops.front().edge != myCurrEdge)
1041  && ((myLaneChangeModel->isOpposite() && !oppositeTransformed) ? myLane->getLength() - myState.myPos : myState.myPos) > myArrivalPos - POSITION_EPS
1042  && !isRemoteControlled());
1043 }
1044 
1045 
1046 bool
1047 MSVehicle::replaceRoute(const MSRoute* newRoute, const std::string& info, bool onInit, int offset, bool addRouteStops, bool removeStops, std::string* msgReturn) {
1048  if (MSBaseVehicle::replaceRoute(newRoute, info, onInit, offset, addRouteStops, removeStops, msgReturn)) {
1049  // update best lanes (after stops were added)
1050  myLastBestLanesEdge = nullptr;
1051  myLastBestLanesInternalLane = nullptr;
1052  updateBestLanes(true, onInit ? (*myCurrEdge)->getLanes().front() : 0);
1053  assert(!removeStops || haveValidStopEdges());
1054  return true;
1055  }
1056  return false;
1057 }
1058 
1059 
1060 // ------------ Interaction with move reminders
1061 void
1062 MSVehicle::workOnMoveReminders(double oldPos, double newPos, double newSpeed) {
1063  // This erasure-idiom works for all stl-sequence-containers
1064  // See Meyers: Effective STL, Item 9
1065  for (MoveReminderCont::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end();) {
1066  // XXX: calling notifyMove with newSpeed seems not the best choice. For the ballistic update, the average speed is calculated and used
1067  // although a higher order quadrature-formula might be more adequate.
1068  // For the euler case (where the speed is considered constant for each time step) it is conceivable that
1069  // the current calculations may lead to systematic errors for large time steps (compared to reality). Refs. #2579
1070  if (!rem->first->notifyMove(*this, oldPos + rem->second, newPos + rem->second, MAX2(0., newSpeed))) {
1071 #ifdef _DEBUG
1072  if (myTraceMoveReminders) {
1073  traceMoveReminder("notifyMove", rem->first, rem->second, false);
1074  }
1075 #endif
1076  rem = myMoveReminders.erase(rem);
1077  } else {
1078 #ifdef _DEBUG
1079  if (myTraceMoveReminders) {
1080  traceMoveReminder("notifyMove", rem->first, rem->second, true);
1081  }
1082 #endif
1083  ++rem;
1084  }
1085  }
1086 }
1087 
1088 void
1090  updateWaitingTime(0.); // cf issue 2233
1091 
1092  // vehicle move reminders
1093  for (MoveReminderCont::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end();) {
1094  rem->first->notifyIdle(*this);
1095  ++rem;
1096  }
1097 
1098  // lane move reminders - for aggregated values
1099  for (MSMoveReminder* rem : getLane()->getMoveReminders()) {
1100  rem->notifyIdle(*this);
1101  }
1102 }
1103 
1104 // XXX: consider renaming...
1105 void
1107  // save the old work reminders, patching the position information
1108  // add the information about the new offset to the old lane reminders
1109  const double oldLaneLength = myLane->getLength();
1110  for (MoveReminderCont::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end(); ++rem) {
1111  rem->second += oldLaneLength;
1112 #ifdef _DEBUG
1113 // if (rem->first==0) std::cout << "Null reminder (?!)" << std::endl;
1114 // std::cout << "Adapted MoveReminder on lane " << ((rem->first->getLane()==0) ? "NULL" : rem->first->getLane()->getID()) <<" position to " << rem->second << std::endl;
1115  if (myTraceMoveReminders) {
1116  traceMoveReminder("adaptedPos", rem->first, rem->second, true);
1117  }
1118 #endif
1119  }
1120  for (std::vector< MSMoveReminder* >::const_iterator rem = enteredLane.getMoveReminders().begin(); rem != enteredLane.getMoveReminders().end(); ++rem) {
1121  addReminder(*rem);
1122  }
1123 }
1124 
1125 
1126 // ------------ Other getter methods
1127 double
1129  if (!isOnRoad() && isParking() && getStops().begin()->parkingarea != nullptr) {
1130  return getStops().begin()->parkingarea->getVehicleSlope(*this);
1131  }
1132  if (myLane == nullptr) {
1133  return 0;
1134  }
1135  const double lp = getPositionOnLane();
1136  const double gp = myLane->interpolateLanePosToGeometryPos(lp);
1137  return myLane->getShape().slopeDegreeAtOffset(gp);
1138 }
1139 
1140 
1141 Position
1142 MSVehicle::getPosition(const double offset) const {
1143  if (myLane == nullptr) {
1144  // when called in the context of GUI-Drawing, the simulation step is already incremented
1146  return myCachedPosition;
1147  } else {
1148  return Position::INVALID;
1149  }
1150  }
1151  if (isParking()) {
1152  if (myStops.begin()->parkingarea != nullptr) {
1153  return myStops.begin()->parkingarea->getVehiclePosition(*this);
1154  } else {
1155  // position beside the road
1156  PositionVector shp = myLane->getEdge().getLanes()[0]->getShape();
1159  }
1160  }
1161  const bool changingLanes = myLaneChangeModel->isChangingLanes();
1162  const double posLat = (MSGlobals::gLefthand ? 1 : -1) * getLateralPositionOnLane();
1163  if (offset == 0. && !changingLanes) {
1166  }
1167  return myCachedPosition;
1168  }
1169  Position result = validatePosition(myLane->geometryPositionAtOffset(getPositionOnLane() + offset, posLat), offset);
1170  return result;
1171 }
1172 
1173 
1174 Position
1177  if (!isOnRoad()) {
1178  return Position::INVALID;
1179  }
1180  const std::vector<MSLane*>& bestLanes = getBestLanesContinuation();
1181  auto nextBestLane = bestLanes.begin();
1182  const bool opposite = myLaneChangeModel->isOpposite();
1183  double pos = opposite ? myLane->getLength() - myState.myPos : myState.myPos;
1184  const MSLane* lane = opposite ? myLane->getParallelOpposite() : getLane();
1185  assert(lane != 0);
1186  bool success = true;
1187 
1188  while (offset > 0) {
1189  // take into account lengths along internal lanes
1190  while (lane->isInternal() && offset > 0) {
1191  if (offset > lane->getLength() - pos) {
1192  offset -= lane->getLength() - pos;
1193  lane = lane->getLinkCont()[0]->getViaLaneOrLane();
1194  pos = 0.;
1195  if (lane == nullptr) {
1196  success = false;
1197  offset = 0.;
1198  }
1199  } else {
1200  pos += offset;
1201  offset = 0;
1202  }
1203  }
1204  // set nextBestLane to next non-internal lane
1205  while (nextBestLane != bestLanes.end() && *nextBestLane == nullptr) {
1206  ++nextBestLane;
1207  }
1208  if (offset > 0) {
1209  assert(!lane->isInternal());
1210  assert(lane == *nextBestLane);
1211  if (offset > lane->getLength() - pos) {
1212  offset -= lane->getLength() - pos;
1213  ++nextBestLane;
1214  assert(nextBestLane == bestLanes.end() || *nextBestLane != 0);
1215  if (nextBestLane == bestLanes.end()) {
1216  success = false;
1217  offset = 0.;
1218  } else {
1219  const MSLink* link = lane->getLinkTo(*nextBestLane);
1220  assert(link != nullptr);
1221  lane = link->getViaLaneOrLane();
1222  pos = 0.;
1223  }
1224  } else {
1225  pos += offset;
1226  offset = 0;
1227  }
1228  }
1229 
1230  }
1231 
1232  if (success) {
1233  return lane->geometryPositionAtOffset(pos, -getLateralPositionOnLane());
1234  } else {
1235  return Position::INVALID;
1236  }
1237 }
1238 
1239 
1240 double
1242  if (myLane != nullptr) {
1243  return myLane->getVehicleMaxSpeed(this);
1244  }
1245  return myType->getMaxSpeed();
1246 }
1247 
1248 
1249 Position
1250 MSVehicle::validatePosition(Position result, double offset) const {
1251  int furtherIndex = 0;
1252  double lastLength = getPositionOnLane();
1253  while (result == Position::INVALID) {
1254  if (furtherIndex >= (int)myFurtherLanes.size()) {
1255  //WRITE_WARNING("Could not compute position for vehicle '" + getID() + "', time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
1256  break;
1257  }
1258  //std::cout << SIMTIME << " veh=" << getID() << " lane=" << myLane->getID() << " pos=" << getPositionOnLane() << " posLat=" << getLateralPositionOnLane() << " offset=" << offset << " result=" << result << " i=" << furtherIndex << " further=" << myFurtherLanes.size() << "\n";
1259  MSLane* further = myFurtherLanes[furtherIndex];
1260  offset += lastLength;
1261  result = further->geometryPositionAtOffset(further->getLength() + offset, -getLateralPositionOnLane());
1262  lastLength = further->getLength();
1263  furtherIndex++;
1264  //std::cout << SIMTIME << " newResult=" << result << "\n";
1265  }
1266  return result;
1267 }
1268 
1269 
1270 const MSEdge*
1272  // too close to the next junction, so avoid an emergency brake here
1273  if (myLane != nullptr && (myCurrEdge + 1) != myRoute->end() &&
1274  myState.myPos > myLane->getLength() - getCarFollowModel().brakeGap(myState.mySpeed, getCarFollowModel().getMaxDecel(), 0.)) {
1275  return *(myCurrEdge + 1);
1276  }
1277  if (myLane != nullptr) {
1278  return myLane->getNextNormal();
1279  }
1280  return *myCurrEdge;
1281 }
1282 
1283 void
1284 MSVehicle::setAngle(double angle, bool straightenFurther) {
1285 #ifdef DEBUG_FURTHER
1286  if (DEBUG_COND) {
1287  std::cout << SIMTIME << " veh '" << getID() << " setAngle(" << angle << ") straightenFurther=" << straightenFurther << std::endl;
1288  }
1289 #endif
1290  myAngle = angle;
1291  MSLane* next = myLane;
1292  if (straightenFurther && myFurtherLanesPosLat.size() > 0) {
1293  for (int i = 0; i < (int)myFurtherLanes.size(); i++) {
1294  MSLane* further = myFurtherLanes[i];
1295  if (further->getLinkTo(next) != nullptr) {
1297  next = further;
1298  } else {
1299  break;
1300  }
1301  }
1302  }
1303 }
1304 
1305 
1306 void
1307 MSVehicle::setActionStepLength(double actionStepLength, bool resetOffset) {
1308  SUMOTime actionStepLengthMillisecs = SUMOVehicleParserHelper::processActionStepLength(actionStepLength);
1309  SUMOTime previousActionStepLength = getActionStepLength();
1310  const bool newActionStepLength = actionStepLengthMillisecs != previousActionStepLength;
1311  if (newActionStepLength) {
1312  getSingularType().setActionStepLength(actionStepLengthMillisecs, resetOffset);
1313  if (!resetOffset) {
1314  updateActionOffset(previousActionStepLength, actionStepLengthMillisecs);
1315  }
1316  }
1317  if (resetOffset) {
1319  }
1320 }
1321 
1322 
1323 bool
1325  return myState.mySpeed < (60.0 / 3.6) || myLane->getSpeedLimit() < (60.1 / 3.6);
1326 }
1327 
1328 
1329 double
1331  Position p1;
1332  const double posLat = -myState.myPosLat; // @todo get rid of the '-'
1333  const double lefthandSign = (MSGlobals::gLefthand ? -1 : 1);
1334 
1335  // if parking manoeuvre is happening then rotate vehicle on each step
1337  return getAngle() + myManoeuvre.getGUIIncrement();
1338  }
1339 
1340  if (isParking()) {
1341  if (myStops.begin()->parkingarea != nullptr) {
1342  return myStops.begin()->parkingarea->getVehicleAngle(*this);
1343  } else {
1345  }
1346  }
1348  // cannot use getPosition() because it already includes the offset to the side and thus messes up the angle
1349  p1 = myLane->geometryPositionAtOffset(myState.myPos, lefthandSign * posLat);
1350  } else {
1351  p1 = getPosition();
1352  }
1353 
1354  Position p2 = getBackPosition();
1355  if (p2 == Position::INVALID) {
1356  // Handle special case of vehicle's back reaching out of the network
1357  if (myFurtherLanes.size() > 0) {
1358  p2 = myFurtherLanes.back()->geometryPositionAtOffset(0, -myFurtherLanesPosLat.back());
1359  if (p2 == Position::INVALID) {
1360  // unsuitable lane geometry
1361  p2 = myLane->geometryPositionAtOffset(0, posLat);
1362  }
1363  } else {
1364  p2 = myLane->geometryPositionAtOffset(0, posLat);
1365  }
1366  }
1367  double result = (p1 != p2 ? p2.angleTo2D(p1) :
1370  result += lefthandSign * DEG2RAD(myLaneChangeModel->getAngleOffset());
1371  }
1372 #ifdef DEBUG_FURTHER
1373  if (DEBUG_COND) {
1374  std::cout << SIMTIME << " computeAngle veh=" << getID() << " p1=" << p1 << " p2=" << p2 << " angle=" << RAD2DEG(result) << " naviDegree=" << GeomHelper::naviDegree(result) << "\n";
1375  }
1376 #endif
1377  return result;
1378 }
1379 
1380 
1381 const Position
1383  const double posLat = MSGlobals::gLefthand ? myState.myPosLat : -myState.myPosLat;
1384  if (myState.myPos >= myType->getLength()) {
1385  // vehicle is fully on the new lane
1387  } else {
1388  if (myLaneChangeModel->isChangingLanes() && myFurtherLanes.size() > 0 && myLaneChangeModel->getShadowLane(myFurtherLanes.back()) == nullptr) {
1389  // special case where the target lane has no predecessor
1390 #ifdef DEBUG_FURTHER
1391  if (DEBUG_COND) {
1392  std::cout << " getBackPosition veh=" << getID() << " specialCase using myLane=" << myLane->getID() << " pos=0 posLat=" << myState.myPosLat << " result=" << myLane->geometryPositionAtOffset(0, posLat) << "\n";
1393  }
1394 #endif
1395  return myLane->geometryPositionAtOffset(0, posLat);
1396  } else {
1397 #ifdef DEBUG_FURTHER
1398  if (DEBUG_COND) {
1399  std::cout << " getBackPosition veh=" << getID() << " myLane=" << myLane->getID() << " further=" << toString(myFurtherLanes) << " myFurtherLanesPosLat=" << toString(myFurtherLanesPosLat) << "\n";
1400  }
1401 #endif
1402  return myFurtherLanes.size() > 0 && !myLaneChangeModel->isChangingLanes()
1403  ? myFurtherLanes.back()->geometryPositionAtOffset(getBackPositionOnLane(myFurtherLanes.back()), -myFurtherLanesPosLat.back() * (MSGlobals::gLefthand ? -1 : 1))
1404  : myLane->geometryPositionAtOffset(0, posLat);
1405  }
1406  }
1407 }
1408 
1409 
1410 bool
1411 MSVehicle::replaceParkingArea(MSParkingArea* parkingArea, std::string& errorMsg) {
1412  // Check if there is a parking area to be replaced
1413  if (parkingArea == 0) {
1414  errorMsg = "new parkingArea is NULL";
1415  return false;
1416  }
1417  if (myStops.size() == 0) {
1418  errorMsg = "vehicle has no stops";
1419  return false;
1420  }
1421  if (myStops.front().parkingarea == 0) {
1422  errorMsg = "first stop is not at parkingArea";
1423  return false;
1424  }
1425  MSStop& first = myStops.front();
1426  SUMOVehicleParameter::Stop& stopPar = const_cast<SUMOVehicleParameter::Stop&>(first.pars);
1427  // merge subsequent duplicate stops equals to parking area
1428  for (std::list<MSStop>::iterator iter = ++myStops.begin(); iter != myStops.end();) {
1429  if (iter->parkingarea == parkingArea) {
1430  stopPar.duration += iter->duration;
1431  myStops.erase(iter++);
1432  } else {
1433  break;
1434  }
1435  }
1436  stopPar.lane = parkingArea->getLane().getID();
1437  stopPar.parkingarea = parkingArea->getID();
1438  stopPar.startPos = parkingArea->getBeginLanePosition();
1439  stopPar.endPos = parkingArea->getEndLanePosition();
1440  first.edge = myRoute->end(); // will be patched in replaceRoute
1441  first.lane = &parkingArea->getLane();
1442  first.parkingarea = parkingArea;
1443  return true;
1444 }
1445 
1446 
1449  MSParkingArea* nextParkingArea = nullptr;
1450  if (!myStops.empty()) {
1452  MSStop stop = myStops.front();
1453  if (!stop.reached && stop.parkingarea != nullptr) {
1454  nextParkingArea = stop.parkingarea;
1455  }
1456  }
1457  return nextParkingArea;
1458 }
1459 
1460 
1463  MSParkingArea* currentParkingArea = nullptr;
1464  if (isParking()) {
1465  currentParkingArea = myStops.begin()->parkingarea;
1466  }
1467  return currentParkingArea;
1468 }
1469 
1470 
1471 bool
1473  return !isStopped() && !myStops.empty() && myLane != nullptr && &myStops.front().lane->getEdge() == &myLane->getEdge();
1474 }
1475 
1476 bool
1478  return isStopped() && myStops.front().lane == myLane;
1479 }
1480 
1481 bool
1482 MSVehicle::keepStopping(bool afterProcessing) const {
1483  if (isStopped()) {
1484  // when coming out of vehicleTransfer we must shift the time forward
1485  return (myStops.front().duration - (afterProcessing ? DELTA_T : 0) > 0 || isStoppedTriggered() || myStops.front().collision
1486  || (myStops.front().pars.speed > 0 && myState.myPos < MIN2(myStops.front().pars.endPos, myStops.front().lane->getLength() - POSITION_EPS)));
1487  } else {
1488  return false;
1489  }
1490 }
1491 
1492 
1493 SUMOTime
1495  if (isStopped()) {
1496  return myStops.front().duration;
1497  }
1498  return 0;
1499 }
1500 
1501 
1502 SUMOTime
1504  return (myStops.empty() || !myStops.front().collision) ? myCollisionImmunity : MAX2((SUMOTime)0, myStops.front().duration);
1505 }
1506 
1507 
1508 bool
1510  return myCollisionImmunity > 0;
1511 }
1512 
1513 
1514 double
1515 MSVehicle::processNextStop(double currentVelocity) {
1516  if (myStops.empty()) {
1517  // no stops; pass
1518  return currentVelocity;
1519  }
1520 
1521 #ifdef DEBUG_STOPS
1522  if (DEBUG_COND) {
1523  std::cout << "\nPROCESS_NEXT_STOP\n" << SIMTIME << " vehicle '" << getID() << "'" << std::endl;
1524  }
1525 #endif
1526 
1527  MSStop& stop = myStops.front();
1529  if (stop.reached) {
1530  stop.duration -= getActionStepLength();
1531 
1532 #ifdef DEBUG_STOPS
1533  if (DEBUG_COND) {
1534  std::cout << SIMTIME << " vehicle '" << getID() << "' reached stop.\n"
1535  << "Remaining duration: " << STEPS2TIME(stop.duration) << std::endl;
1536  if (stop.pars.speed > 0) {
1537  std::cout << " waypointSpeed=" << stop.pars.speed << "vehPos=" << myState.myPos << " endPos=" << stop.pars.endPos << "\n";
1538  }
1539  }
1540 #endif
1541  if (stop.duration <= 0 && stop.pars.join != "") {
1542  // join this train (part) to another one
1543  MSVehicle* joinVeh = dynamic_cast<MSVehicle*>(MSNet::getInstance()->getVehicleControl().getVehicle(stop.pars.join));
1544  if (joinVeh && (joinVeh->joinTrainPart(this) || joinVeh->joinTrainPartFront(this))) {
1545  stop.joinTriggered = false;
1546  // avoid collision warning before this vehicle is removed (joinVeh was already made longer)
1548  // mark this vehicle as arrived
1550  }
1551  }
1552  if (!keepStopping() && isOnRoad()) {
1553 #ifdef DEBUG_STOPS
1554  if (DEBUG_COND) {
1555  std::cout << SIMTIME << " vehicle '" << getID() << "' resumes from stopping." << std::endl;
1556  }
1557 #endif
1559  if (isRailway(getVClass())
1560  && hasStops()) {
1561  // stay on the current lane in case of a double stop
1562  const MSStop& nextStop = getNextStop();
1563  if (nextStop.edge == myCurrEdge) {
1564  const double stopSpeed = getCarFollowModel().stopSpeed(this, getSpeed(), nextStop.pars.endPos - myState.myPos);
1565  //std::cout << SIMTIME << " veh=" << getID() << " resumedFromStopping currentVelocity=" << currentVelocity << " stopSpeed=" << stopSpeed << "\n";
1566  return stopSpeed;
1567  }
1568  }
1569  } else {
1570  if (isParking()) {
1571  // called via MSVehicleTransfer
1572  for (MSVehicleDevice* const dev : myDevices) {
1573  dev->notifyParking();
1574  }
1575  }
1576  boardTransportables(stop);
1577 
1579  if (getVehicleType().getPersonCapacity() == getPersonNumber()) {
1580  WRITE_WARNING("Vehicle '" + getID() + "' ignores triggered stop on lane '" + stop.lane->getID() + "' due to capacity constraints.");
1581  stop.triggered = false;
1582  }
1583  // we can only register after waiting for one step. otherwise we might falsely signal a deadlock
1586  }
1588 #ifdef DEBUG_STOPS
1589  if (DEBUG_COND) {
1590  std::cout << SIMTIME << " vehicle '" << getID() << "' registers as waiting for person." << std::endl;
1591  }
1592 #endif
1593  }
1595  if (getVehicleType().getContainerCapacity() == getContainerNumber()) {
1596  WRITE_WARNING("Vehicle '" + getID() + "' ignores container triggered stop on lane '" + stop.lane->getID() + "' due to capacity constraints.");
1597  stop.containerTriggered = false;
1598  }
1599  // we can only register after waiting for one step. otherwise we might falsely signal a deadlock
1602  }
1604 #ifdef DEBUG_STOPS
1605  if (DEBUG_COND) {
1606  std::cout << SIMTIME << " vehicle '" << getID() << "' registers as waiting for container." << std::endl;
1607  }
1608 #endif
1609  }
1610  if (stop.pars.speed > 0) {
1611  //waypoint mode
1612  if (stop.duration == 0) {
1613  return stop.pars.speed;
1614  } else {
1615  // stop for 'until' (computed in planMove)
1616  return currentVelocity;
1617  }
1618  } else {
1619  // brake
1621  return 0;
1622  } else {
1623  // ballistic:
1624  return getSpeed() - getCarFollowModel().getMaxDecel();
1625  }
1626  }
1627  }
1628  } else {
1629 
1630 #ifdef DEBUG_STOPS
1631  if (DEBUG_COND) {
1632  std::cout << SIMTIME << " vehicle '" << getID() << "' hasn't reached next stop." << std::endl;
1633  }
1634 #endif
1635 
1636  // is the next stop on the current lane?
1637  if (stop.edge == myCurrEdge) {
1638  // get the stopping position
1639  bool useStoppingPlace = stop.busstop != nullptr || stop.containerstop != nullptr || stop.parkingarea != nullptr;
1640  bool fitsOnStoppingPlace = true;
1641  if (stop.busstop != nullptr) {
1642  fitsOnStoppingPlace &= stop.busstop->fits(myState.myPos, *this);
1643  }
1644  if (stop.containerstop != nullptr) {
1645  fitsOnStoppingPlace &= stop.containerstop->fits(myState.myPos, *this);
1646  }
1647  // if the stop is a parking area we check if there is a free position on the area
1648  if (stop.parkingarea != nullptr) {
1649  fitsOnStoppingPlace &= myState.myPos > stop.parkingarea->getBeginLanePosition();
1650  if (stop.parkingarea->getOccupancy() >= stop.parkingarea->getCapacity()) {
1651  fitsOnStoppingPlace = false;
1652  // trigger potential parkingZoneReroute
1653  for (std::vector< MSMoveReminder* >::const_iterator rem = myLane->getMoveReminders().begin(); rem != myLane->getMoveReminders().end(); ++rem) {
1654  addReminder(*rem);
1655  }
1656  MSParkingArea* oldParkingArea = stop.parkingarea;
1658  if (myStops.empty() || myStops.front().parkingarea != oldParkingArea) {
1659  // rerouted, keep driving
1660  return currentVelocity;
1661  }
1662  } else if (stop.parkingarea->getOccupancyIncludingBlocked() >= stop.parkingarea->getCapacity()) {
1663  fitsOnStoppingPlace = false;
1664  } else if (stop.parkingarea->parkOnRoad() && stop.parkingarea->getLotIndex(this) < 0) {
1665  fitsOnStoppingPlace = false;
1666  }
1667  }
1668  const double targetPos = myState.myPos + myStopDist + (stop.pars.speed > 0 ? (stop.pars.startPos - stop.pars.endPos) : 0);
1669  const double reachedThreshold = (useStoppingPlace ? targetPos - STOPPING_PLACE_OFFSET : stop.getReachedThreshold()) - NUMERICAL_EPS;
1670 #ifdef DEBUG_STOPS
1671  if (DEBUG_COND) {
1672  std::cout << " pos=" << myState.pos() << " speed=" << currentVelocity << " targetPos=" << targetPos << " fits=" << fitsOnStoppingPlace
1673  << " reachedThresh=" << reachedThreshold
1674  << " myLane=" << Named::getIDSecure(myLane)
1675  << " stopLane=" << Named::getIDSecure(stop.lane)
1676  << "\n";
1677  }
1678 #endif
1679  if (myState.pos() >= reachedThreshold && fitsOnStoppingPlace && currentVelocity <= stop.pars.speed + SUMO_const_haltingSpeed && myLane == stop.lane
1681  // ok, we may stop (have reached the stop) and either we are not modelling manoeuvering or have completed entry
1682  stop.reached = true;
1683  if (stop.pars.started == -1) { // if not we are probably loading a state
1684  stop.pars.started = time;
1685  }
1686 #ifdef DEBUG_STOPS
1687  if (DEBUG_COND) {
1688  std::cout << SIMTIME << " vehicle '" << getID() << "' reached next stop." << std::endl;
1689  }
1690 #endif
1691  if (MSStopOut::active()) {
1693  }
1694  myLane->getEdge().addWaiting(this);
1697  // compute stopping time
1698  if (stop.pars.until >= 0) {
1699  if (stop.duration == -1) {
1700  stop.duration = stop.pars.until - time;
1701  } else {
1702  stop.duration = MAX2(stop.duration, stop.pars.until - time);
1703  }
1704  }
1705  if (MSGlobals::gUseStopEnded && stop.pars.ended >= 0) {
1706  stop.duration = stop.pars.ended - time;
1707  }
1708  stop.endBoarding = stop.pars.extension >= 0 ? time + stop.duration + stop.pars.extension : SUMOTime_MAX;
1709  if (stop.pars.speed > 0) {
1710  // ignore duration parameter in waypoint mode
1711  if (stop.pars.until > time) {
1712  stop.duration = stop.pars.until - time;
1713  } else {
1714  stop.duration = 0;
1715  }
1716  }
1717  if (stop.busstop != nullptr) {
1718  // let the bus stop know the vehicle
1719  stop.busstop->enter(this, stop.pars.parking);
1720  }
1721  if (stop.containerstop != nullptr) {
1722  // let the container stop know the vehicle
1723  stop.containerstop->enter(this, stop.pars.parking);
1724  }
1725  if (stop.parkingarea != nullptr) {
1726  // let the parking area know the vehicle
1727  stop.parkingarea->enter(this);
1728  }
1729  if (stop.chargingStation != nullptr) {
1730  // let the container stop know the vehicle
1731  stop.chargingStation->enter(this, stop.pars.parking);
1732  }
1733 
1734  if (stop.pars.tripId != "") {
1735  ((SUMOVehicleParameter&)getParameter()).setParameter("tripId", stop.pars.tripId);
1736  }
1737  if (stop.pars.line != "") {
1738  ((SUMOVehicleParameter&)getParameter()).line = stop.pars.line;
1739  }
1740  if (stop.pars.split != "") {
1741  // split the train
1742  MSVehicle* splitVeh = dynamic_cast<MSVehicle*>(MSNet::getInstance()->getVehicleControl().getVehicle(stop.pars.split));
1743  if (splitVeh == nullptr) {
1744  WRITE_WARNINGF("Vehicle '%' to split from vehicle '%' is not known. time=%.", stop.pars.split, getID(), SIMTIME)
1745  } else {
1747  splitVeh->getRoute().getEdges()[0]->removeWaiting(splitVeh);
1749  const double newLength = MAX2(myType->getLength() - splitVeh->getVehicleType().getLength(),
1751  getSingularType().setLength(newLength);
1752  }
1753  }
1754 
1755  boardTransportables(stop);
1756  if (stop.pars.posLat != INVALID_DOUBLE) {
1757  myState.myPosLat = stop.pars.posLat;
1758  }
1759  }
1760  }
1761  }
1762  return currentVelocity;
1763 }
1764 
1765 
1766 void
1768  // we have reached the stop
1769  // any waiting persons may board now
1771  MSNet* const net = MSNet::getInstance();
1772  const bool boarded = (time <= stop.endBoarding
1773  && net->hasPersons()
1775  && stop.numExpectedPerson == 0);
1776  // load containers
1777  const bool loaded = (time <= stop.endBoarding
1778  && net->hasContainers()
1780  && stop.numExpectedContainer == 0);
1781 
1782  bool unregister = false;
1783  if (time > stop.endBoarding) {
1784  stop.triggered = false;
1785  stop.containerTriggered = false;
1787  unregister = true;
1790  }
1791  }
1792  if (boarded) {
1793  // the triggering condition has been fulfilled. Maybe we want to wait a bit longer for additional riders (car pooling)
1795  unregister = true;
1796  }
1797  stop.triggered = false;
1799  }
1800  if (loaded) {
1801  // the triggering condition has been fulfilled
1803  unregister = true;
1804  }
1805  stop.containerTriggered = false;
1807  }
1808 
1809  if (unregister) {
1811 #ifdef DEBUG_STOPS
1812  if (DEBUG_COND) {
1813  std::cout << SIMTIME << " vehicle '" << getID() << "' unregisters as waiting for transportable." << std::endl;
1814  }
1815 #endif
1816  }
1817 }
1818 
1819 bool
1821  // check if veh is close enough to be joined
1822  MSLane* backLane = myFurtherLanes.size() == 0 ? myLane : myFurtherLanes.back();
1823  double gap = getBackPositionOnLane() - veh->getPositionOnLane();
1824  if (isStopped() && myStops.begin()->joinTriggered && backLane == veh->getLane()
1825  && gap >= 0 && gap <= getVehicleType().getMinGap() + 1) {
1826  const double newLength = myType->getLength() + veh->getVehicleType().getLength();
1827  getSingularType().setLength(newLength);
1828  myStops.begin()->joinTriggered = false;
1829  return true;
1830  } else {
1831  return false;
1832  }
1833 }
1834 
1835 
1836 bool
1838  // check if veh is close enough to be joined
1839  MSLane* backLane = veh->myFurtherLanes.size() == 0 ? veh->myLane : veh->myFurtherLanes.back();
1840  double gap = veh->getBackPositionOnLane() - getPositionOnLane();
1841  if (isStopped() && myStops.begin()->joinTriggered && backLane == getLane()
1842  && gap >= 0 && gap <= getVehicleType().getMinGap() + 1) {
1843  if (veh->myFurtherLanes.size() > 0) {
1844  // this vehicle must be moved to the lane of veh
1845  // ensure that lane and furtherLanes of veh match our route
1846  int routeIndex = getRoutePosition();
1847  if (myLane->isInternal()) {
1848  routeIndex++;
1849  }
1850  for (int i = (int)veh->myFurtherLanes.size() - 1; i >= 0; i--) {
1851  MSEdge* edge = &veh->myFurtherLanes[i]->getEdge();
1852  if (!edge->isInternal() && edge != myRoute->getEdges()[routeIndex]) {
1853  WRITE_WARNING("Cannot join vehicle '" + veh->getID() + " to vehicle '" + getID()
1854  + "' due to incompatible routes. time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()));
1855  return false;
1856  }
1857  }
1858  for (int i = (int)veh->myFurtherLanes.size() - 2; i >= 0; i--) {
1860  }
1861  }
1862  const double newLength = myType->getLength() + veh->getVehicleType().getLength();
1863  getSingularType().setLength(newLength);
1864  assert(myLane == veh->getLane());
1865  myState.myPos = veh->getPositionOnLane();
1866  myStops.begin()->joinTriggered = false;
1867  return true;
1868  } else {
1869  return false;
1870  }
1871 }
1872 
1873 bool
1875  if (stop == nullptr) {
1876  return false;
1877  }
1878  for (const MSStop& s : myStops) {
1879  if (s.busstop == stop
1880  || s.containerstop == stop
1881  || s.parkingarea == stop
1882  || s.chargingStation == stop) {
1883  return true;
1884  }
1885  }
1886  return false;
1887 }
1888 
1889 bool
1890 MSVehicle::stopsAtEdge(const MSEdge* edge) const {
1891  for (const MSStop& s : myStops) {
1892  if (&s.lane->getEdge() == edge) {
1893  return true;
1894  }
1895  }
1896  return false;
1897 }
1898 
1899 double
1900 MSVehicle::getBrakeGap(bool delayed) const {
1901  return getCarFollowModel().brakeGap(getSpeed(), getCarFollowModel().getMaxDecel(), delayed ? getCarFollowModel().getHeadwayTime() : 0);
1902 }
1903 
1904 
1905 bool
1908  if (myActionStep) {
1909  myLastActionTime = t;
1910  }
1911  return myActionStep;
1912 }
1913 
1914 
1915 void
1916 MSVehicle::resetActionOffset(const SUMOTime timeUntilNextAction) {
1917  myLastActionTime = MSNet::getInstance()->getCurrentTimeStep() + timeUntilNextAction;
1918 }
1919 
1920 
1921 void
1922 MSVehicle::updateActionOffset(const SUMOTime oldActionStepLength, const SUMOTime newActionStepLength) {
1924  SUMOTime timeSinceLastAction = now - myLastActionTime;
1925  if (timeSinceLastAction == 0) {
1926  // Action was scheduled now, may be delayed be new action step length
1927  timeSinceLastAction = oldActionStepLength;
1928  }
1929  if (timeSinceLastAction >= newActionStepLength) {
1930  // Action point required in this step
1931  myLastActionTime = now;
1932  } else {
1933  SUMOTime timeUntilNextAction = newActionStepLength - timeSinceLastAction;
1934  resetActionOffset(timeUntilNextAction);
1935  }
1936 }
1937 
1938 
1939 
1940 void
1941 MSVehicle::planMove(const SUMOTime t, const MSLeaderInfo& ahead, const double lengthsInFront) {
1942 #ifdef DEBUG_PLAN_MOVE
1943  if (DEBUG_COND) {
1944  std::cout
1945  << "\nPLAN_MOVE\n"
1946  << SIMTIME
1947  << std::setprecision(gPrecision)
1948  << " veh=" << getID()
1949  << " lane=" << myLane->getID()
1950  << " pos=" << getPositionOnLane()
1951  << " posLat=" << getLateralPositionOnLane()
1952  << " speed=" << getSpeed()
1953  << "\n";
1954  }
1955 #endif
1956  // Update the driver state
1957  if (hasDriverState()) {
1958  myDriverState->update();
1959  setActionStepLength(myDriverState->getDriverState()->getActionStepLength(), false);
1960  }
1961 
1962  if (!checkActionStep(t)) {
1963 #ifdef DEBUG_ACTIONSTEPS
1964  if (DEBUG_COND) {
1965  std::cout << STEPS2TIME(t) << " vehicle '" << getID() << "' skips action." << std::endl;
1966  }
1967 #endif
1968  // During non-action passed drive items still need to be removed
1969  // @todo rather work with updating myCurrentDriveItem (refs #3714)
1971  return;
1972  } else {
1973 #ifdef DEBUG_ACTIONSTEPS
1974  if (DEBUG_COND) {
1975  std::cout << STEPS2TIME(t) << " vehicle = '" << getID() << "' takes action." << std::endl;
1976  }
1977 #endif
1980 #ifdef DEBUG_PLAN_MOVE
1981  if (DEBUG_COND) {
1982  DriveItemVector::iterator i;
1983  for (i = myLFLinkLanes.begin(); i != myLFLinkLanes.end(); ++i) {
1984  std::cout
1985  << " vPass=" << (*i).myVLinkPass
1986  << " vWait=" << (*i).myVLinkWait
1987  << " linkLane=" << ((*i).myLink == 0 ? "NULL" : (*i).myLink->getViaLaneOrLane()->getID())
1988  << " request=" << (*i).mySetRequest
1989  << "\n";
1990  }
1991  }
1992 #endif
1993  checkRewindLinkLanes(lengthsInFront, myLFLinkLanes);
1994  myNextDriveItem = myLFLinkLanes.begin();
1995  // ideally would only do this with the call inside planMoveInternal - but that needs a const method
1996  // so this is a kludge here - nuisance as it adds an extra check in a busy loop
2000  }
2001  }
2002  }
2004 }
2005 
2006 void
2007 MSVehicle::planMoveInternal(const SUMOTime t, MSLeaderInfo ahead, DriveItemVector& lfLinks, double& newStopDist, std::pair<double, LinkDirection>& nextTurn) const {
2008  lfLinks.clear();
2009  newStopDist = std::numeric_limits<double>::max();
2010  //
2011  const MSCFModel& cfModel = getCarFollowModel();
2012  const double vehicleLength = getVehicleType().getLength();
2013  const double maxV = cfModel.maxNextSpeed(myState.mySpeed, this);
2014  const bool opposite = myLaneChangeModel->isOpposite();
2015  double laneMaxV = myLane->getVehicleMaxSpeed(this);
2016  const double vMinComfortable = cfModel.minNextSpeed(getSpeed(), this);
2017  double lateralShift = 0;
2018  if (isRailway((SVCPermissions)getVehicleType().getVehicleClass())) {
2019  // speed limits must hold for the whole length of the train
2020  for (MSLane* l : myFurtherLanes) {
2021  laneMaxV = MIN2(laneMaxV, l->getVehicleMaxSpeed(this));
2022 #ifdef DEBUG_PLAN_MOVE
2023  if (DEBUG_COND) {
2024  std::cout << " laneMaxV=" << laneMaxV << " lane=" << l->getID() << "\n";
2025  }
2026 #endif
2027  }
2028  }
2029  // speed limits are not emergencies (e.g. when the limit changes suddenly due to TraCI or a variableSpeedSignal)
2030  laneMaxV = MAX2(laneMaxV, vMinComfortable);
2032  laneMaxV = std::numeric_limits<double>::max();
2033  }
2034  // v is the initial maximum velocity of this vehicle in this step
2035  double v = cfModel.maximumLaneSpeedCF(maxV, laneMaxV);
2036  // if we are modelling parking then we dawdle until the manoeuvre is complete - by setting a very low max speed
2037  // in practice this only applies to exit manoeuvre because entry manoeuvre just delays setting stop.reached - when the vehicle is virtually stopped
2039  v = NUMERICAL_EPS_SPEED;
2040  }
2041 
2042  if (myInfluencer != nullptr) {
2043  const double vMin = MAX2(0., cfModel.minNextSpeed(myState.mySpeed, this));
2044 #ifdef DEBUG_TRACI
2045  if (DEBUG_COND) {
2046  std::cout << SIMTIME << " veh=" << getID() << " speedBeforeTraci=" << v;
2047  }
2048 #endif
2049  v = myInfluencer->influenceSpeed(MSNet::getInstance()->getCurrentTimeStep(), v, v, vMin, maxV);
2050 #ifdef DEBUG_TRACI
2051  if (DEBUG_COND) {
2052  std::cout << " influencedSpeed=" << v;
2053  }
2054 #endif
2055  v = myInfluencer->gapControlSpeed(MSNet::getInstance()->getCurrentTimeStep(), this, v, v, vMin, maxV);
2056 #ifdef DEBUG_TRACI
2057  if (DEBUG_COND) {
2058  std::cout << " gapControlSpeed=" << v << "\n";
2059  }
2060 #endif
2061  }
2062  // all links within dist are taken into account (potentially)
2063  const double dist = SPEED2DIST(maxV) + cfModel.brakeGap(maxV);
2064 
2065  const std::vector<MSLane*>& bestLaneConts = getBestLanesContinuation();
2066 #ifdef DEBUG_PLAN_MOVE
2067  if (DEBUG_COND) {
2068  std::cout << " dist=" << dist << " bestLaneConts=" << toString(bestLaneConts)
2069  << "\n maxV=" << maxV << " laneMaxV=" << laneMaxV << " v=" << v << "\n";
2070  }
2071 #endif
2072  assert(bestLaneConts.size() > 0);
2073  bool hadNonInternal = false;
2074  // the distance already "seen"; in the following always up to the end of the current "lane"
2075  double seen = opposite ? myState.myPos : myLane->getLength() - myState.myPos;
2076  nextTurn.first = seen;
2077  nextTurn.second = LinkDirection::NODIR;
2078  bool encounteredTurn = (MSGlobals::gLateralResolution <= 0); // next turn is only needed for sublane
2079  double seenNonInternal = 0;
2080  double seenInternal = myLane->isInternal() ? seen : 0;
2081  double vLinkPass = MIN2(cfModel.estimateSpeedAfterDistance(seen, v, cfModel.getMaxAccel()), laneMaxV); // upper bound
2082  int view = 0;
2083  DriveProcessItem* lastLink = nullptr;
2084  bool slowedDownForMinor = false; // whether the vehicle already had to slow down on approach to a minor link
2085  double mustSeeBeforeReversal = 0;
2086  // iterator over subsequent lanes and fill lfLinks until stopping distance or stopped
2087  const MSLane* lane = opposite ? myLane->getParallelOpposite() : myLane;
2088  assert(lane != 0);
2089  const MSLane* leaderLane = myLane;
2090  bool foundRailSignal = !isRailway(getVClass());
2091 #ifdef PARALLEL_STOPWATCH
2092  myLane->getStopWatch()[0].start();
2093 #endif
2094 #ifdef _MSC_VER
2095 #pragma warning(push)
2096 #pragma warning(disable: 4127) // do not warn about constant conditional expression
2097 #endif
2098  while (true) {
2099 #ifdef _MSC_VER
2100 #pragma warning(pop)
2101 #endif
2102  // check leader on lane
2103  // leader is given for the first edge only
2104  if (opposite &&
2105  (leaderLane->getVehicleNumberWithPartials() > 1
2106  || (leaderLane != myLane && leaderLane->getVehicleNumber() > 0))) {
2107  ahead.clear();
2108  // find opposite-driving leader that must be respected on the currently looked at lane
2109  // (only looking at one lane at a time)
2110  const double backOffset = leaderLane == myLane ? getPositionOnLane() : leaderLane->getLength();
2111  const double gapOffset = leaderLane == myLane ? 0 : seen - leaderLane->getLength();
2112  const MSLeaderDistanceInfo cands = leaderLane->getFollowersOnConsecutive(this, backOffset, true, backOffset, true);
2113  MSLeaderDistanceInfo oppositeLeaders(leaderLane, this, 0);
2114  const double minTimeToLeaveLane = MSGlobals::gSublane ? MAX2(TS, (0.5 * myLane->getWidth() - getLateralPositionOnLane()) / getVehicleType().getMaxSpeedLat()) : 0;
2115  for (int i = 0; i < cands.numSublanes(); i++) {
2116  CLeaderDist cand = cands[i];
2117  if (cand.first != 0) {
2118  if ((cand.first->myLaneChangeModel->isOpposite() && cand.first->getLane() == leaderLane)
2119  || (!cand.first->myLaneChangeModel->isOpposite() && cand.first->getLaneChangeModel().getShadowLane() == leaderLane)) {
2120  // respect leaders that also drive in the opposite direction (fully or with some overlap)
2121  oppositeLeaders.addLeader(cand.first, cand.second + gapOffset - getVehicleType().getMinGap() + cand.first->getVehicleType().getMinGap() - cand.first->getVehicleType().getLength());
2122  } else if (cand.second >= 0 && cand.second - (v + cand.first->getSpeed()) * minTimeToLeaveLane < 0) {
2123  oppositeLeaders.addLeader(cand.first, cand.second + gapOffset - getVehicleType().getMinGap());
2124  }
2125  }
2126  }
2127 #ifdef DEBUG_PLAN_MOVE
2128  if (DEBUG_COND) {
2129  std::cout << " leaderLane=" << leaderLane->getID() << " gapOffset=" << gapOffset << " minTimeToLeaveLane=" << minTimeToLeaveLane
2130  << " cands=" << cands.toString() << " oppositeLeaders=" << oppositeLeaders.toString() << "\n";
2131  }
2132 #endif
2133  adaptToLeaderDistance(oppositeLeaders, 0, seen, lastLink, myLane, v, vLinkPass);
2134  } else {
2135  adaptToLeaders(ahead, lateralShift, seen, lastLink, leaderLane, v, vLinkPass);
2136  }
2137  if (lastLink != nullptr) {
2138  lastLink->myVLinkWait = MIN2(lastLink->myVLinkWait, v);
2139  }
2140 #ifdef DEBUG_PLAN_MOVE
2141  if (DEBUG_COND) {
2142  std::cout << "\nv = " << v << "\n";
2143 
2144  }
2145 #endif
2146  // XXX efficiently adapt to shadow leaders using neighAhead by iteration over the whole edge in parallel (lanechanger-style)
2147  if (myLaneChangeModel->getShadowLane() != nullptr) {
2148  // also slow down for leaders on the shadowLane relative to the current lane
2149  const MSLane* shadowLane = myLaneChangeModel->getShadowLane(leaderLane);
2150  if (shadowLane != nullptr
2151  && (MSGlobals::gLateralResolution > 0 || getLateralOverlap() > POSITION_EPS
2152  // continous lane change cannot be stopped so we must adapt to the leader on the target lane
2154  if ((&shadowLane->getEdge() == &leaderLane->getEdge() || myLaneChangeModel->isOpposite())) {
2156  if (myLaneChangeModel->isOpposite()) {
2157  // ego posLat is added when retrieving sublanes but it
2158  // should be negated (subtract twice to compensate)
2159  latOffset = ((myLane->getWidth() + shadowLane->getWidth()) * 0.5
2160  - 2 * getLateralPositionOnLane());
2161 
2162  }
2163  MSLeaderInfo shadowLeaders = shadowLane->getLastVehicleInformation(this, latOffset, lane->getLength() - seen);
2164 #ifdef DEBUG_PLAN_MOVE
2166  std::cout << SIMTIME << " opposite veh=" << getID() << " shadowLane=" << shadowLane->getID() << " latOffset=" << latOffset << " shadowLeaders=" << shadowLeaders.toString() << "\n";
2167  }
2168 #endif
2169  if (myLaneChangeModel->isOpposite()) {
2170  // ignore oncoming vehicles on the shadow lane
2171  shadowLeaders.removeOpposite(shadowLane);
2172  }
2173  adaptToLeaders(shadowLeaders, latOffset, seen, lastLink, shadowLane, v, vLinkPass);
2174  } else if (shadowLane == myLaneChangeModel->getShadowLane() && leaderLane == myLane) {
2175  // check for leader vehicles driving in the opposite direction on the opposite-direction shadow lane
2176  // (and thus in the same direction as ego)
2177  MSLeaderDistanceInfo shadowLeaders = shadowLane->getFollowersOnConsecutive(this, myLane->getOppositePos(getPositionOnLane()), true);
2178  const double latOffset = 0;
2179 #ifdef DEBUG_PLAN_MOVE
2180  if (DEBUG_COND) {
2181  std::cout << SIMTIME << " opposite shadows veh=" << getID() << " shadowLane=" << shadowLane->getID()
2182  << " latOffset=" << latOffset << " shadowLeaders=" << shadowLeaders.toString() << "\n";
2183  }
2184 #endif
2185  shadowLeaders.fixOppositeGaps(true);
2186 #ifdef DEBUG_PLAN_MOVE
2187  if (DEBUG_COND) {
2188  std::cout << " shadowLeadersFixed=" << shadowLeaders.toString() << "\n";
2189  }
2190 #endif
2191  adaptToLeaderDistance(shadowLeaders, latOffset, seen, lastLink, myLane, v, vLinkPass);
2192  }
2193  }
2194  }
2195  // adapt to pedestrians on the same lane
2196  if (lane->getEdge().getPersons().size() > 0 && lane->hasPedestrians()) {
2197  const double relativePos = lane->getLength() - seen;
2198 #ifdef DEBUG_PLAN_MOVE
2199  if (DEBUG_COND) {
2200  std::cout << SIMTIME << " adapt to pedestrians on lane=" << lane->getID() << " relPos=" << relativePos << "\n";
2201  }
2202 #endif
2203  PersonDist leader = lane->nextBlocking(relativePos,
2205  if (leader.first != 0) {
2206  const double stopSpeed = cfModel.stopSpeed(this, getSpeed(), leader.second - getVehicleType().getMinGap());
2207  v = MIN2(v, stopSpeed);
2208 #ifdef DEBUG_PLAN_MOVE
2209  if (DEBUG_COND) {
2210  std::cout << SIMTIME << " pedLeader=" << leader.first->getID() << " dist=" << leader.second << " v=" << v << "\n";
2211  }
2212 #endif
2213  }
2214  }
2215 
2216  // process stops
2217  if (!myStops.empty()
2218  && ((&myStops.begin()->lane->getEdge() == &lane->getEdge())
2219  || (myStops.begin()->isOpposite && myStops.begin()->lane->getEdge().getOppositeEdge() == &lane->getEdge()))
2220  && (!myStops.begin()->reached || (myStops.begin()->pars.speed > 0 && keepStopping()))
2221  // ignore stops that occur later in a looped route
2222  && myStops.front().edge == myCurrEdge + view) {
2223  // we are approaching a stop on the edge; must not drive further
2224  const MSStop& stop = *myStops.begin();
2225  bool isWaypoint = stop.pars.speed > 0;
2226  double endPos = stop.getEndPos(*this) + NUMERICAL_EPS;
2227  if (stop.parkingarea != nullptr) {
2228  // leave enough space so parking vehicles can exit
2229  const double brakePos = getBrakeGap() + lane->getLength() - seen;
2230  endPos = stop.parkingarea->getLastFreePosWithReservation(t, *this, brakePos);
2231  } else if (isWaypoint && !stop.reached) {
2232  endPos = stop.pars.startPos;
2233  }
2234  newStopDist = seen + endPos - lane->getLength();
2235 #ifdef DEBUG_STOPS
2236  if (DEBUG_COND) {
2237  std::cout << SIMTIME << " veh=" << getID() << " newStopDist=" << newStopDist << " stopLane=" << stop.lane->getID() << " stopEndPos=" << endPos << "\n";
2238  }
2239 #endif
2240  // regular stops are not emergencies
2241  double stopSpeed = laneMaxV;
2242  if (isWaypoint) {
2243  bool waypointWithStop = false;
2244  if (stop.pars.until > t) {
2245  // check if we have to slow down or even stop
2246  SUMOTime time2end = 0;
2247  if (stop.reached) {
2248  time2end = TIME2STEPS((stop.pars.endPos - myState.myPos) / stop.pars.speed);
2249  } else {
2250  time2end = TIME2STEPS(
2251  // time to reach waypoint start
2252  newStopDist / ((getSpeed() + stop.pars.speed) / 2)
2253  // time to reach waypoint end
2254  + (stop.pars.endPos - stop.pars.startPos) / stop.pars.speed);
2255  }
2256  if (stop.pars.until > t + time2end) {
2257  // we need to stop
2258  double distToEnd = newStopDist;
2259  if (!stop.reached) {
2260  distToEnd += stop.pars.endPos - stop.pars.startPos;
2261  }
2262  stopSpeed = MAX2(cfModel.stopSpeed(this, getSpeed(), distToEnd), vMinComfortable);
2263  waypointWithStop = true;
2264  }
2265  }
2266  if (stop.reached) {
2267  stopSpeed = MIN2(stop.pars.speed, stopSpeed);
2268  if (myState.myPos >= stop.pars.endPos && !waypointWithStop) {
2269  newStopDist = std::numeric_limits<double>::max();
2270  }
2271  } else {
2272  stopSpeed = MIN2(MAX2(cfModel.freeSpeed(this, getSpeed(), newStopDist, stop.pars.speed), vMinComfortable), stopSpeed);
2273  if (!stop.reached) {
2274  newStopDist += stop.pars.endPos - stop.pars.startPos;
2275  }
2276  if (lastLink != nullptr) {
2277  lastLink->adaptLeaveSpeed(cfModel.freeSpeed(this, vLinkPass, endPos, stop.pars.speed));
2278  }
2279  }
2280  } else {
2281  stopSpeed = MAX2(cfModel.stopSpeed(this, getSpeed(), newStopDist), vMinComfortable);
2282  if (lastLink != nullptr) {
2283  lastLink->adaptLeaveSpeed(cfModel.stopSpeed(this, vLinkPass, endPos));
2284  }
2285  }
2286  v = MIN2(v, stopSpeed);
2287  if (lane->isInternal()) {
2288  std::vector<MSLink*>::const_iterator exitLink = MSLane::succLinkSec(*this, view + 1, *lane, bestLaneConts);
2289  assert(!lane->isLinkEnd(exitLink));
2290  bool dummySetRequest;
2291  double dummyVLinkWait;
2292  checkLinkLeaderCurrentAndParallel(*exitLink, lane, seen, lastLink, v, vLinkPass, dummyVLinkWait, dummySetRequest);
2293  }
2294 
2295 #ifdef DEBUG_PLAN_MOVE
2296  if (DEBUG_COND) {
2297  std::cout << "\n" << SIMTIME << " next stop: distance = " << newStopDist << " requires stopSpeed = " << stopSpeed << "\n";
2298 
2299  }
2300 #endif
2301  if (!isWaypoint && !isRailway(getVClass())) {
2302  lfLinks.emplace_back(v, newStopDist);
2303  break;
2304  }
2305  }
2306 
2307  // move to next lane
2308  // get the next link used
2309  std::vector<MSLink*>::const_iterator link = MSLane::succLinkSec(*this, view + 1, *lane, bestLaneConts);
2310 
2311  // Check whether this is a turn (to save info about the next upcoming turn)
2312  if (!encounteredTurn) {
2313  if (!lane->isLinkEnd(link) && lane->getLinkCont().size() > 1) {
2314  LinkDirection linkDir = (*link)->getDirection();
2315  switch (linkDir) {
2317  case LinkDirection::NODIR:
2318  break;
2319  default:
2320  nextTurn.first = seen;
2321  nextTurn.second = linkDir;
2322  encounteredTurn = true;
2323 #ifdef DEBUG_NEXT_TURN
2324  if (DEBUG_COND) {
2325  std::cout << SIMTIME << " veh '" << getID() << "' nextTurn: " << toString(nextTurn.second)
2326  << " at " << nextTurn.first << "m." << std::endl;
2327  }
2328 #endif
2329  }
2330  }
2331  }
2332 
2333  // check whether the vehicle is on its final edge
2334  if (myCurrEdge + view + 1 == myRoute->end()
2335  || (myParameter->arrivalEdge >= 0 && getRoutePosition() + view == myParameter->arrivalEdge)) {
2336  const double arrivalSpeed = (myParameter->arrivalSpeedProcedure == ArrivalSpeedDefinition::GIVEN ?
2337  myParameter->arrivalSpeed : laneMaxV);
2338  // subtract the arrival speed from the remaining distance so we get one additional driving step with arrival speed
2339  // XXX: This does not work for ballistic update refs #2579
2340  const double distToArrival = seen + myArrivalPos - lane->getLength() - SPEED2DIST(arrivalSpeed);
2341  const double va = MAX2(NUMERICAL_EPS, cfModel.freeSpeed(this, getSpeed(), distToArrival, arrivalSpeed));
2342  v = MIN2(v, va);
2343  if (lastLink != nullptr) {
2344  lastLink->adaptLeaveSpeed(va);
2345  }
2346  lfLinks.push_back(DriveProcessItem(v, seen, lane->getEdge().isFringe() ? 1000 : 0));
2347  break;
2348  }
2349  // check whether the lane or the shadowLane is a dead end (allow some leeway on intersections)
2350  if (lane->isLinkEnd(link)
2351  || ((*link)->getViaLane() == nullptr
2352  && getLateralOverlap() > POSITION_EPS
2353  // do not get stuck on narrow edges
2354  && getVehicleType().getWidth() <= lane->getEdge().getWidth()
2355  // this is the exit link of a junction. The normal edge should support the shadow
2356  && ((myLaneChangeModel->getShadowLane((*link)->getLane()) == nullptr)
2357  // the internal lane after an internal junction has no parallel lane. make sure there is no shadow before continuing
2358  || (lane->getEdge().isInternal() && lane->getIncomingLanes()[0].lane->getEdge().isInternal()))
2359  // ignore situations where the shadow lane is part of a double-connection with the current lane
2360  && (myLaneChangeModel->getShadowLane() == nullptr
2361  || myLaneChangeModel->getShadowLane()->getLinkCont().size() == 0
2362  || myLaneChangeModel->getShadowLane()->getLinkCont().front()->getLane() != (*link)->getLane()))
2363  || (opposite && (*link)->getViaLaneOrLane()->getParallelOpposite() == nullptr
2364  && !myLaneChangeModel->hasBlueLight())) {
2365  double va = cfModel.stopSpeed(this, getSpeed(), seen);
2366  if (lastLink != nullptr) {
2367  lastLink->adaptLeaveSpeed(va);
2368  }
2369  if (myLaneChangeModel->getCommittedSpeed() > 0) {
2371  } else {
2372  v = MIN2(va, v);
2373  }
2374 #ifdef DEBUG_PLAN_MOVE
2375  if (DEBUG_COND) {
2376  std::cout << " braking for link end lane=" << lane->getID() << " seen=" << seen
2377  << " overlap=" << getLateralOverlap() << " va=" << va << " committed=" << myLaneChangeModel->getCommittedSpeed() << " v=" << v << "\n";
2378 
2379  }
2380 #endif
2381  if (lane->isLinkEnd(link)) {
2382  lfLinks.emplace_back(v, seen);
2383  break;
2384  }
2385  }
2386  lateralShift += (*link)->getLateralShift();
2387  const bool yellowOrRed = (*link)->haveRed() || (*link)->haveYellow();
2388  // We distinguish 3 cases when determining the point at which a vehicle stops:
2389  // - links that require stopping: here the vehicle needs to stop close to the stop line
2390  // to ensure it gets onto the junction in the next step. Otherwise the vehicle would 'forget'
2391  // that it already stopped and need to stop again. This is necessary pending implementation of #999
2392  // - red/yellow light: here the vehicle 'knows' that it will have priority eventually and does not need to stop on a precise spot
2393  // - other types of minor links: the vehicle needs to stop as close to the junction as necessary
2394  // to minimize the time window for passing the junction. If the
2395  // vehicle 'decides' to accelerate and cannot enter the junction in
2396  // the next step, new foes may appear and cause a collision (see #1096)
2397  // - major links: stopping point is irrelevant
2398  double laneStopOffset;
2399  const double majorStopOffset = MAX2(getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_STOPLINE_GAP, DIST_TO_STOPLINE_EXPECT_PRIORITY), lane->getVehicleStopOffset(this));
2400  const double minorStopOffset = lane->getVehicleStopOffset(this);
2401  // override low desired decel at yellow and red
2402  const double stopDecel = yellowOrRed && !isRailway(getVClass()) ? MAX2(MIN2(MSGlobals::gTLSYellowMinDecel, cfModel.getEmergencyDecel()), cfModel.getMaxDecel()) : cfModel.getMaxDecel();
2403  const double brakeDist = cfModel.brakeGap(myState.mySpeed, stopDecel, 0);
2404  const bool canBrakeBeforeLaneEnd = seen >= brakeDist;
2405  const bool canBrakeBeforeStopLine = seen - lane->getVehicleStopOffset(this) >= brakeDist;
2406  if (yellowOrRed) {
2407  // Wait at red traffic light with full distance if possible
2408  laneStopOffset = majorStopOffset;
2409  } else if ((*link)->havePriority()) {
2410  // On priority link, we should never stop below visibility distance
2411  laneStopOffset = MIN2((*link)->getFoeVisibilityDistance() - POSITION_EPS, majorStopOffset);
2412  } else {
2413  // On minor link, we should likewise never stop below visibility distance
2414  laneStopOffset = MIN2((*link)->getFoeVisibilityDistance() - POSITION_EPS, minorStopOffset);
2415  }
2416  if (canBrakeBeforeLaneEnd) {
2417  // avoid emergency braking if possible
2418  laneStopOffset = MIN2(laneStopOffset, seen - brakeDist);
2419  }
2420  laneStopOffset = MAX2(POSITION_EPS, laneStopOffset);
2421  double stopDist = MAX2(0., seen - laneStopOffset);
2422  if (newStopDist != std::numeric_limits<double>::max()) {
2423  stopDist = MAX2(stopDist, newStopDist);
2424  }
2425 #ifdef DEBUG_PLAN_MOVE
2426  if (DEBUG_COND) {
2427  std::cout << SIMTIME << " veh=" << getID() << " effective stopOffset on lane '" << lane->getID()
2428  << "' is " << laneStopOffset << " (-> stopDist=" << stopDist << ")" << std::endl;
2429  }
2430 #endif
2431  if (isRailway(getVClass())
2432  && !lane->isInternal()) {
2433  // check for train direction reversal
2434  if (lane->getBidiLane() != nullptr
2435  && (*link)->getLane()->getBidiLane() == lane) {
2436  double vMustReverse = getCarFollowModel().stopSpeed(this, getSpeed(), seen - POSITION_EPS);
2437  if (seen < 1) {
2438  mustSeeBeforeReversal = 2 * seen + getLength();
2439  }
2440  v = MIN2(v, vMustReverse);
2441  }
2442  // signal that is passed in the current step does not count
2443  foundRailSignal |= ((*link)->getTLLogic() != nullptr
2444  && (*link)->getTLLogic()->getLogicType() == TrafficLightType::RAIL_SIGNAL
2445  && seen > SPEED2DIST(v));
2446  }
2447 
2448  bool canReverseEventually = false;
2449  const double vReverse = checkReversal(canReverseEventually, laneMaxV, seen);
2450  v = MIN2(v, vReverse);
2451 #ifdef DEBUG_PLAN_MOVE
2452  if (DEBUG_COND) {
2453  std::cout << SIMTIME << " veh=" << getID() << " canReverseEventually=" << canReverseEventually << " v=" << v << "\n";
2454  }
2455 #endif
2456 
2457  // check whether we need to slow down in order to finish a continuous lane change
2459  if ( // slow down to finish lane change before a turn lane
2460  ((*link)->getDirection() == LinkDirection::LEFT || (*link)->getDirection() == LinkDirection::RIGHT) ||
2461  // slow down to finish lane change before the shadow lane ends
2462  (myLaneChangeModel->getShadowLane() != nullptr &&
2463  (*link)->getViaLaneOrLane()->getParallelLane(myLaneChangeModel->getShadowDirection()) == nullptr)) {
2464  // XXX maybe this is too harsh. Vehicles could cut some corners here
2465  const double timeRemaining = STEPS2TIME(myLaneChangeModel->remainingTime());
2466  assert(timeRemaining != 0);
2467  // XXX: Euler-logic (#860), but I couldn't identify problems from this yet (Leo). Refs. #2575
2468  const double va = MAX2(cfModel.stopSpeed(this, getSpeed(), seen - POSITION_EPS),
2469  (seen - POSITION_EPS) / timeRemaining);
2470 #ifdef DEBUG_PLAN_MOVE
2471  if (DEBUG_COND) {
2472  std::cout << SIMTIME << " veh=" << getID() << " slowing down to finish continuous change before"
2473  << " link=" << (*link)->getViaLaneOrLane()->getID()
2474  << " timeRemaining=" << timeRemaining
2475  << " v=" << v
2476  << " va=" << va
2477  << std::endl;
2478  }
2479 #endif
2480  v = MIN2(va, v);
2481  }
2482  }
2483 
2484  // - always issue a request to leave the intersection we are currently on
2485  const bool leavingCurrentIntersection = myLane->getEdge().isInternal() && lastLink == nullptr;
2486  // - do not issue a request to enter an intersection after we already slowed down for an earlier one
2487  const bool abortRequestAfterMinor = slowedDownForMinor && (*link)->getInternalLaneBefore() == nullptr;
2488  // - even if red, if we cannot break we should issue a request
2489  bool setRequest = (v > NUMERICAL_EPS_SPEED && !abortRequestAfterMinor) || (leavingCurrentIntersection);
2490 
2491  double stopSpeed = cfModel.stopSpeed(this, getSpeed(), stopDist, stopDecel);
2492  double vLinkWait = MIN2(v, stopSpeed);
2493 #ifdef DEBUG_PLAN_MOVE
2494  if (DEBUG_COND) {
2495  std::cout
2496  << " stopDist=" << stopDist
2497  << " stopDecel=" << stopDecel
2498  << " vLinkWait=" << vLinkWait
2499  << " brakeDist=" << brakeDist
2500  << " seen=" << seen
2501  << " leaveIntersection=" << leavingCurrentIntersection
2502  << " setRequest=" << setRequest
2503  //<< std::setprecision(16)
2504  //<< " v=" << v
2505  //<< " speedEps=" << NUMERICAL_EPS_SPEED
2506  //<< std::setprecision(gPrecision)
2507  << "\n";
2508  }
2509 #endif
2510 
2511  if (yellowOrRed && canBrakeBeforeStopLine && !ignoreRed(*link, canBrakeBeforeStopLine) && seen >= mustSeeBeforeReversal) {
2512  if (lane->isInternal()) {
2513  checkLinkLeaderCurrentAndParallel(*link, lane, seen, lastLink, v, vLinkPass, vLinkWait, setRequest);
2514  }
2515  // arrivalSpeed / arrivalTime when braking for red light is only relevent for rail signal switching
2516  const SUMOTime arrivalTime = getArrivalTime(t, seen, v, vLinkPass);
2517  // the vehicle is able to brake in front of a yellow/red traffic light
2518  lfLinks.push_back(DriveProcessItem(*link, v, vLinkWait, false, arrivalTime, vLinkWait, arrivalTime + TIME2STEPS(30), 0, seen));
2519  //lfLinks.push_back(DriveProcessItem(0, vLinkWait, vLinkWait, false, 0, 0, stopDist));
2520  break;
2521  }
2522 
2523  if (ignoreRed(*link, canBrakeBeforeStopLine) && STEPS2TIME(t - (*link)->getLastStateChange()) > 2) {
2524  // restrict speed when ignoring a red light
2525  const double redSpeed = MIN2(v, getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_DRIVE_RED_SPEED, v));
2526  const double va = MAX2(redSpeed, cfModel.freeSpeed(this, getSpeed(), seen, redSpeed));
2527  v = MIN2(va, v);
2528 #ifdef DEBUG_PLAN_MOVE
2529  if (DEBUG_COND) std::cout
2530  << " ignoreRed spent=" << STEPS2TIME(t - (*link)->getLastStateChange())
2531  << " redSpeed=" << redSpeed
2532  << " va=" << va
2533  << " v=" << v
2534  << "\n";
2535 #endif
2536  }
2537 
2538 
2539  checkLinkLeaderCurrentAndParallel(*link, lane, seen, lastLink, v, vLinkPass, vLinkWait, setRequest);
2540 
2541  if (lastLink != nullptr) {
2542  lastLink->adaptLeaveSpeed(laneMaxV);
2543  }
2544  double arrivalSpeed = vLinkPass;
2545  // vehicles should decelerate when approaching a minor link
2546  // - unless they are close enough to have clear visibility of all relevant foe lanes and may start to accelerate again
2547  // - and unless they are so close that stopping is impossible (i.e. when a green light turns to yellow when close to the junction)
2548 
2549  // whether the vehicle/driver is close enough to the link to see all possible foes #2123
2550  const double visibilityDistance = (*link)->getFoeVisibilityDistance();
2551  const double determinedFoePresence = seen <= visibilityDistance;
2552 // // VARIANT: account for time needed to recognize whether relevant vehicles are on the foe lanes. (Leo)
2553 // double foeRecognitionTime = 0.0;
2554 // double determinedFoePresence = seen < visibilityDistance - myState.mySpeed*foeRecognitionTime;
2555 
2556 #ifdef DEBUG_PLAN_MOVE
2557  if (DEBUG_COND) {
2558  std::cout << " approaching link=" << (*link)->getViaLaneOrLane()->getID() << " prio=" << (*link)->havePriority() << " seen=" << seen << " visibilityDistance=" << visibilityDistance << " brakeDist=" << brakeDist << "\n";
2559  }
2560 #endif
2561 
2562  const bool couldBrakeForMinor = !(*link)->havePriority() && brakeDist < seen && !(*link)->lastWasContMajor();
2563  if (couldBrakeForMinor && !determinedFoePresence) {
2564  // vehicle decelerates just enough to be able to stop if necessary and then accelerates
2565  double maxSpeedAtVisibilityDist = cfModel.maximumSafeStopSpeed(visibilityDistance, cfModel.getMaxDecel(), myState.mySpeed, false, 0.);
2566  // XXX: estimateSpeedAfterDistance does not use euler-logic (thus returns a lower value than possible here...)
2567  double maxArrivalSpeed = cfModel.estimateSpeedAfterDistance(visibilityDistance, maxSpeedAtVisibilityDist, cfModel.getMaxAccel());
2568  arrivalSpeed = MIN2(vLinkPass, maxArrivalSpeed);
2569  slowedDownForMinor = true;
2570 #ifdef DEBUG_PLAN_MOVE
2571  if (DEBUG_COND) {
2572  std::cout << " slowedDownForMinor maxSpeedAtVisDist=" << maxSpeedAtVisibilityDist << " maxArrivalSpeed=" << maxArrivalSpeed << " arrivalSpeed=" << arrivalSpeed << "\n";
2573  }
2574 #endif
2575  } else if ((*link)->getState() == LINKSTATE_EQUAL && myWaitingTime > 0) {
2576  // check for deadlock (circular yielding)
2577  //std::cout << SIMTIME << " veh=" << getID() << " check rbl-deadlock\n";
2578  std::pair<const SUMOVehicle*, const MSLink*> blocker = (*link)->getFirstApproachingFoe(*link);
2579  //std::cout << " blocker=" << Named::getIDSecure(blocker.first) << "\n";
2580  int n = 100;
2581  while (blocker.second != nullptr && blocker.second != *link && n > 0) {
2582  blocker = blocker.second->getFirstApproachingFoe(*link);
2583  n--;
2584  //std::cout << " blocker=" << Named::getIDSecure(blocker.first) << "\n";
2585  }
2586  if (n == 0) {
2587  WRITE_WARNINGF("Suspicious right_before_left junction '%s'.", lane->getEdge().getToJunction()->getID());
2588  }
2589  //std::cout << " blockerLink=" << blocker.second << " link=" << *link << "\n";
2590  if (blocker.second == *link) {
2591  const double threshold = (*link)->getDirection() == LinkDirection::STRAIGHT ? 0.25 : 0.75;
2592  if (RandHelper::rand(getRNG()) < threshold) {
2593  //std::cout << " abort request, threshold=" << threshold << "\n";
2594  setRequest = false;
2595  }
2596  }
2597  }
2598  if (couldBrakeForMinor && (*link)->getLane()->getEdge().isRoundabout()) {
2599  slowedDownForMinor = true;
2600 #ifdef DEBUG_PLAN_MOVE
2601  if (DEBUG_COND) {
2602  std::cout << " slowedDownForMinor at roundabout\n";
2603  }
2604 #endif
2605  }
2606 
2607  const SUMOTime arrivalTime = getArrivalTime(t, seen, v, arrivalSpeed);
2608 
2609  // compute arrival speed and arrival time if vehicle starts braking now
2610  // if stopping is possible, arrivalTime can be arbitrarily large. A small value keeps fractional times (impatience) meaningful
2611  double arrivalSpeedBraking = 0;
2612  SUMOTime arrivalTimeBraking = arrivalTime + TIME2STEPS(30);
2613  if (seen < cfModel.brakeGap(v) && !isStopped()) { // XXX: should this use the current speed (at least for the ballistic case)? (Leo) Refs. #2575
2614  // vehicle cannot come to a complete stop in time
2616  arrivalSpeedBraking = cfModel.getMinimalArrivalSpeedEuler(seen, v);
2617  // due to discrete/continuous mismatch (when using Euler update) we have to ensure that braking actually helps
2618  arrivalSpeedBraking = MIN2(arrivalSpeedBraking, arrivalSpeed);
2619  } else {
2620  arrivalSpeedBraking = cfModel.getMinimalArrivalSpeed(seen, myState.mySpeed);
2621  }
2622  if (v + arrivalSpeedBraking <= 0.) {
2623  arrivalTimeBraking = std::numeric_limits<long long int>::max();
2624  } else {
2625  arrivalTimeBraking = MAX2(arrivalTime, t + TIME2STEPS(seen / ((v + arrivalSpeedBraking) * 0.5)));
2626  }
2627  }
2628  // estimate leave speed for passing time computation
2629  // l=linkLength, a=accel, t=continuousTime, v=vLeave
2630  // l=v*t + 0.5*a*t^2, solve for t and multiply with a, then add v
2631  const double estimatedLeaveSpeed = MIN2((*link)->getViaLaneOrLane()->getVehicleMaxSpeed(this),
2632  getCarFollowModel().estimateSpeedAfterDistance((*link)->getLength(), arrivalSpeed, getVehicleType().getCarFollowModel().getMaxAccel()));
2633  lfLinks.push_back(DriveProcessItem(*link, v, vLinkWait, setRequest,
2634  arrivalTime, arrivalSpeed,
2635  arrivalTimeBraking, arrivalSpeedBraking,
2636  seen, estimatedLeaveSpeed));
2637  if ((*link)->getViaLane() == nullptr) {
2638  hadNonInternal = true;
2639  ++view;
2640  }
2641 #ifdef DEBUG_PLAN_MOVE
2642  if (DEBUG_COND) {
2643  std::cout << " checkAbort setRequest=" << setRequest << " v=" << v << " seen=" << seen << " dist=" << dist
2644  << " seenNonInternal=" << seenNonInternal
2645  << " seenInternal=" << seenInternal << " length=" << vehicleLength << "\n";
2646  }
2647 #endif
2648  // we need to look ahead far enough to see available space for checkRewindLinkLanes
2649  if ((!setRequest || v <= 0 || seen > dist) && hadNonInternal && seenNonInternal > MAX2(vehicleLength * CRLL_LOOK_AHEAD, vehicleLength + seenInternal) && foundRailSignal) {
2650  break;
2651  }
2652  // get the following lane
2653  lane = (*link)->getViaLaneOrLane();
2654  laneMaxV = lane->getVehicleMaxSpeed(this);
2656  laneMaxV = std::numeric_limits<double>::max();
2657  }
2658  // the link was passed
2659  // compute the velocity to use when the link is not blocked by other vehicles
2660  // the vehicle shall be not faster when reaching the next lane than allowed
2661  // speed limits are not emergencies (e.g. when the limit changes suddenly due to TraCI or a variableSpeedSignal)
2662  const double va = MAX2(cfModel.freeSpeed(this, getSpeed(), seen, laneMaxV), vMinComfortable);
2663  v = MIN2(va, v);
2664  if (lane->getEdge().isInternal()) {
2665  seenInternal += lane->getLength();
2666  } else {
2667  seenNonInternal += lane->getLength();
2668  }
2669  // do not restrict results to the current vehicle to allow caching for the current time step
2670  leaderLane = opposite ? lane->getParallelOpposite() : lane;
2671  if (leaderLane == nullptr) {
2672 
2673  break;
2674  }
2675  ahead = opposite ? MSLeaderInfo(leaderLane) : leaderLane->getLastVehicleInformation(nullptr, 0);
2676  seen += lane->getLength();
2677  vLinkPass = MIN2(cfModel.estimateSpeedAfterDistance(lane->getLength(), v, cfModel.getMaxAccel()), laneMaxV); // upper bound
2678  lastLink = &lfLinks.back();
2679  }
2680 
2681 //#ifdef DEBUG_PLAN_MOVE
2682 // if(DEBUG_COND){
2683 // std::cout << "planMoveInternal found safe speed v = " << v << std::endl;
2684 // }
2685 //#endif
2686 
2687 #ifdef PARALLEL_STOPWATCH
2688  myLane->getStopWatch()[0].stop();
2689 #endif
2690 }
2691 
2692 
2693 SUMOTime
2694 MSVehicle::getArrivalTime(SUMOTime t, double seen, double v, double arrivalSpeed) const {
2695  const MSCFModel& cfModel = getCarFollowModel();
2696  SUMOTime arrivalTime;
2698  // @note intuitively it would make sense to compare arrivalSpeed with getSpeed() instead of v
2699  // however, due to the current position update rule (ticket #860) the vehicle moves with v in this step
2700  // subtract DELTA_T because t is the time at the end of this step and the movement is not carried out yet
2701  arrivalTime = t - DELTA_T + cfModel.getMinimalArrivalTime(seen, v, arrivalSpeed);
2702  } else {
2703  arrivalTime = t - DELTA_T + cfModel.getMinimalArrivalTime(seen, myState.mySpeed, arrivalSpeed);
2704  }
2705  if (isStopped()) {
2706  arrivalTime += MAX2((SUMOTime)0, myStops.front().duration);
2707  }
2708  return arrivalTime;
2709 }
2710 
2711 
2712 void
2713 MSVehicle::adaptToLeaders(const MSLeaderInfo& ahead, double latOffset,
2714  const double seen, DriveProcessItem* const lastLink,
2715  const MSLane* const lane, double& v, double& vLinkPass) const {
2716  int rightmost;
2717  int leftmost;
2718  ahead.getSubLanes(this, latOffset, rightmost, leftmost);
2719 #ifdef DEBUG_PLAN_MOVE
2720  if (DEBUG_COND) std::cout << SIMTIME
2721  << "\nADAPT_TO_LEADERS\nveh=" << getID()
2722  << " lane=" << lane->getID()
2723  << " latOffset=" << latOffset
2724  << " rm=" << rightmost
2725  << " lm=" << leftmost
2726  << " ahead=" << ahead.toString()
2727  << "\n";
2728 #endif
2729  /*
2730  if (myLaneChangeModel->getCommittedSpeed() > 0) {
2731  v = MIN2(v, myLaneChangeModel->getCommittedSpeed());
2732  vLinkPass = MIN2(vLinkPass, myLaneChangeModel->getCommittedSpeed());
2733  #ifdef DEBUG_PLAN_MOVE
2734  if (DEBUG_COND) std::cout << " hasCommitted=" << myLaneChangeModel->getCommittedSpeed() << "\n";
2735  #endif
2736  return;
2737  }
2738  */
2739  for (int sublane = rightmost; sublane <= leftmost; ++sublane) {
2740  const MSVehicle* pred = ahead[sublane];
2741  if (pred != nullptr && pred != this) {
2742  // @todo avoid multiple adaptations to the same leader
2743  const double predBack = pred->getBackPositionOnLane(lane);
2744  double gap = (lastLink == nullptr
2745  ? predBack - myState.myPos - getVehicleType().getMinGap()
2746  : predBack + seen - lane->getLength() - getVehicleType().getMinGap());
2747  if (myLaneChangeModel->isOpposite()) {
2748  if (pred->getLaneChangeModel().isOpposite() || lane == pred->getLaneChangeModel().getShadowLane()) {
2749  // ego might and leader are driving against lane
2750  gap = myState.myPos - predBack - getVehicleType().getMinGap();
2751  } else {
2752  // ego and leader are driving in the same direction as lane (shadowlane for ego)
2753  gap = predBack - (myLane->getLength() - myState.myPos) - getVehicleType().getMinGap();
2754  }
2755  } else if (pred->getLaneChangeModel().isOpposite() && pred->isStopped()) {
2756  // must react to stopped vehicles
2757  gap = pred->getPositionOnLane() - myState.myPos - MAX2(getVehicleType().getMinGap(), pred->getVehicleType().getMinGap());
2758  }
2759 #ifdef DEBUG_PLAN_MOVE
2760  if (DEBUG_COND) {
2761  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";
2762  }
2763 #endif
2764  adaptToLeader(std::make_pair(pred, gap), seen, lastLink, lane, v, vLinkPass);
2765  }
2766  }
2767 }
2768 
2769 void
2771  const double seen, DriveProcessItem* const lastLink,
2772  const MSLane* const lane, double& v, double& vLinkPass) const {
2773  int rightmost;
2774  int leftmost;
2775  ahead.getSubLanes(this, latOffset, rightmost, leftmost);
2776 #ifdef DEBUG_PLAN_MOVE
2777  if (DEBUG_COND) std::cout << SIMTIME
2778  << "\nADAPT_TO_LEADERS_DISTANCE\nveh=" << getID()
2779  << " lane=" << lane->getID()
2780  << " latOffset=" << latOffset
2781  << " rm=" << rightmost
2782  << " lm=" << leftmost
2783  << " ahead=" << ahead.toString()
2784  << "\n";
2785 #endif
2786  for (int sublane = rightmost; sublane <= leftmost; ++sublane) {
2787  CLeaderDist predDist = ahead[sublane];
2788  const MSVehicle* pred = predDist.first;
2789  if (pred != nullptr && pred != this) {
2790 #ifdef DEBUG_PLAN_MOVE
2791  if (DEBUG_COND) {
2792  std::cout << " pred=" << pred->getID() << " predLane=" << pred->getLane()->getID() << " predPos=" << pred->getPositionOnLane() << " gap=" << predDist.second << "\n";
2793  }
2794 #endif
2795  adaptToLeader(predDist, seen, lastLink, lane, v, vLinkPass);
2796  }
2797  }
2798 }
2799 
2800 
2801 void
2802 MSVehicle::adaptToLeader(const std::pair<const MSVehicle*, double> leaderInfo,
2803  const double seen, DriveProcessItem* const lastLink,
2804  const MSLane* const lane, double& v, double& vLinkPass,
2805  double distToCrossing) const {
2806  if (leaderInfo.first != 0) {
2807  const double vsafeLeader = getSafeFollowSpeed(leaderInfo, seen, lane, distToCrossing);
2808  if (lastLink != nullptr) {
2809  lastLink->adaptLeaveSpeed(vsafeLeader);
2810  }
2811  v = MIN2(v, vsafeLeader);
2812  vLinkPass = MIN2(vLinkPass, vsafeLeader);
2813 
2814 #ifdef DEBUG_PLAN_MOVE
2815  if (DEBUG_COND) std::cout
2816  << SIMTIME
2817  //std::cout << std::setprecision(10);
2818  << " veh=" << getID()
2819  << " lead=" << leaderInfo.first->getID()
2820  << " leadSpeed=" << leaderInfo.first->getSpeed()
2821  << " gap=" << leaderInfo.second
2822  << " leadLane=" << leaderInfo.first->getLane()->getID()
2823  << " predPos=" << leaderInfo.first->getPositionOnLane()
2824  << " seen=" << seen
2825  << " lane=" << lane->getID()
2826  << " myLane=" << myLane->getID()
2827  << " dTC=" << distToCrossing
2828  << " v=" << v
2829  << " vSafeLeader=" << vsafeLeader
2830  << " vLinkPass=" << vLinkPass
2831  << "\n";
2832 #endif
2833  }
2834 }
2835 
2836 
2837 void
2838 MSVehicle::checkLinkLeaderCurrentAndParallel(const MSLink* link, const MSLane* lane, double seen,
2839  DriveProcessItem* const lastLink, double& v, double& vLinkPass, double& vLinkWait, bool& setRequest) const {
2841  // we want to pass the link but need to check for foes on internal lanes
2842  checkLinkLeader(link, lane, seen, lastLink, v, vLinkPass, vLinkWait, setRequest);
2843  if (myLaneChangeModel->getShadowLane() != nullptr) {
2844  const MSLink* const parallelLink = link->getParallelLink(myLaneChangeModel->getShadowDirection());
2845  if (parallelLink != nullptr) {
2846  checkLinkLeader(parallelLink, lane, seen, lastLink, v, vLinkPass, vLinkWait, setRequest, true);
2847  }
2848  }
2849  }
2850 
2851 }
2852 
2853 void
2854 MSVehicle::checkLinkLeader(const MSLink* link, const MSLane* lane, double seen,
2855  DriveProcessItem* const lastLink, double& v, double& vLinkPass, double& vLinkWait, bool& setRequest,
2856  bool isShadowLink) const {
2857 #ifdef DEBUG_PLAN_MOVE_LEADERINFO
2858  if (DEBUG_COND) {
2859  gDebugFlag1 = true; // See MSLink::getLeaderInfo
2860  }
2861 #endif
2862  const MSLink::LinkLeaders linkLeaders = link->getLeaderInfo(this, seen, nullptr, isShadowLink);
2863 #ifdef DEBUG_PLAN_MOVE_LEADERINFO
2864  if (DEBUG_COND) {
2865  gDebugFlag1 = false; // See MSLink::getLeaderInfo
2866  }
2867 #endif
2868  for (MSLink::LinkLeaders::const_iterator it = linkLeaders.begin(); it != linkLeaders.end(); ++it) {
2869  // the vehicle to enter the junction first has priority
2870  const MSVehicle* leader = (*it).vehAndGap.first;
2871  if (leader == nullptr) {
2872  // leader is a pedestrian. Passing 'this' as a dummy.
2873 #ifdef DEBUG_PLAN_MOVE_LEADERINFO
2874  if (DEBUG_COND) {
2875  std::cout << SIMTIME << " veh=" << getID() << " is blocked on link to " << link->getViaLaneOrLane()->getID() << " by pedestrian. dist=" << it->distToCrossing << "\n";
2876  }
2877 #endif
2880 #ifdef DEBUG_PLAN_MOVE
2881  if (DEBUG_COND) {
2882  std::cout << SIMTIME << " veh=" << getID() << " is ignoring pedestrian (jmIgnoreJunctionFoeProb)\n";
2883  }
2884 #endif
2885  continue;
2886  }
2887  adaptToLeader(std::make_pair(this, -1), seen, lastLink, lane, v, vLinkPass, it->distToCrossing);
2888  } else if (isLeader(link, leader) || (*it).inTheWay) {
2891 #ifdef DEBUG_PLAN_MOVE
2892  if (DEBUG_COND) {
2893  std::cout << SIMTIME << " veh=" << getID() << " is ignoring linkLeader=" << leader->getID() << " (jmIgnoreJunctionFoeProb)\n";
2894  }
2895 #endif
2896  continue;
2897  }
2899  // sibling link (XXX: could also be partial occupator where this check fails)
2900  &leader->getLane()->getEdge() == &lane->getEdge()) {
2901  // check for sublane obstruction (trivial for sibling link leaders)
2902  const MSLane* conflictLane = link->getInternalLaneBefore();
2903  MSLeaderInfo linkLeadersAhead = MSLeaderInfo(conflictLane);
2904  linkLeadersAhead.addLeader(leader, false, 0); // assume sibling lane has the same geometry as the leader lane
2905  const double latOffset = isShadowLink ? (getLane()->getRightSideOnEdge() - myLaneChangeModel->getShadowLane()->getRightSideOnEdge()) : 0;
2906  // leader is neither on lane nor conflictLane (the conflict is only established geometrically)
2907  adaptToLeaders(linkLeadersAhead, latOffset, seen, lastLink, leader->getLane(), v, vLinkPass);
2908 #ifdef DEBUG_PLAN_MOVE
2909  if (DEBUG_COND) {
2910  std::cout << SIMTIME << " veh=" << getID()
2911  << " siblingFoe link=" << link->getViaLaneOrLane()->getID()
2912  << " isShadowLink=" << isShadowLink
2913  << " lane=" << lane->getID()
2914  << " foe=" << leader->getID()
2915  << " foeLane=" << leader->getLane()->getID()
2916  << " latOffset=" << latOffset
2917  << " latOffsetFoe=" << leader->getLatOffset(lane)
2918  << " linkLeadersAhead=" << linkLeadersAhead.toString()
2919  << "\n";
2920  }
2921 #endif
2922  } else {
2923 #ifdef DEBUG_PLAN_MOVE
2924  if (DEBUG_COND) {
2925  std::cout << SIMTIME << " veh=" << getID() << " linkLeader=" << leader->getID()
2926  << " ET=" << myJunctionEntryTime << " lET=" << leader->myJunctionEntryTime
2927  << " ETN=" << myJunctionEntryTimeNeverYield << " lETN=" << leader->myJunctionEntryTimeNeverYield
2928  << " CET=" << myJunctionConflictEntryTime << " lCET=" << leader->myJunctionConflictEntryTime
2929  << "\n";
2930  }
2931 #endif
2932  adaptToLeader(it->vehAndGap, seen, lastLink, lane, v, vLinkPass, it->distToCrossing);
2933  }
2934  if (lastLink != nullptr) {
2935  // we are not yet on the junction with this linkLeader.
2936  // at least we can drive up to the previous link and stop there
2937  v = MAX2(v, lastLink->myVLinkWait);
2938  }
2939  // if blocked by a leader from the same or next lane we must yield our request
2940  // also, if blocked by a stopped or blocked leader
2941  if (v < SUMO_const_haltingSpeed
2942  //&& leader->getSpeed() < SUMO_const_haltingSpeed
2944  || leader->getLane()->getLogicalPredecessorLane() == myLane
2945  || leader->isStopped()
2947  setRequest = false;
2948 #ifdef DEBUG_PLAN_MOVE_LEADERINFO
2949  if (DEBUG_COND) {
2950  std::cout << " aborting request\n";
2951  }
2952 #endif
2953  if (lastLink != nullptr && leader->getLane()->getLogicalPredecessorLane() == myLane) {
2954  // we are not yet on the junction so must abort that request as well
2955  // (or maybe we are already on the junction and the leader is a partial occupator beyond)
2956  lastLink->mySetRequest = false;
2957 #ifdef DEBUG_PLAN_MOVE_LEADERINFO
2958  if (DEBUG_COND) {
2959  std::cout << " aborting previous request\n";
2960  }
2961 #endif
2962  }
2963  }
2964  }
2965 #ifdef DEBUG_PLAN_MOVE_LEADERINFO
2966  else {
2967  if (DEBUG_COND) {
2968  std::cout << SIMTIME << " veh=" << getID() << " ignoring leader " << leader->getID()
2969  << " ET=" << myJunctionEntryTime << " lET=" << leader->myJunctionEntryTime
2970  << " ETN=" << myJunctionEntryTimeNeverYield << " lETN=" << leader->myJunctionEntryTimeNeverYield
2971  << " CET=" << myJunctionConflictEntryTime << " lCET=" << leader->myJunctionConflictEntryTime
2972  << "\n";
2973  }
2974  }
2975 #endif
2976  }
2977  // if this is the link between two internal lanes we may have to slow down for pedestrians
2978  vLinkWait = MIN2(vLinkWait, v);
2979 }
2980 
2981 
2982 double
2983 MSVehicle::getSafeFollowSpeed(const std::pair<const MSVehicle*, double> leaderInfo,
2984  const double seen, const MSLane* const lane, double distToCrossing) const {
2985  assert(leaderInfo.first != 0);
2986  const MSCFModel& cfModel = getCarFollowModel();
2987  double vsafeLeader = 0;
2989  vsafeLeader = -std::numeric_limits<double>::max();
2990  }
2991  if (leaderInfo.second >= 0) {
2992  vsafeLeader = cfModel.followSpeed(this, getSpeed(), leaderInfo.second, leaderInfo.first->getSpeed(), leaderInfo.first->getCurrentApparentDecel(), leaderInfo.first);
2993  } else {
2994  // the leading, in-lapping vehicle is occupying the complete next lane
2995  // stop before entering this lane
2996  vsafeLeader = cfModel.stopSpeed(this, getSpeed(), seen - lane->getLength() - POSITION_EPS);
2997 #ifdef DEBUG_PLAN_MOVE_LEADERINFO
2998  if (DEBUG_COND) {
2999  std::cout << SIMTIME << " veh=" << getID() << " stopping before junction: lane=" << lane->getID() << " seen=" << seen
3000  << " laneLength=" << lane->getLength()
3001  << " stopDist=" << seen - lane->getLength() - POSITION_EPS
3002  << " vsafeLeader=" << vsafeLeader
3003  << " distToCrossing=" << distToCrossing
3004  << "\n";
3005  }
3006 #endif
3007  }
3008  if (distToCrossing >= 0) {
3009  // can the leader still stop in the way?
3010  const double vStop = cfModel.stopSpeed(this, getSpeed(), distToCrossing - getVehicleType().getMinGap());
3011  if (leaderInfo.first == this) {
3012  // braking for pedestrian
3013  vsafeLeader = vStop;
3014 #ifdef DEBUG_PLAN_MOVE_LEADERINFO
3015  if (DEBUG_COND) {
3016  std::cout << " breaking for pedestrian distToCrossing=" << distToCrossing << " vStop=" << vStop << "\n";
3017  }
3018 #endif
3019  } else if (leaderInfo.second == -std::numeric_limits<double>::max()) {
3020  // drive up to the crossing point and stop
3021 #ifdef DEBUG_PLAN_MOVE_LEADERINFO
3022  if (DEBUG_COND) {
3023  std::cout << " stop at crossing point for critical leader\n";
3024  };
3025 #endif
3026  vsafeLeader = MAX2(vsafeLeader, vStop);
3027  } else {
3028  const double leaderDistToCrossing = distToCrossing - leaderInfo.second;
3029  // estimate the time at which the leader has gone past the crossing point
3030  const double leaderPastCPTime = leaderDistToCrossing / MAX2(leaderInfo.first->getSpeed(), SUMO_const_haltingSpeed);
3031  // reach distToCrossing after that time
3032  // avgSpeed * leaderPastCPTime = distToCrossing
3033  // ballistic: avgSpeed = (getSpeed + vFinal) / 2
3034  const double vFinal = MAX2(getSpeed(), 2 * (distToCrossing - getVehicleType().getMinGap()) / leaderPastCPTime - getSpeed());
3035  const double v2 = getSpeed() + ACCEL2SPEED((vFinal - getSpeed()) / leaderPastCPTime);
3036  vsafeLeader = MAX2(vsafeLeader, MIN2(v2, vStop));
3037 #ifdef DEBUG_PLAN_MOVE_LEADERINFO
3038  if (DEBUG_COND) {
3039  std::cout << " driving up to the crossing point (distToCrossing=" << distToCrossing << ")"
3040  << " leaderPastCPTime=" << leaderPastCPTime
3041  << " vFinal=" << vFinal
3042  << " v2=" << v2
3043  << " vStop=" << vStop
3044  << " vsafeLeader=" << vsafeLeader << "\n";
3045  }
3046 #endif
3047  }
3048  }
3049  return vsafeLeader;
3050 }
3051 
3052 double
3053 MSVehicle::getDeltaPos(const double accel) const {
3054  double vNext = myState.mySpeed + ACCEL2SPEED(accel);
3056  // apply implicit Euler positional update
3057  return SPEED2DIST(MAX2(vNext, 0.));
3058  } else {
3059  // apply ballistic update
3060  if (vNext >= 0) {
3061  // assume constant acceleration during this time step
3062  return SPEED2DIST(myState.mySpeed + 0.5 * ACCEL2SPEED(accel));
3063  } else {
3064  // negative vNext indicates a stop within the middle of time step
3065  // The corresponding stop time is s = mySpeed/deceleration \in [0,dt], and the
3066  // covered distance is therefore deltaPos = mySpeed*s - 0.5*deceleration*s^2.
3067  // Here, deceleration = (myState.mySpeed - vNext)/dt is the constant deceleration
3068  // until the vehicle stops.
3069  return -SPEED2DIST(0.5 * myState.mySpeed * myState.mySpeed / ACCEL2SPEED(accel));
3070  }
3071  }
3072 }
3073 
3074 void
3075 MSVehicle::processLinkApproaches(double& vSafe, double& vSafeMin, double& vSafeMinDist) {
3076 
3077  // Speed limit due to zipper merging
3078  double vSafeZipper = std::numeric_limits<double>::max();
3079 
3080  myHaveToWaitOnNextLink = false;
3081  bool canBrakeVSafeMin = false;
3082 
3083  // Get safe velocities from DriveProcessItems.
3084  assert(myLFLinkLanes.size() != 0 || isRemoteControlled());
3085  for (const DriveProcessItem& dpi : myLFLinkLanes) {
3086  MSLink* const link = dpi.myLink;
3087 
3088 #ifdef DEBUG_EXEC_MOVE
3089  if (DEBUG_COND) {
3090  std::cout
3091  << SIMTIME
3092  << " veh=" << getID()
3093  << " link=" << (link == 0 ? "NULL" : link->getViaLaneOrLane()->getID())
3094  << " req=" << dpi.mySetRequest
3095  << " vP=" << dpi.myVLinkPass
3096  << " vW=" << dpi.myVLinkWait
3097  << " d=" << dpi.myDistance
3098  << "\n";
3099  gDebugFlag1 = true; // See MSLink_DEBUG_OPENED
3100  }
3101 #endif
3102 
3103  // the vehicle must change the lane on one of the next lanes (XXX: refs to code further below???, Leo)
3104  if (link != nullptr && dpi.mySetRequest) {
3105 
3106  const LinkState ls = link->getState();
3107  // vehicles should brake when running onto a yellow light if the distance allows to halt in front
3108  const bool yellow = link->haveYellow();
3109  const bool canBrake = (dpi.myDistance > getCarFollowModel().brakeGap(myState.mySpeed, getCarFollowModel().getMaxDecel(), 0.)
3111  assert(link->getLaneBefore() != nullptr);
3112  const bool beyondStopLine = dpi.myDistance < link->getLaneBefore()->getVehicleStopOffset(this);
3113  const bool ignoreRedLink = ignoreRed(link, canBrake) || beyondStopLine;
3114  if (yellow && canBrake && !ignoreRedLink) {
3115  vSafe = dpi.myVLinkWait;
3116  myHaveToWaitOnNextLink = true;
3117 #ifdef DEBUG_CHECKREWINDLINKLANES
3118  if (DEBUG_COND) {
3119  std::cout << SIMTIME << " veh=" << getID() << " haveToWait (yellow)\n";
3120  }
3121 #endif
3122  break;
3123  }
3124  const bool influencerPrio = (myInfluencer != nullptr && !myInfluencer->getRespectJunctionPriority());
3125  MSLink::BlockingFoes collectFoes;
3126  bool opened = (yellow || influencerPrio
3127  || link->opened(dpi.myArrivalTime, dpi.myArrivalSpeed, dpi.getLeaveSpeed(),
3129  canBrake ? getImpatience() : 1,
3132  ls == LINKSTATE_ZIPPER ? &collectFoes : nullptr,
3133  ignoreRedLink, this));
3134  if (opened && myLaneChangeModel->getShadowLane() != nullptr) {
3135  const MSLink* const parallelLink = dpi.myLink->getParallelLink(myLaneChangeModel->getShadowDirection());
3136  if (parallelLink != nullptr) {
3137  const double shadowLatPos = getLateralPositionOnLane() - myLaneChangeModel->getShadowDirection() * 0.5 * (
3139  opened = yellow || influencerPrio || (opened && parallelLink->opened(dpi.myArrivalTime, dpi.myArrivalSpeed, dpi.getLeaveSpeed(),
3142  getWaitingTime(), shadowLatPos, nullptr,
3143  ignoreRedLink, this));
3144 #ifdef DEBUG_EXEC_MOVE
3145  if (DEBUG_COND) {
3146  std::cout << SIMTIME
3147  << " veh=" << getID()
3148  << " shadowLane=" << myLaneChangeModel->getShadowLane()->getID()
3149  << " shadowDir=" << myLaneChangeModel->getShadowDirection()
3150  << " parallelLink=" << (parallelLink == 0 ? "NULL" : parallelLink->getViaLaneOrLane()->getID())
3151  << " opened=" << opened
3152  << "\n";
3153  }
3154 #endif
3155  }
3156  }
3157  // vehicles should decelerate when approaching a minor link
3158 #ifdef DEBUG_EXEC_MOVE
3159  if (DEBUG_COND) {
3160  std::cout << SIMTIME
3161  << " opened=" << opened
3162  << " influencerPrio=" << influencerPrio
3163  << " linkPrio=" << link->havePriority()
3164  << " lastContMajor=" << link->lastWasContMajor()
3165  << " isCont=" << link->isCont()
3166  << " ignoreRed=" << ignoreRedLink
3167  << "\n";
3168  }
3169 #endif
3170  if (opened && !influencerPrio && !link->havePriority() && !link->lastWasContMajor() && !link->isCont() && !ignoreRedLink) {
3171  double visibilityDistance = link->getFoeVisibilityDistance();
3172  double determinedFoePresence = dpi.myDistance <= visibilityDistance;
3173  if (!determinedFoePresence && (canBrake || !yellow)) {
3174  vSafe = dpi.myVLinkWait;
3175  myHaveToWaitOnNextLink = true;
3176 #ifdef DEBUG_CHECKREWINDLINKLANES
3177  if (DEBUG_COND) {
3178  std::cout << SIMTIME << " veh=" << getID() << " haveToWait (minor)\n";
3179  }
3180 #endif
3181  break;
3182  } else {
3183  // past the point of no return. we need to drive fast enough
3184  // to make it across the link. However, minor slowdowns
3185  // should be permissible to follow leading traffic safely
3186  // basically, this code prevents dawdling
3187  // (it's harder to do this later using
3188  // SUMO_ATTR_JM_SIGMA_MINOR because we don't know whether the
3189  // vehicle is already too close to stop at that part of the code)
3190  //
3191  // XXX: There is a problem in subsecond simulation: If we cannot
3192  // make it across the minor link in one step, new traffic
3193  // could appear on a major foe link and cause a collision. Refs. #1845, #2123
3194  vSafeMinDist = dpi.myDistance; // distance that must be covered
3196  vSafeMin = MIN2((double) DIST2SPEED(vSafeMinDist + POSITION_EPS), dpi.myVLinkPass);
3197  } else {
3198  vSafeMin = MIN2((double) DIST2SPEED(2 * vSafeMinDist + NUMERICAL_EPS) - getSpeed(), dpi.myVLinkPass);
3199  }
3200  canBrakeVSafeMin = canBrake;
3201 #ifdef DEBUG_EXEC_MOVE
3202  if (DEBUG_COND) {
3203  std::cout << " vSafeMin=" << vSafeMin << " vSafeMinDist=" << vSafeMinDist << " canBrake=" << canBrake << "\n";
3204  }
3205 #endif
3206  }
3207  }
3208  // have waited; may pass if opened...
3209  if (opened) {
3210  vSafe = dpi.myVLinkPass;
3211  if (vSafe < getCarFollowModel().getMaxDecel() && vSafe <= dpi.myVLinkWait && vSafe < getCarFollowModel().maxNextSpeed(getSpeed(), this)) {
3212  // this vehicle is probably not gonna drive across the next junction (heuristic)
3213  myHaveToWaitOnNextLink = true;
3214 #ifdef DEBUG_CHECKREWINDLINKLANES
3215  if (DEBUG_COND) {
3216  std::cout << SIMTIME << " veh=" << getID() << " haveToWait (very slow)\n";
3217  }
3218 #endif
3219  }
3220  } else if (link->getState() == LINKSTATE_ZIPPER) {
3221  vSafeZipper = MIN2(vSafeZipper,
3222  link->getZipperSpeed(this, dpi.myDistance, dpi.myVLinkPass, dpi.myArrivalTime, &collectFoes));
3223  } else {
3224  vSafe = dpi.myVLinkWait;
3225  myHaveToWaitOnNextLink = true;
3226 #ifdef DEBUG_CHECKREWINDLINKLANES
3227  if (DEBUG_COND) {
3228  std::cout << SIMTIME << " veh=" << getID() << " haveToWait (closed)\n";
3229  }
3230 #endif
3231 #ifdef DEBUG_EXEC_MOVE
3232  if (DEBUG_COND) {
3233  std::cout << SIMTIME << " braking for closed link=" << link->getViaLaneOrLane()->getID() << "\n";
3234  }
3235 #endif
3236  break;
3237  }
3238  } else {
3239  if (link != nullptr && link->getInternalLaneBefore() != nullptr && myLane->isInternal() && link->getJunction() == myLane->getEdge().getToJunction()) {
3240  // blocked on the junction. yield request so other vehicles may
3241  // become junction leader
3242 #ifdef DEBUG_EXEC_MOVE
3243  if (DEBUG_COND) {
3244  std::cout << SIMTIME << " reseting junctionEntryTime at junction '" << link->getJunction()->getID() << "' beause of non-request exitLink\n";
3245  }
3246 #endif
3249  }
3250  // we have: i->link == 0 || !i->setRequest
3251  vSafe = dpi.myVLinkWait;
3252  if (vSafe < getSpeed()) {
3253  myHaveToWaitOnNextLink = true;
3254 #ifdef DEBUG_CHECKREWINDLINKLANES
3255  if (DEBUG_COND) {
3256  std::cout << SIMTIME << " veh=" << getID() << " haveToWait (no request, braking)\n";
3257  }
3258 #endif
3259  } else if (vSafe < SUMO_const_haltingSpeed) {
3260  myHaveToWaitOnNextLink = true;
3261 #ifdef DEBUG_CHECKREWINDLINKLANES
3262  if (DEBUG_COND) {
3263  std::cout << SIMTIME << " veh=" << getID() << " haveToWait (no request, stopping)\n";
3264  }
3265 #endif
3266  }
3267  if (link == nullptr && myLFLinkLanes.size() == 1
3268  && getBestLanesContinuation().size() > 1
3269  && getBestLanesContinuation()[1]->hadPermissionChanges()
3270  && myLane->getFirstAnyVehicle() == this) {
3271  // temporal lane closing without notification, visible to the
3272  // vehicle at the front of the queue
3273  updateBestLanes(true);
3274  //std::cout << SIMTIME << " veh=" << getID() << " updated bestLanes=" << toString(getBestLanesContinuation()) << "\n";
3275  }
3276  break;
3277  }
3278  }
3279 
3280 //#ifdef DEBUG_EXEC_MOVE
3281 // if (DEBUG_COND) {
3282 // std::cout << "\nvCurrent = " << toString(getSpeed(), 24) << "" << std::endl;
3283 // std::cout << "vSafe = " << toString(vSafe, 24) << "" << std::endl;
3284 // std::cout << "vSafeMin = " << toString(vSafeMin, 24) << "" << std::endl;
3285 // std::cout << "vSafeMinDist = " << toString(vSafeMinDist, 24) << "" << std::endl;
3286 //
3287 // double gap = getLeader().second;
3288 // std::cout << "gap = " << toString(gap, 24) << std::endl;
3289 // std::cout << "vSafeStoppedLeader = " << toString(getCarFollowModel().stopSpeed(this, getSpeed(), gap), 24)
3290 // << "\n" << std::endl;
3291 // }
3292 //#endif
3293 
3294  if ((MSGlobals::gSemiImplicitEulerUpdate && vSafe + NUMERICAL_EPS < vSafeMin)
3295  || (!MSGlobals::gSemiImplicitEulerUpdate && (vSafe + NUMERICAL_EPS < vSafeMin && vSafeMin != 0))) { // this might be good for the euler case as well
3296  // XXX: (Leo) This often called stopSpeed with vSafeMinDist==0 (for the ballistic update), since vSafe can become negative
3297  // 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
3298 #ifdef DEBUG_EXEC_MOVE
3299  if (DEBUG_COND) {
3300  std::cout << "vSafeMin Problem? vSafe=" << vSafe << " vSafeMin=" << vSafeMin << " vSafeMinDist=" << vSafeMinDist << std::endl;
3301  }
3302 #endif
3303  if (canBrakeVSafeMin && vSafe < getSpeed()) {
3304  // cannot drive across a link so we need to stop before it
3305  vSafe = MIN2(vSafe, getCarFollowModel().stopSpeed(this, getSpeed(), vSafeMinDist));
3306  vSafeMin = 0;
3307  myHaveToWaitOnNextLink = true;
3308 #ifdef DEBUG_CHECKREWINDLINKLANES
3309  if (DEBUG_COND) {
3310  std::cout << SIMTIME << " veh=" << getID() << " haveToWait (vSafe=" << vSafe << " < vSafeMin=" << vSafeMin << ")\n";
3311  }
3312 #endif
3313  } else {
3314  // if the link is yellow or visibility distance is large
3315  // then we might not make it across the link in one step anyway..
3316  // Possibly, the lane after the intersection has a lower speed limit so
3317  // we really need to drive slower already
3318  // -> keep driving without dawdling
3319  vSafeMin = vSafe;
3320  }
3321  }
3322 
3323  // vehicles inside a roundabout should maintain their requests
3324  if (myLane->getEdge().isRoundabout()) {
3325  myHaveToWaitOnNextLink = false;
3326  }
3327 
3328  vSafe = MIN2(vSafe, vSafeZipper);
3329 }
3330 
3331 
3332 double
3333 MSVehicle::processTraCISpeedControl(double vSafe, double vNext) {
3334  if (myInfluencer != nullptr) {
3336 #ifdef DEBUG_TRACI
3337  if DEBUG_COND2(this) {
3338  std::cout << SIMTIME << " MSVehicle::processTraCISpeedControl() for vehicle '" << getID() << "'"
3339  << " vSafe=" << vSafe << " (init)vNext=" << vNext;
3340  }
3341 #endif
3344  }
3345  const double vMax = getVehicleType().getCarFollowModel().maxNextSpeed(myState.mySpeed, this);
3346  double vMin = getVehicleType().getCarFollowModel().minNextSpeed(myState.mySpeed, this);
3348  vMin = MAX2(0., vMin);
3349  }
3350  vNext = myInfluencer->influenceSpeed(MSNet::getInstance()->getCurrentTimeStep(), vNext, vSafe, vMin, vMax);
3351 #ifdef DEBUG_TRACI
3352  if DEBUG_COND2(this) {
3353  std::cout << " (processed)vNext=" << vNext << std::endl;
3354  }
3355 #endif
3356  }
3357  return vNext;
3358 }
3359 
3360 
3361 void
3363 #ifdef DEBUG_ACTIONSTEPS
3364  if (DEBUG_COND) {
3365  std::cout << SIMTIME << " veh=" << getID() << " removePassedDriveItems()\n"
3366  << " Current items: ";
3367  for (auto& j : myLFLinkLanes) {
3368  if (j.myLink == 0) {
3369  std::cout << "\n Stop at distance " << j.myDistance;
3370  } else {
3371  const MSLane* to = j.myLink->getViaLaneOrLane();
3372  const MSLane* from = j.myLink->getLaneBefore();
3373  std::cout << "\n Link at distance " << j.myDistance << ": '"
3374  << (from == 0 ? "NONE" : from->getID()) << "' -> '" << (to == 0 ? "NONE" : to->getID()) << "'";
3375  }
3376  }
3377  std::cout << "\n myNextDriveItem: ";
3378  if (myLFLinkLanes.size() != 0) {
3379  if (myNextDriveItem->myLink == 0) {
3380  std::cout << "\n Stop at distance " << myNextDriveItem->myDistance;
3381  } else {
3382  const MSLane* to = myNextDriveItem->myLink->getViaLaneOrLane();
3383  const MSLane* from = myNextDriveItem->myLink->getLaneBefore();
3384  std::cout << "\n Link at distance " << myNextDriveItem->myDistance << ": '"
3385  << (from == 0 ? "NONE" : from->getID()) << "' -> '" << (to == 0 ? "NONE" : to->getID()) << "'";
3386  }
3387  }
3388  std::cout << std::endl;
3389  }
3390 #endif
3391  for (auto j = myLFLinkLanes.begin(); j != myNextDriveItem; ++j) {
3392 #ifdef DEBUG_ACTIONSTEPS
3393  if (DEBUG_COND) {
3394  std::cout << " Removing item: ";
3395  if (j->myLink == 0) {
3396  std::cout << "Stop at distance " << j->myDistance;
3397  } else {
3398  const MSLane* to = j->myLink->getViaLaneOrLane();
3399  const MSLane* from = j->myLink->getLaneBefore();
3400  std::cout << "Link at distance " << j->myDistance << ": '"
3401  << (from == 0 ? "NONE" : from->getID()) << "' -> '" << (to == 0 ? "NONE" : to->getID()) << "'";
3402  }
3403  std::cout << std::endl;
3404  }
3405 #endif
3406  if (j->myLink != nullptr) {
3407  j->myLink->removeApproaching(this);
3408  }
3409  }
3411  myNextDriveItem = myLFLinkLanes.begin();
3412 }
3413 
3414 
3415 void
3417 #ifdef DEBUG_ACTIONSTEPS
3418  if (DEBUG_COND) {
3419  std::cout << SIMTIME << " updateDriveItems(), veh='" << getID() << "' (lane: '" << getLane()->getID() << "')\nCurrent drive items:" << std::endl;
3420  for (const auto& dpi : myLFLinkLanes) {
3421  std::cout
3422  << " vPass=" << dpi.myVLinkPass
3423  << " vWait=" << dpi.myVLinkWait
3424  << " linkLane=" << (dpi.myLink == 0 ? "NULL" : dpi.myLink->getViaLaneOrLane()->getID())
3425  << " request=" << dpi.mySetRequest
3426  << "\n";
3427  }
3428  std::cout << " myNextDriveItem's linked lane: " << (myNextDriveItem->myLink == 0 ? "NULL" : myNextDriveItem->myLink->getViaLaneOrLane()->getID()) << std::endl;
3429  }
3430 #endif
3431  if (myLFLinkLanes.size() == 0) {
3432  // nothing to update
3433  return;
3434  }
3435  const MSLink* nextPlannedLink = nullptr;
3436 // auto i = myLFLinkLanes.begin();
3437  auto i = myNextDriveItem;
3438  while (i != myLFLinkLanes.end() && nextPlannedLink == nullptr) {
3439  nextPlannedLink = i->myLink;
3440  ++i;
3441  }
3442 
3443  if (nextPlannedLink == nullptr) {
3444  // No link for upcoming item -> no need for an update
3445 #ifdef DEBUG_ACTIONSTEPS
3446  if (DEBUG_COND) {
3447  std::cout << "Found no link-related drive item." << std::endl;
3448  }
3449 #endif
3450  return;
3451  }
3452 
3453  if (getLane() == nextPlannedLink->getLaneBefore()) {
3454  // Current lane approaches the stored next link, i.e. no LC happend and no update is required.
3455 #ifdef DEBUG_ACTIONSTEPS
3456  if (DEBUG_COND) {
3457  std::cout << "Continuing on planned lane sequence, no update required." << std::endl;
3458  }
3459 #endif
3460  return;
3461  }
3462  // Lane must have been changed, determine the change direction
3463  const MSLink* parallelLink = nextPlannedLink->getParallelLink(1);
3464  if (parallelLink != nullptr && parallelLink->getLaneBefore() == getLane()) {
3465  // lcDir = 1;
3466  } else {
3467  parallelLink = nextPlannedLink->getParallelLink(-1);
3468  if (parallelLink != nullptr && parallelLink->getLaneBefore() == getLane()) {
3469  // lcDir = -1;
3470  } else {
3471  // If the vehicle's current lane is not the approaching lane for the next
3472  // drive process item's link, it is expected to lead to a parallel link,
3473  // XXX: What if the lc was an overtaking maneuver and there is no upcoming link?
3474  // Then a stop item should be scheduled! -> TODO!
3475  //assert(false);
3476  return;
3477  }
3478  }
3479 #ifdef DEBUG_ACTIONSTEPS
3480  if (DEBUG_COND) {
3481  std::cout << "Changed lane. Drive items will be updated along the current lane continuation." << std::endl;
3482  }
3483 #endif
3484  // Trace link sequence along current best lanes and transfer drive items to the corresponding links
3485 // DriveItemVector::iterator driveItemIt = myLFLinkLanes.begin();
3486  DriveItemVector::iterator driveItemIt = myNextDriveItem;
3487  // In the loop below, lane holds the currently considered lane on the vehicles continuation (including internal lanes)
3488  const MSLane* lane = myLane;
3489  assert(myLane == parallelLink->getLaneBefore());
3490  // *lit is a pointer to the next lane in best continuations for the current lane (always non-internal)
3491  std::vector<MSLane*>::const_iterator bestLaneIt = getBestLanesContinuation().begin() + 1;
3492  // Pointer to the new link for the current drive process item
3493  MSLink* newLink = nullptr;
3494  while (driveItemIt != myLFLinkLanes.end()) {
3495  if (driveItemIt->myLink == nullptr) {
3496  // Items not related to a specific link are not updated
3497  // (XXX: when a stop item corresponded to a dead end, which is overcome by the LC that made
3498  // the update necessary, this may slow down the vehicle's continuation on the new lane...)
3499  ++driveItemIt;
3500  continue;
3501  }
3502  // Continuation links for current best lanes are less than for the former drive items (myLFLinkLanes)
3503  // We just remove the leftover link-items, as they cannot be mapped to new links.
3504  if (bestLaneIt == getBestLanesContinuation().end()) {
3505 #ifdef DEBUG_ACTIONSTEPS
3506  if (DEBUG_COND) {
3507  std::cout << "Reached end of the new continuation sequence. Erasing leftover link-items." << std::endl;
3508  }
3509 #endif
3510  while (driveItemIt != myLFLinkLanes.end()) {
3511  if (driveItemIt->myLink == nullptr) {
3512  ++driveItemIt;
3513  continue;
3514  } else {
3515  driveItemIt->myLink->removeApproaching(this);
3516  driveItemIt = myLFLinkLanes.erase(driveItemIt);
3517  }
3518  }
3519  break;
3520  }
3521  // Do the actual link-remapping for the item. And un/register approaching information on the corresponding links
3522  const MSLane* const target = *bestLaneIt;
3523  assert(!target->isInternal());
3524  newLink = nullptr;
3525  for (MSLink* const link : lane->getLinkCont()) {
3526  if (link->getLane() == target) {
3527  newLink = link;
3528  break;
3529  }
3530  }
3531 
3532  if (newLink == driveItemIt->myLink) {
3533  // new continuation merged into previous - stop update
3534 #ifdef DEBUG_ACTIONSTEPS
3535  if (DEBUG_COND) {
3536  std::cout << "Old and new continuation sequences merge at link\n"
3537  << "'" << newLink->getLaneBefore()->getID() << "'->'" << newLink->getViaLaneOrLane()->getID() << "'"
3538  << "\nNo update beyond merge required." << std::endl;
3539  }
3540 #endif
3541  break;
3542  }
3543 
3544 #ifdef DEBUG_ACTIONSTEPS
3545  if (DEBUG_COND) {
3546  std::cout << "lane=" << lane->getID() << "\nUpdating link\n '" << driveItemIt->myLink->getLaneBefore()->getID() << "'->'" << driveItemIt->myLink->getViaLaneOrLane()->getID() << "'"
3547  << "==> " << "'" << newLink->getLaneBefore()->getID() << "'->'" << newLink->getViaLaneOrLane()->getID() << "'" << std::endl;
3548  }
3549 #endif
3550  newLink->setApproaching(this, driveItemIt->myLink->getApproaching(this));
3551  driveItemIt->myLink->removeApproaching(this);
3552  driveItemIt->myLink = newLink;
3553  lane = newLink->getViaLaneOrLane();
3554  ++driveItemIt;
3555  if (!lane->isInternal()) {
3556  ++bestLaneIt;
3557  }
3558  }
3559 #ifdef DEBUG_ACTIONSTEPS
3560  if (DEBUG_COND) {
3561  std::cout << "Updated drive items:" << std::endl;
3562  for (const auto& dpi : myLFLinkLanes) {
3563  std::cout
3564  << " vPass=" << dpi.myVLinkPass
3565  << " vWait=" << dpi.myVLinkWait
3566  << " linkLane=" << (dpi.myLink == 0 ? "NULL" : dpi.myLink->getViaLaneOrLane()->getID())
3567  << " request=" << dpi.mySetRequest
3568  << "\n";
3569  }
3570  }
3571 #endif
3572 }
3573 
3574 
3575 void
3577  // To avoid casual blinking brake lights at high speeds due to dawdling of the
3578  // leading vehicle, we don't show brake lights when the deceleration could be caused
3579  // by frictional forces and air resistance (i.e. proportional to v^2, coefficient could be adapted further)
3580  double pseudoFriction = (0.05 + 0.005 * getSpeed()) * getSpeed();
3581  bool brakelightsOn = vNext < getSpeed() - ACCEL2SPEED(pseudoFriction);
3582 
3583  if (vNext <= SUMO_const_haltingSpeed) {
3584  brakelightsOn = true;
3585  }
3586  if (brakelightsOn && !isStopped()) {
3588  } else {
3590  }
3591 }
3592 
3593 
3594 void
3596  if (vNext <= SUMO_const_haltingSpeed && (!isStopped() || isIdling())) { // cf issue 2233
3599  } else {
3600  myWaitingTime = 0;
3602  }
3603 }
3604 
3605 
3606 void
3608  // update time loss (depends on the updated edge)
3609  if (!isStopped()) {
3610  const double vmax = myLane->getVehicleMaxSpeed(this);
3611  if (vmax > 0) {
3612  myTimeLoss += TS * (vmax - vNext) / vmax;
3613  }
3614  }
3615 }
3616 
3617 
3618 double
3619 MSVehicle::checkReversal(bool& canReverse, double speedThreshold, double seen) const {
3620 #ifdef DEBUG_REVERSE_BIDI
3621  if (DEBUG_COND) std::cout << SIMTIME << " checkReversal lane=" << myLane->getID()
3622  << " pos=" << myState.myPos
3623  << " speed=" << std::setprecision(6) << getPreviousSpeed() << std::setprecision(gPrecision)
3624  << " speedThreshold=" << speedThreshold
3625  << " seen=" << seen
3626  << " isRail=" << ((getVClass() & SVC_RAIL_CLASSES) != 0)
3627  << " speedOk=" << (getPreviousSpeed() <= speedThreshold)
3628  << " posOK=" << (myState.myPos <= myLane->getLength())
3629  << " normal=" << !myLane->isInternal()
3630  << " routeOK=" << ((myCurrEdge + 1) != myRoute->end())
3631  << " bidi=" << (myLane->getEdge().getBidiEdge() == *(myCurrEdge + 1))
3632  << " stopOk=" << (myStops.empty() || myStops.front().edge != myCurrEdge)
3633  << "\n";
3634 #endif
3635  if ((getVClass() & SVC_RAIL_CLASSES) != 0
3636  && getPreviousSpeed() <= speedThreshold
3637  && myState.myPos <= myLane->getLength()
3638  && !myLane->isInternal()
3639  && (myCurrEdge + 1) != myRoute->end()
3640  && myLane->getEdge().getBidiEdge() == *(myCurrEdge + 1)
3641  // ensure there are no further stops on this edge
3642  && (myStops.empty() || myStops.front().edge != myCurrEdge)
3643  ) {
3644  //if (isSelected()) std::cout << " check1 passed\n";
3645 
3646  // ensure that the vehicle is fully on bidi edges that allow reversal
3647  const int neededFutureRoute = 1 + (int)(MSGlobals::gUsingInternalLanes
3648  ? myFurtherLanes.size()
3649  : ceil(myFurtherLanes.size() / 2.0));
3650  const int remainingRoute = int(myRoute->end() - myCurrEdge) - 1;
3651  if (remainingRoute < neededFutureRoute) {
3652 #ifdef DEBUG_REVERSE_BIDI
3653  if (DEBUG_COND) {
3654  std::cout << " fail: remainingEdges=" << ((int)(myRoute->end() - myCurrEdge)) << " further=" << myFurtherLanes.size() << "\n";
3655  }
3656 #endif
3657  return getVehicleType().getMaxSpeed();
3658  }
3659  //if (isSelected()) std::cout << " check2 passed\n";
3660 
3661  // ensure that the turn-around connection exists from the current edge to it's bidi-edge
3662  const MSEdgeVector& succ = myLane->getEdge().getSuccessors();
3663  if (std::find(succ.begin(), succ.end(), myLane->getEdge().getBidiEdge()) == succ.end()) {
3664 #ifdef DEBUG_REVERSE_BIDI
3665  if (DEBUG_COND) {
3666  std::cout << " noTurn (bidi=" << myLane->getEdge().getBidiEdge()->getID() << " succ=" << toString(succ) << "\n";
3667  }
3668 #endif
3669  return getVehicleType().getMaxSpeed();
3670  }
3671  //if (isSelected()) std::cout << " check3 passed\n";
3672 
3673  // ensure that the vehicle front will not move past a stop on the bidi edge of the current edge
3674  if (!myStops.empty() && myStops.front().edge == (myCurrEdge + 1)) {
3675  const double stopPos = myStops.front().getEndPos(*this);
3676  const double brakeDist = getCarFollowModel().brakeGap(getSpeed(), getCarFollowModel().getMaxDecel(), 0);
3677  const double newPos = myLane->getLength() - (getBackPositionOnLane() + brakeDist);
3678  if (newPos > stopPos) {
3679 #ifdef DEBUG_REVERSE_BIDI
3680  if (DEBUG_COND) {
3681  std::cout << " reversal would go past stop on " << myLane->getBidiLane()->getID() << "\n";
3682  }
3683 #endif
3684  if (seen > MAX2(brakeDist, 1.0)) {
3685  return getVehicleType().getMaxSpeed();
3686  } else {
3687 #ifdef DEBUG_REVERSE_BIDI
3688  if (DEBUG_COND) {
3689  std::cout << " train is too long, skipping stop at " << stopPos << " cannot be avoided\n";
3690  }
3691 #endif
3692  }
3693  }
3694  }
3695  //if (isSelected()) std::cout << " check4 passed\n";
3696 
3697  // ensure that bidi-edges exist for all further edges and that no stops will be skipped when reversing
3698  int view = 2;
3699  for (MSLane* further : myFurtherLanes) {
3700  if (!further->getEdge().isInternal()) {
3701  if (further->getEdge().getBidiEdge() != *(myCurrEdge + view)) {
3702 #ifdef DEBUG_REVERSE_BIDI
3703  if (DEBUG_COND) {
3704  std::cout << " noBidi view=" << view << " further=" << further->getID() << " furtherBidi=" << Named::getIDSecure(further->getEdge().getBidiEdge()) << " future=" << (*(myCurrEdge + view))->getID() << "\n";
3705  }
3706 #endif
3707  return getVehicleType().getMaxSpeed();
3708  }
3709  if (!myStops.empty() && myStops.front().edge == (myCurrEdge + view)) {
3710  const double brakeDist = getCarFollowModel().brakeGap(getSpeed(), getCarFollowModel().getMaxDecel(), 0);
3711  const double stopPos = myStops.front().getEndPos(*this);
3712  const double newPos = further->getLength() - (getBackPositionOnLane(further) + brakeDist);
3713  if (newPos > stopPos) {
3714 #ifdef DEBUG_REVERSE_BIDI
3715  if (DEBUG_COND) {
3716  std::cout << " reversal would go past stop on further-opposite lane " << further->getBidiLane()->getID() << "\n";
3717  }
3718 #endif
3719  if (seen > MAX2(brakeDist, 1.0)) {
3720  canReverse = false;
3721  return getVehicleType().getMaxSpeed();
3722  } else {
3723 #ifdef DEBUG_REVERSE_BIDI
3724  if (DEBUG_COND) {
3725  std::cout << " train is too long, skipping stop at " << stopPos << " cannot be avoided\n";
3726  }
3727 #endif
3728  }
3729  }
3730  }
3731  view++;
3732  }
3733  }
3734  // reverse as soon as comfortably possible
3735  const double vMinComfortable = getCarFollowModel().minNextSpeed(getSpeed(), this);
3736 #ifdef DEBUG_REVERSE_BIDI
3737  if (DEBUG_COND) {
3738  std::cout << SIMTIME << " seen=" << seen << " vReverseOK=" << vMinComfortable << "\n";
3739  }
3740 #endif
3741  canReverse = true;
3742  return vMinComfortable;
3743  }
3744  return getVehicleType().getMaxSpeed();
3745 }
3746 
3747 
3748 void
3749 MSVehicle::processLaneAdvances(std::vector<MSLane*>& passedLanes, std::string& emergencyReason) {
3750  for (std::vector<MSLane*>::reverse_iterator i = myFurtherLanes.rbegin(); i != myFurtherLanes.rend(); ++i) {
3751  passedLanes.push_back(*i);
3752  }
3753  if (passedLanes.size() == 0 || passedLanes.back() != myLane) {
3754  passedLanes.push_back(myLane);
3755  }
3756  // let trains reverse direction
3757  bool reverseTrain = false;
3758  checkReversal(reverseTrain);
3759  if (reverseTrain) {
3760  // add some slack to ensure that the back of train does appear looped
3761  myState.myPos += 2 * (myLane->getLength() - myState.myPos) + myType->getLength() + NUMERICAL_EPS;
3762  myState.mySpeed = 0;
3763 #ifdef DEBUG_REVERSE_BIDI
3764  if (DEBUG_COND) {
3765  std::cout << SIMTIME << " reversing train=" << getID() << " newPos=" << myState.myPos << "\n";
3766  }
3767 #endif
3768  }
3769  // move on lane(s)
3770  if (myState.myPos > myLane->getLength()) {
3771  // The vehicle has moved at least to the next lane (maybe it passed even more than one)
3772  if (myCurrEdge != myRoute->end() - 1) {
3773  MSLane* approachedLane = myLane;
3774  // move the vehicle forward
3775  myNextDriveItem = myLFLinkLanes.begin();
3776  while (myNextDriveItem != myLFLinkLanes.end() && approachedLane != nullptr && myState.myPos > approachedLane->getLength()) {
3777  const MSLink* link = myNextDriveItem->myLink;
3778  const double linkDist = myNextDriveItem->myDistance;
3779  ++myNextDriveItem;
3780  // check whether the vehicle was allowed to enter lane
3781  // otherwise it is decelerated and we do not need to test for it's
3782  // approach on the following lanes when a lane changing is performed
3783  // proceed to the next lane
3784  if (approachedLane->mustCheckJunctionCollisions()) {
3785  // vehicle moves past approachedLane within a single step, collision checking must still be done
3787  }
3788  if (link != nullptr) {
3789  if ((getVClass() & SVC_RAIL_CLASSES) != 0
3790  && !myLane->isInternal()
3791  && myLane->getBidiLane() != nullptr
3792  && link->getLane()->getBidiLane() == myLane
3793  && !reverseTrain) {
3794  emergencyReason = " because it must reverse direction";
3795  approachedLane = nullptr;
3796  break;
3797  }
3798  if ((getVClass() & SVC_RAIL_CLASSES) != 0
3799  && myState.myPos < myLane->getLength() + NUMERICAL_EPS
3800  && hasStops() && getNextStop().edge == myCurrEdge) {
3801  // avoid skipping stop due to numerical instability
3802  // this is a special case for rail vehicles because they
3803  // continue myLFLinkLanes past stops
3804  approachedLane = myLane;
3806  break;
3807  }
3808  approachedLane = link->getViaLaneOrLane();
3809  if (myInfluencer == nullptr || myInfluencer->getEmergencyBrakeRedLight()) {
3810  bool beyondStopLine = linkDist < link->getLaneBefore()->getVehicleStopOffset(this);
3811  if (link->haveRed() && !ignoreRed(link, false) && !beyondStopLine && !reverseTrain) {
3812  emergencyReason = " because of a red traffic light";
3813  break;
3814  }
3815  }
3816  if (reverseTrain && approachedLane->isInternal()) {
3817  // avoid getting stuck on a slow turn-around internal lane
3818  myState.myPos += approachedLane->getLength();
3819  }
3820  } else if (myState.myPos < myLane->getLength() + NUMERICAL_EPS) {
3821  // avoid warning due to numerical instability
3822  approachedLane = myLane;
3824  } else if (reverseTrain) {
3825  approachedLane = (*(myCurrEdge + 1))->getLanes()[0];
3826  link = myLane->getLinkTo(approachedLane);
3827  assert(link != 0);
3828  while (link->getViaLane() != nullptr) {
3829  link = link->getViaLane()->getLinkCont()[0];
3830  }
3831  --myNextDriveItem;
3832  } else {
3833  emergencyReason = " because there is no connection to the next edge";
3834  approachedLane = nullptr;
3835  break;
3836  }
3837  if (approachedLane != myLane && approachedLane != nullptr) {
3839  myState.myPos -= myLane->getLength();
3840  assert(myState.myPos > 0);
3841  enterLaneAtMove(approachedLane);
3842  if (link->isEntryLink()) {
3845  }
3846  if (link->isConflictEntryLink()) {
3848  }
3849  if (link->isExitLink()) {
3850  // passed junction, reset for approaching the next one
3854  }
3855 #ifdef DEBUG_PLAN_MOVE_LEADERINFO
3856  if (DEBUG_COND) {
3857  std::cout << "Update junctionTimes link=" << link->getViaLaneOrLane()->getID()
3858  << " entry=" << link->isEntryLink() << " conflict=" << link->isConflictEntryLink() << " exit=" << link->isExitLink()
3859  << " ET=" << myJunctionEntryTime
3860  << " ETN=" << myJunctionEntryTimeNeverYield
3861  << " CET=" << myJunctionConflictEntryTime
3862  << "\n";
3863  }
3864 #endif
3865  if (hasArrivedInternal()) {
3866  break;
3867  }
3869  if (link->getDirection() == LinkDirection::LEFT || link->getDirection() == LinkDirection::RIGHT) {
3870  // abort lane change
3871  WRITE_WARNING("Vehicle '" + getID() + "' could not finish continuous lane change (turn lane) time=" +
3872  time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
3874  }
3875  }
3876  if (approachedLane->getEdge().isVaporizing()) {
3878  break;
3879  }
3880  passedLanes.push_back(approachedLane);
3881  }
3882  }
3883  // NOTE: Passed drive items will be erased in the next simstep's planMove()
3884 
3885 #ifdef DEBUG_ACTIONSTEPS
3886  if (DEBUG_COND && myNextDriveItem != myLFLinkLanes.begin()) {
3887  std::cout << "Updated drive items:" << std::endl;
3888  for (DriveItemVector::iterator i = myLFLinkLanes.begin(); i != myLFLinkLanes.end(); ++i) {
3889  std::cout
3890  << " vPass=" << (*i).myVLinkPass
3891  << " vWait=" << (*i).myVLinkWait
3892  << " linkLane=" << ((*i).myLink == 0 ? "NULL" : (*i).myLink->getViaLaneOrLane()->getID())
3893  << " request=" << (*i).mySetRequest
3894  << "\n";
3895  }
3896  }
3897 #endif
3898  } else if (!hasArrivedInternal() && myState.myPos < myLane->getLength() + NUMERICAL_EPS) {
3899  // avoid warning due to numerical instability when stopping at the end of the route
3901  }
3902 
3903  }
3904 }
3905 
3906 
3907 
3908 bool
3910 #ifdef DEBUG_EXEC_MOVE
3911  if (DEBUG_COND) {
3912  std::cout << "\nEXECUTE_MOVE\n"
3913  << SIMTIME
3914  << " veh=" << getID()
3915  << " speed=" << getSpeed() // toString(getSpeed(), 24)
3916  << std::endl;
3917  }
3918 #endif
3919 
3920 
3921  // Maximum safe velocity
3922  double vSafe = std::numeric_limits<double>::max();
3923  // Minimum safe velocity (lower bound).
3924  double vSafeMin = -std::numeric_limits<double>::max();
3925  // The distance to a link, which should either be crossed this step
3926  // or in front of which we need to stop.
3927  double vSafeMinDist = 0;
3928 
3929  if (myActionStep) {
3930  // Actuate control (i.e. choose bounds for safe speed in current simstep (euler), resp. after current sim step (ballistic))
3931  processLinkApproaches(vSafe, vSafeMin, vSafeMinDist);
3932 #ifdef DEBUG_ACTIONSTEPS
3933  if (DEBUG_COND) {
3934  std::cout << SIMTIME << " vehicle '" << getID() << "'\n"
3935  " vsafe from processLinkApproaches(): vsafe " << vSafe << std::endl;
3936  }
3937 #endif
3938  } else {
3939  // Continue with current acceleration
3940  vSafe = getSpeed() + ACCEL2SPEED(myAcceleration);
3941 #ifdef DEBUG_ACTIONSTEPS
3942  if (DEBUG_COND) {
3943  std::cout << SIMTIME << " vehicle '" << getID() << "' skips processLinkApproaches()\n"
3944  " continues with constant accel " << myAcceleration << "...\n"
3945  << "speed: " << getSpeed() << " -> " << vSafe << std::endl;
3946  }
3947 #endif
3948  }
3949 
3950 
3951 //#ifdef DEBUG_EXEC_MOVE
3952 // if (DEBUG_COND) {
3953 // std::cout << "vSafe = " << toString(vSafe,12) << "\n" << std::endl;
3954 // }
3955 //#endif
3956 
3957  // Determine vNext = speed after current sim step (ballistic), resp. in current simstep (euler)
3958  // Call to finalizeSpeed applies speed reduction due to dawdling / lane changing but ensures minimum safe speed
3959  double vNext = vSafe;
3960  if (myActionStep) {
3961  vNext = getCarFollowModel().finalizeSpeed(this, vSafe);
3962  if (vNext > 0) {
3963  vNext = MAX2(vNext, vSafeMin);
3964  }
3965  }
3966  // (Leo) to avoid tiny oscillations (< 1e-10) of vNext in a standing vehicle column (observed for ballistic update), we cap off vNext
3967  // (We assure to do this only for vNext<<NUMERICAL_EPS since otherwise this would nullify the workaround for #2995
3968  if (fabs(vNext) < NUMERICAL_EPS_SPEED) {
3969  vNext = 0.;
3970  }
3971 #ifdef DEBUG_EXEC_MOVE
3972  if (DEBUG_COND) {
3973  std::cout << SIMTIME << " finalizeSpeed vSafe=" << vSafe << " vSafeMin=" << (vSafeMin == -std::numeric_limits<double>::max() ? "-Inf" : toString(vSafeMin))
3974  << " vNext=" << vNext << " (i.e. accel=" << SPEED2ACCEL(vNext - getSpeed()) << ")" << std::endl;
3975  }
3976 #endif
3977 
3978  // vNext may be higher than vSafe without implying a bug:
3979  // - when approaching a green light that suddenly switches to yellow
3980  // - when using unregulated junctions
3981  // - when using tau < step-size
3982  // - when using unsafe car following models
3983  // - when using TraCI and some speedMode / laneChangeMode settings
3984  //if (vNext > vSafe + NUMERICAL_EPS) {
3985  // WRITE_WARNING("vehicle '" + getID() + "' cannot brake hard enough to reach safe speed "
3986  // + toString(vSafe, 4) + ", moving at " + toString(vNext, 4) + " instead. time="
3987  // + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
3988  //}
3989 
3991  vNext = MAX2(vNext, 0.);
3992  } else {
3993  // (Leo) Ballistic: negative vNext can be used to indicate a stop within next step.
3994  }
3995 
3996  // Check for speed advices from the traci client
3997  vNext = processTraCISpeedControl(vSafe, vNext);
3998 
3999  // the acceleration of a vehicle equipped with the elecHybrid device is restricted by the maximal power of the electric drive as well
4000  MSDevice_ElecHybrid* elecHybridOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
4001  if (elecHybridOfVehicle != nullptr) {
4002  // this is the consumption given by the car following model-computed acceleration
4003  elecHybridOfVehicle->setConsum(elecHybridOfVehicle->consumption(*this, (vNext - this->getSpeed()) / TS, vNext));
4004  // but the maximum power of the electric motor may be lower
4005  // it needs to be converted from [W] to [Wh/s] (3600s / 1h) so that TS can be taken into account
4006  double maxPower = elecHybridOfVehicle->getParameterDouble(toString(SUMO_ATTR_MAXIMUMPOWER)) / 3600;
4007  if (elecHybridOfVehicle->getConsum() / TS > maxPower) {
4008  // no, we cannot accelerate that fast, recompute the maximum possible acceleration
4009  double accel = elecHybridOfVehicle->acceleration(*this, maxPower, this->getSpeed());
4010  // and update the speed of the vehicle
4011  vNext = MIN2(vNext, this->getSpeed() + accel * TS);
4012  vNext = MAX2(vNext, 0.);
4013  // and set the vehicle consumption to reflect this
4014  elecHybridOfVehicle->setConsum(elecHybridOfVehicle->consumption(*this, (vNext - this->getSpeed()) / TS, vNext));
4015  }
4016  }
4017 
4018  setBrakingSignals(vNext);
4019  updateWaitingTime(vNext);
4020 
4021  // update position and speed
4022  int oldLaneIndex = myLane->getIndex();
4023  const MSLane* oldLaneMaybeOpposite = myLane;
4024  if (myLaneChangeModel->isOpposite()) {
4025  // transform to the forward-direction lane, move and then transform back
4028  }
4029  updateState(vNext);
4030 
4031  // Lanes, which the vehicle touched at some moment of the executed simstep
4032  std::vector<MSLane*> passedLanes;
4033  // remeber previous lane (myLane is updated in processLaneAdvances)
4034  const MSLane* oldLane = myLane;
4035  // Reason for a possible emergency stop
4036  std::string emergencyReason = " for unknown reasons";
4037  processLaneAdvances(passedLanes, emergencyReason);
4038 
4039  updateTimeLoss(vNext);
4041 
4042  if (!hasArrivedInternal() && !myLane->getEdge().isVaporizing()) {
4043  if (myState.myPos > myLane->getLength()) {
4044  WRITE_WARNING("Vehicle '" + getID() + "' performs emergency stop at the end of lane '" + myLane->getID()
4045  + "'" + emergencyReason
4046  + " (decel=" + toString(myAcceleration - myState.mySpeed)
4047  + ", offset=" + toString(myState.myPos - myLane->getLength())
4048  + "), time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
4052  myState.mySpeed = 0;
4053  myAcceleration = 0;
4054  }
4055  const MSLane* oldBackLane = getBackLane();
4056  if (myLaneChangeModel->isOpposite()) {
4057  passedLanes.clear(); // ignore back occupation
4058  }
4059 #ifdef DEBUG_ACTIONSTEPS
4060  if (DEBUG_COND) {
4061  std::cout << SIMTIME << " veh '" << getID() << "' updates further lanes." << std::endl;
4062  }
4063 #endif
4065  // bestLanes need to be updated before lane changing starts. NOTE: This call is also a presumption for updateDriveItems()
4066  updateBestLanes();
4067  if (myLane != oldLane || oldBackLane != getBackLane()) {
4068  if (myLaneChangeModel->getShadowLane() != nullptr || getLateralOverlap() > POSITION_EPS) {
4069  // shadow lane must be updated if the front or back lane changed
4070  // either if we already have a shadowLane or if there is lateral overlap
4072  }
4074  // The vehicles target lane must be also be updated if the front or back lane changed
4076  }
4077  }
4078  setBlinkerInformation(); // needs updated bestLanes
4079  //change the blue light only for emergency vehicles SUMOVehicleClass
4080  if (myType->getVehicleClass() == SVC_EMERGENCY) {
4081  setEmergencyBlueLight(MSNet::getInstance()->getCurrentTimeStep());
4082  }
4083  // State needs to be reset for all vehicles before the next call to MSEdgeControl::changeLanes
4084  if (myActionStep) {
4085  // check (#2681): Can this be skipped?
4087  } else {
4088 #ifdef DEBUG_ACTIONSTEPS
4089  if (DEBUG_COND) {
4090  std::cout << SIMTIME << " veh '" << getID() << "' skips LCM->prepareStep()." << std::endl;
4091  }
4092 #endif
4093  }
4094  myAngle = computeAngle();
4095  }
4096 
4097 #ifdef DEBUG_EXEC_MOVE
4098  if (DEBUG_COND) {
4099  std::cout << SIMTIME << " executeMove finished veh=" << getID() << " lane=" << myLane->getID() << " myPos=" << getPositionOnLane() << " myPosLat=" << getLateralPositionOnLane() << "\n";
4100  gDebugFlag1 = false; // See MSLink_DEBUG_OPENED
4101  }
4102 #endif
4103  if (myLaneChangeModel->isOpposite()) {
4104  // transform back to the opposite-direction lane
4105  MSLane* newOpposite = nullptr;
4106  const MSEdge* newOppositeEdge = myLane->getEdge().getOppositeEdge();
4107  if (newOppositeEdge != nullptr && oldLaneIndex < newOppositeEdge->getNumLanes()) {
4108  newOpposite = newOppositeEdge->getLanes()[oldLaneIndex];
4109  }
4110  if (newOpposite == nullptr) {
4111  if (!myLaneChangeModel->hasBlueLight()) {
4112  // unusual overtaking at junctions is ok for emergency vehicles
4113  WRITE_WARNING("Unexpected end of opposite lane for vehicle '" + getID() + "' at lane '" + myLane->getID() + "', time=" +
4114  time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
4115  }
4117  if (myState.myPos < getLength()) {
4118  // further lanes is always cleared during opposite driving
4119  MSLane* oldOpposite = oldLane->getOpposite();
4120  if (oldOpposite != nullptr) {
4121  myFurtherLanes.push_back(oldOpposite);
4122  myFurtherLanesPosLat.push_back(0);
4123  // small value since the lane is going in the other direction
4125  myAngle = computeAngle();
4126  } else {
4127 #ifdef WIN32
4128 #pragma warning(push)
4129 #pragma warning(disable: 4127) // do not warn about constant conditional expression
4130 #endif
4131  SOFT_ASSERT(false);
4132 #ifdef WIN32
4133 #pragma warning(pop)
4134 #endif
4135  }
4136  }
4137  } else {
4139  myLane = newOpposite;
4140  oldLane = oldLaneMaybeOpposite;
4141  //std::cout << SIMTIME << " updated myLane=" << Named::getIDSecure(myLane) << " oldLane=" << oldLane->getID() << "\n";
4144  }
4145  }
4147  // Return whether the vehicle did move to another lane
4148  return myLane != oldLane;
4149 }
4150 
4151 void
4153  //std::cout << SIMTIME << " veh=" << getID() << " executeFractionalMove dist=" << dist << "\n";
4154  myState.myPos += dist;
4155  myState.myLastCoveredDist = dist;
4157 
4158  const std::vector<const MSLane*> lanes = getUpcomingLanesUntil(dist);
4160  for (int i = 0; i < (int)lanes.size(); i++) {
4161  MSLink* link = nullptr;
4162  if (i + 1 < (int)lanes.size()) {
4163  const MSLane* const to = lanes[i + 1];
4164  const bool internal = to->isInternal();
4165  for (MSLink* const l : lanes[i]->getLinkCont()) {
4166  if ((internal && l->getViaLane() == to) || (!internal && l->getLane() == to)) {
4167  link = l;
4168  break;
4169  }
4170  }
4171  }
4172  myLFLinkLanes.emplace_back(link, getSpeed(), getSpeed(), true, t, getSpeed(), 0, 0, dist);
4173  }
4174  // minimum execute move:
4175  std::vector<MSLane*> passedLanes;
4176  // Reason for a possible emergency stop
4177  std::string emergencyReason = " for unknown reasons";
4178  if (lanes.size() > 1) {
4180  }
4181  processLaneAdvances(passedLanes, emergencyReason);
4183  if (lanes.size() > 1) {
4185  }
4186 }
4187 
4188 
4189 void
4190 MSVehicle::updateState(double vNext) {
4191  // update position and speed
4192  double deltaPos; // positional change
4194  // euler
4195  deltaPos = SPEED2DIST(vNext);
4196  } else {
4197  // ballistic
4198  deltaPos = getDeltaPos(SPEED2ACCEL(vNext - myState.mySpeed));
4199  }
4200 
4201  // the *mean* acceleration during the next step (probably most appropriate for emission calculation)
4202  // NOTE: for the ballistic update vNext may be negative, indicating a stop.
4203  myAcceleration = SPEED2ACCEL(MAX2(vNext, 0.) - myState.mySpeed);
4204 
4205 #ifdef DEBUG_EXEC_MOVE
4206  if (DEBUG_COND) {
4207  std::cout << SIMTIME << " updateState() for veh '" << getID() << "': deltaPos=" << deltaPos
4208  << " pos=" << myState.myPos << " newPos=" << myState.myPos + deltaPos << std::endl;
4209  }
4210 #endif
4211  double decelPlus = -myAcceleration - getCarFollowModel().getMaxDecel() - NUMERICAL_EPS;
4212  if (decelPlus > 0) {
4213  const double previousAcceleration = SPEED2ACCEL(myState.mySpeed - myState.myPreviousSpeed);
4214  if (myAcceleration + NUMERICAL_EPS < previousAcceleration) {
4215  // vehicle brakes beyond wished maximum deceleration (only warn at the start of the braking manoeuvre)
4216  decelPlus += 2 * NUMERICAL_EPS;
4217  const double emergencyFraction = decelPlus / MAX2(NUMERICAL_EPS, getCarFollowModel().getEmergencyDecel() - getCarFollowModel().getMaxDecel());
4218  if (emergencyFraction >= MSGlobals::gEmergencyDecelWarningThreshold) {
4219  WRITE_WARNING("Vehicle '" + getID()
4220  + "' performs emergency braking with decel=" + toString(myAcceleration)
4221  + " wished=" + toString(getCarFollowModel().getMaxDecel())
4222  + " severity=" + toString(emergencyFraction)
4223  //+ " decelPlus=" + toString(decelPlus)
4224  //+ " prevAccel=" + toString(previousAcceleration)
4225  //+ " reserve=" + toString(MAX2(NUMERICAL_EPS, getCarFollowModel().getEmergencyDecel() - getCarFollowModel().getMaxDecel()))
4226  + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
4227  }
4228  }
4229  }
4230 
4232  myState.mySpeed = MAX2(vNext, 0.);
4233 
4234  if (myInfluencer != nullptr && myInfluencer->isRemoteControlled()) {
4235  deltaPos = myInfluencer->implicitDeltaPosRemote(this);
4236  }
4237 
4238  myState.myPos += deltaPos;
4239  myState.myLastCoveredDist = deltaPos;
4240  myNextTurn.first -= deltaPos;
4241 
4243 }
4244 
4245 void
4247  updateState(0);
4248  // deboard while parked
4249  if (myPersonDevice != nullptr) {
4251  }
4252  if (myContainerDevice != nullptr) {
4254  }
4255 }
4256 
4257 
4258 void
4261  delete myCFVariables;
4263 }
4264 
4265 
4266 const MSLane*
4268  if (myFurtherLanes.size() > 0) {
4269  return myFurtherLanes.back();
4270  } else {
4271  return myLane;
4272  }
4273 }
4274 
4275 
4276 double
4277 MSVehicle::updateFurtherLanes(std::vector<MSLane*>& furtherLanes, std::vector<double>& furtherLanesPosLat,
4278  const std::vector<MSLane*>& passedLanes) {
4279 #ifdef DEBUG_SETFURTHER
4280  if (DEBUG_COND) std::cout << SIMTIME << " veh=" << getID()
4281  << " updateFurtherLanes oldFurther=" << toString(furtherLanes)
4282  << " oldFurtherPosLat=" << toString(furtherLanesPosLat)
4283  << " passed=" << toString(passedLanes)
4284  << "\n";
4285 #endif
4286  for (std::vector<MSLane*>::iterator i = furtherLanes.begin(); i != furtherLanes.end(); ++i) {
4287  (*i)->resetPartialOccupation(this);
4288  }
4289 
4290  std::vector<MSLane*> newFurther;
4291  std::vector<double> newFurtherPosLat;
4292  double backPosOnPreviousLane = myState.myPos - getLength();
4293  bool widthShift = myFurtherLanesPosLat.size() > myFurtherLanes.size();
4294  if (passedLanes.size() > 1) {
4295  // There are candidates for further lanes. (passedLanes[-1] is the current lane, or current shadow lane in context of updateShadowLanes())
4296  std::vector<MSLane*>::const_iterator fi = furtherLanes.begin();
4297  std::vector<double>::const_iterator fpi = furtherLanesPosLat.begin();
4298  for (auto pi = passedLanes.rbegin() + 1; pi != passedLanes.rend() && backPosOnPreviousLane < 0; ++pi) {
4299  // As long as vehicle back reaches into passed lane, add it to the further lanes
4300  newFurther.push_back(*pi);
4301  backPosOnPreviousLane += (*pi)->setPartialOccupation(this);
4302  if (fi != furtherLanes.end() && *pi == *fi) {
4303  // Lateral position on this lane is already known. Assume constant and use old value.
4304  newFurtherPosLat.push_back(*fpi);
4305  ++fi;
4306  ++fpi;
4307  } else {
4308  // The lane *pi was not in furtherLanes before.
4309  // If it is downstream, we assume as lateral position the current position
4310  // If it is a new lane upstream (can appear as shadow further in case of LC-maneuvering, e.g.)
4311  // we assign the last known lateral position.
4312  if (newFurtherPosLat.size() == 0) {
4313  if (widthShift) {
4314  newFurtherPosLat.push_back(myFurtherLanesPosLat.back());
4315  } else {
4316  newFurtherPosLat.push_back(myState.myPosLat);
4317  }
4318  } else {
4319  newFurtherPosLat.push_back(newFurtherPosLat.back());
4320  }
4321  }
4322 #ifdef DEBUG_SETFURTHER
4323  if (DEBUG_COND) {
4324  std::cout << SIMTIME << " updateFurtherLanes \n"
4325  << " further lane '" << (*pi)->getID() << "' backPosOnPreviousLane=" << backPosOnPreviousLane
4326  << std::endl;
4327  }
4328 #endif
4329  }
4330  furtherLanes = newFurther;
4331  furtherLanesPosLat = newFurtherPosLat;
4332  } else {
4333  furtherLanes.clear();
4334  furtherLanesPosLat.clear();
4335  }
4336 #ifdef DEBUG_SETFURTHER
4337  if (DEBUG_COND) std::cout
4338  << " newFurther=" << toString(furtherLanes)
4339  << " newFurtherPosLat=" << toString(furtherLanesPosLat)
4340  << " newBackPos=" << backPosOnPreviousLane
4341  << "\n";
4342 #endif
4343  return backPosOnPreviousLane;
4344 }
4345 
4346 
4347 double
4348 MSVehicle::getBackPositionOnLane(const MSLane* lane, bool calledByGetPosition) const {
4349 #ifdef DEBUG_FURTHER
4350  if (DEBUG_COND) {
4351  std::cout << SIMTIME
4352  << " getBackPositionOnLane veh=" << getID()
4353  << " lane=" << Named::getIDSecure(lane)
4354  << " pos=" << myState.myPos
4355  << " backPos=" << myState.myBackPos
4356  << " myLane=" << myLane->getID()
4357  << " further=" << toString(myFurtherLanes)
4358  << " furtherPosLat=" << toString(myFurtherLanesPosLat)
4359  << "\n shadowLane=" << Named::getIDSecure(myLaneChangeModel->getShadowLane())
4360  << " shadowFurther=" << toString(myLaneChangeModel->getShadowFurtherLanes())
4361  << " shadowFurtherPosLat=" << toString(myLaneChangeModel->getShadowFurtherLanesPosLat())
4362  << "\n targetLane=" << Named::getIDSecure(myLaneChangeModel->getTargetLane())
4363  << " furtherTargets=" << toString(myLaneChangeModel->getFurtherTargetLanes())
4364  << std::endl;
4365  }
4366 #endif
4367  if (lane == myLane
4368  || lane == myLaneChangeModel->getShadowLane()
4369  || lane == myLaneChangeModel->getTargetLane()) {
4370  if (myLaneChangeModel->isOpposite()) {
4371  if (lane == myLaneChangeModel->getShadowLane()) {
4372  return lane->getLength() - myState.myPos - myType->getLength();
4373  } else {
4374  return myState.myPos + (calledByGetPosition ? -1 : 1) * myType->getLength();
4375  }
4376  } else if (&lane->getEdge() != &myLane->getEdge()) {
4377  return lane->getLength() - myState.myPos + (calledByGetPosition ? -1 : 1) * myType->getLength();
4378  } else {
4379  return myState.myPos - myType->getLength();
4380  }
4381  } else if (myFurtherLanes.size() > 0 && lane == myFurtherLanes.back()) {
4382  return myState.myBackPos;
4383  } else if ((myLaneChangeModel->getShadowFurtherLanes().size() > 0 && lane == myLaneChangeModel->getShadowFurtherLanes().back())
4384  || (myLaneChangeModel->getFurtherTargetLanes().size() > 0 && lane == myLaneChangeModel->getFurtherTargetLanes().back())) {
4385  assert(myFurtherLanes.size() > 0);
4386  if (lane->getLength() == myFurtherLanes.back()->getLength()) {
4387  return myState.myBackPos;
4388  } else {
4389  // interpolate
4390  //if (DEBUG_COND) {
4391  //if (myFurtherLanes.back()->getLength() != lane->getLength()) {
4392  // std::cout << SIMTIME << " veh=" << getID() << " lane=" << lane->getID() << " further=" << myFurtherLanes.back()->getID()
4393  // << " len=" << lane->getLength() << " fLen=" << myFurtherLanes.back()->getLength()
4394  // << " backPos=" << myState.myBackPos << " result=" << myState.myBackPos / myFurtherLanes.back()->getLength() * lane->getLength() << "\n";
4395  //}
4396  return myState.myBackPos / myFurtherLanes.back()->getLength() * lane->getLength();
4397  }
4398  } else {
4399  if (lane->getBidiLane() != nullptr) {
4400  if (myLane == lane->getBidiLane()) {
4401  return lane->getLength() - (myState.myPos - myType->getLength());
4402  } else if (myFurtherLanes.size() > 0 && lane->getBidiLane() == myFurtherLanes.back()) {
4403  return lane->getLength() - myState.myBackPos;
4404  }
4405  }
4406  //if (DEBUG_COND) std::cout << SIMTIME << " veh=" << getID() << " myFurtherLanes=" << toString(myFurtherLanes) << "\n";
4407  double leftLength = myType->getLength() - myState.myPos;
4408 
4409  std::vector<MSLane*>::const_iterator i = myFurtherLanes.begin();
4410  while (leftLength > 0 && i != myFurtherLanes.end()) {
4411  leftLength -= (*i)->getLength();
4412  //if (DEBUG_COND) std::cout << " comparing i=" << (*i)->getID() << " lane=" << lane->getID() << "\n";
4413  if (*i == lane) {
4414  return -leftLength;
4415  }
4416  ++i;
4417  }
4418  //if (DEBUG_COND) std::cout << SIMTIME << " veh=" << getID() << " myShadowFurtherLanes=" << toString(myLaneChangeModel->getShadowFurtherLanes()) << "\n";
4419  leftLength = myType->getLength() - myState.myPos;
4421  while (leftLength > 0 && i != myLaneChangeModel->getShadowFurtherLanes().end()) {
4422  leftLength -= (*i)->getLength();
4423  //if (DEBUG_COND) std::cout << " comparing i=" << (*i)->getID() << " lane=" << lane->getID() << "\n";
4424  if (*i == lane) {
4425  return -leftLength;
4426  }
4427  ++i;
4428  }
4429  //if (DEBUG_COND) std::cout << SIMTIME << " veh=" << getID() << " myFurtherTargetLanes=" << toString(myLaneChangeModel->getFurtherTargetLanes()) << "\n";
4430  leftLength = myType->getLength() - myState.myPos;
4431  i = getFurtherLanes().begin();
4432  const std::vector<MSLane*> furtherTargetLanes = myLaneChangeModel->getFurtherTargetLanes();
4433  auto j = furtherTargetLanes.begin();
4434  while (leftLength > 0 && j != furtherTargetLanes.end()) {
4435  leftLength -= (*i)->getLength();
4436  // if (DEBUG_COND) std::cout << " comparing i=" << (*i)->getID() << " lane=" << lane->getID() << "\n";
4437  if (*j == lane) {
4438  return -leftLength;
4439  }
4440  ++i;
4441  ++j;
4442  }
4443  WRITE_WARNING("Request backPos of vehicle '" + getID() + "' for invalid lane '" + Named::getIDSecure(lane)
4444  + "' time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".")
4445 #ifdef WIN32
4446 #pragma warning(push)
4447 #pragma warning(disable: 4127) // do not warn about constant conditional expression
4448 #endif
4449  SOFT_ASSERT(false);
4450 #ifdef WIN32
4451 #pragma warning(pop)
4452 #endif
4453  return myState.myBackPos;
4454  }
4455 }
4456 
4457 
4458 double
4460  return getBackPositionOnLane(lane, true) + myType->getLength();
4461 }
4462 
4463 
4464 bool
4465 MSVehicle::isFrontOnLane(const MSLane* lane) const {
4466  return lane == myLane || lane == myLaneChangeModel->getShadowLane();
4467 }
4468 
4469 
4470 void
4471 MSVehicle::checkRewindLinkLanes(const double lengthsInFront, DriveItemVector& lfLinks) const {
4473  double seenSpace = -lengthsInFront;
4474 #ifdef DEBUG_CHECKREWINDLINKLANES
4475  if (DEBUG_COND) {
4476  std::cout << "\nCHECK_REWIND_LINKLANES\n" << " veh=" << getID() << " lengthsInFront=" << lengthsInFront << "\n";
4477  };
4478 #endif
4479  bool foundStopped = false;
4480  // compute available space until a stopped vehicle is found
4481  // this is the sum of non-interal lane length minus in-between vehicle lengths
4482  for (int i = 0; i < (int)lfLinks.size(); ++i) {
4483  // skip unset links
4484  DriveProcessItem& item = lfLinks[i];
4485 #ifdef DEBUG_CHECKREWINDLINKLANES
4486  if (DEBUG_COND) std::cout << SIMTIME
4487  << " link=" << (item.myLink == 0 ? "NULL" : item.myLink->getViaLaneOrLane()->getID())
4488  << " foundStopped=" << foundStopped;
4489 #endif
4490  if (item.myLink == nullptr || foundStopped) {
4491  if (!foundStopped) {
4492  item.availableSpace += seenSpace;
4493  } else {
4494  item.availableSpace = seenSpace;
4495  }
4496 #ifdef DEBUG_CHECKREWINDLINKLANES
4497  if (DEBUG_COND) {
4498  std::cout << " avail=" << item.availableSpace << "\n";
4499  }
4500 #endif
4501  continue;
4502  }
4503  // get the next lane, determine whether it is an internal lane
4504  const MSLane* approachedLane = item.myLink->getViaLane();
4505  if (approachedLane != nullptr) {
4506  if (keepClear(item.myLink)) {
4507  seenSpace = seenSpace - approachedLane->getBruttoVehLenSum();
4508  if (approachedLane == myLane) {
4509  seenSpace += getVehicleType().getLengthWithGap();
4510  }
4511  } else {
4512  seenSpace = seenSpace + approachedLane->getSpaceTillLastStanding(this, foundStopped);// - approachedLane->getBruttoVehLenSum() + approachedLane->getLength();
4513  }
4514  item.availableSpace = seenSpace;
4515 #ifdef DEBUG_CHECKREWINDLINKLANES
4516  if (DEBUG_COND) std::cout
4517  << " approached=" << approachedLane->getID()
4518  << " approachedBrutto=" << approachedLane->getBruttoVehLenSum()
4519  << " avail=" << item.availableSpace
4520  << " seenSpace=" << seenSpace
4521  << " hadStoppedVehicle=" << item.hadStoppedVehicle
4522  << " lengthsInFront=" << lengthsInFront
4523  << "\n";
4524 #endif
4525  continue;
4526  }
4527  approachedLane = item.myLink->getLane();
4528  const MSVehicle* last = approachedLane->getLastAnyVehicle();
4529  if (last == nullptr || last == this) {
4530  if (approachedLane->getLength() > getVehicleType().getLength()
4531  || keepClear(item.myLink)) {
4532  seenSpace += approachedLane->getLength();
4533  }
4534  item.availableSpace = seenSpace;
4535 #ifdef DEBUG_CHECKREWINDLINKLANES
4536  if (DEBUG_COND) {
4537  std::cout << " last=" << Named::getIDSecure(last) << " laneLength=" << approachedLane->getLength() << " avail=" << item.availableSpace << "\n";
4538  }
4539 #endif
4540  } else {
4541  bool foundStopped2 = false;
4542  const double spaceTillLastStanding = approachedLane->getSpaceTillLastStanding(this, foundStopped2);
4543  seenSpace += spaceTillLastStanding;
4544  if (foundStopped2) {
4545  foundStopped = true;
4546  item.hadStoppedVehicle = true;
4547  }
4548  item.availableSpace = seenSpace;
4549  if (last->myHaveToWaitOnNextLink || last->isStopped()) {
4550  foundStopped = true;
4551  item.hadStoppedVehicle = true;
4552  }
4553 #ifdef DEBUG_CHECKREWINDLINKLANES
4554  if (DEBUG_COND) std::cout
4555  << " approached=" << approachedLane->getID()
4556  << " last=" << last->getID()
4557  << " lastHasToWait=" << last->myHaveToWaitOnNextLink
4558  << " lastBrakeLight=" << last->signalSet(VEH_SIGNAL_BRAKELIGHT)
4559  << " lastBrakeGap=" << last->getCarFollowModel().brakeGap(last->getSpeed())
4560  << " lastGap=" << (last->getBackPositionOnLane(approachedLane) + last->getCarFollowModel().brakeGap(last->getSpeed()) - last->getSpeed() * last->getCarFollowModel().getHeadwayTime()
4561  // gap of last up to the next intersection
4562  - last->getVehicleType().getMinGap())
4563  << " stls=" << spaceTillLastStanding
4564  << " avail=" << item.availableSpace
4565  << " seenSpace=" << seenSpace
4566  << " foundStopped=" << foundStopped
4567  << " foundStopped2=" << foundStopped2
4568  << "\n";
4569 #endif
4570  }
4571  }
4572 
4573  // check which links allow continuation and add pass available to the previous item
4574  for (int i = ((int)lfLinks.size() - 1); i > 0; --i) {
4575  DriveProcessItem& item = lfLinks[i - 1];
4576  DriveProcessItem& nextItem = lfLinks[i];
4577  const bool canLeaveJunction = item.myLink->getViaLane() == nullptr || nextItem.myLink == nullptr || nextItem.mySetRequest;
4578  const bool opened = (item.myLink != nullptr
4579  && (canLeaveJunction || (
4580  // indirect bicycle turn
4581  nextItem.myLink != nullptr && nextItem.myLink->isInternalJunctionLink() && nextItem.myLink->haveRed()))
4582  && (
4583  item.myLink->havePriority()
4584  || i == 1 // the upcoming link (item 0) is checked in executeMove anyway. No need to use outdata approachData here
4586  || item.myLink->opened(item.myArrivalTime, item.myArrivalSpeed,
4589  bool allowsContinuation = (item.myLink == nullptr || item.myLink->isCont() || opened) && !item.hadStoppedVehicle;
4590 #ifdef DEBUG_CHECKREWINDLINKLANES
4591  if (DEBUG_COND) std::cout
4592  << " link=" << (item.myLink == 0 ? "NULL" : item.myLink->getViaLaneOrLane()->getID())
4593  << " canLeave=" << canLeaveJunction
4594  << " opened=" << opened
4595  << " allowsContinuation=" << allowsContinuation
4596  << " foundStopped=" << foundStopped
4597  << "\n";
4598 #endif
4599  if (!opened && item.myLink != nullptr) {
4600  foundStopped = true;
4601  if (i > 1) {
4602  DriveProcessItem& item2 = lfLinks[i - 2];
4603  if (item2.myLink != nullptr && item2.myLink->isCont()) {
4604  allowsContinuation = true;
4605  }
4606  }
4607  }
4608  if (allowsContinuation) {
4609  item.availableSpace = nextItem.availableSpace;
4610 #ifdef DEBUG_CHECKREWINDLINKLANES
4611  if (DEBUG_COND) std::cout
4612  << " link=" << (item.myLink == nullptr ? "NULL" : item.myLink->getViaLaneOrLane()->getID())
4613  << " copy nextAvail=" << nextItem.availableSpace
4614  << "\n";
4615 #endif
4616  }
4617  }
4618 
4619  // find removalBegin
4620  int removalBegin = -1;
4621  for (int i = 0; foundStopped && i < (int)lfLinks.size() && removalBegin < 0; ++i) {
4622  // skip unset links
4623  const DriveProcessItem& item = lfLinks[i];
4624  if (item.myLink == nullptr) {
4625  continue;
4626  }
4627  /*
4628  double impatienceCorrection = MAX2(0., double(double(myWaitingTime)));
4629  if (seenSpace<getVehicleType().getLengthWithGap()-impatienceCorrection/10.&&nextSeenNonInternal!=0) {
4630  removalBegin = lastLinkToInternal;
4631  }
4632  */
4633 
4634  const double leftSpace = item.availableSpace - getVehicleType().getLengthWithGap();
4635 #ifdef DEBUG_CHECKREWINDLINKLANES
4636  if (DEBUG_COND) std::cout
4637  << SIMTIME
4638  << " veh=" << getID()
4639  << " link=" << (item.myLink == 0 ? "NULL" : item.myLink->getViaLaneOrLane()->getID())
4640  << " avail=" << item.availableSpace
4641  << " leftSpace=" << leftSpace
4642  << "\n";
4643 #endif
4644  if (leftSpace < 0/* && item.myLink->willHaveBlockedFoe()*/) {
4645  double impatienceCorrection = 0;
4646  /*
4647  if(item.myLink->getState()==LINKSTATE_MINOR) {
4648  impatienceCorrection = MAX2(0., STEPS2TIME(myWaitingTime));
4649  }
4650  */
4651  // may ignore keepClear rules
4652  if (leftSpace < -impatienceCorrection / 10. && keepClear(item.myLink)) {
4653  removalBegin = i;
4654  }
4655  //removalBegin = i;
4656  }
4657  }
4658  // abort requests
4659  if (removalBegin != -1 && !(removalBegin == 0 && myLane->getEdge().isInternal())) {
4660  const double brakeGap = getCarFollowModel().brakeGap(myState.mySpeed, getCarFollowModel().getMaxDecel(), 0.);
4661  while (removalBegin < (int)(lfLinks.size())) {
4662  DriveProcessItem& dpi = lfLinks[removalBegin];
4663  if (dpi.myLink == nullptr) {
4664  break;
4665  }
4666  dpi.myVLinkPass = dpi.myVLinkWait;
4667 #ifdef DEBUG_CHECKREWINDLINKLANES
4668  if (DEBUG_COND) {
4669  std::cout << " removalBegin=" << removalBegin << " brakeGap=" << brakeGap << " dist=" << dpi.myDistance << " speed=" << myState.mySpeed << " a2s=" << ACCEL2SPEED(getCarFollowModel().getMaxDecel()) << "\n";
4670  }
4671 #endif
4672  if (dpi.myDistance >= brakeGap + POSITION_EPS) {
4673  // always leave junctions after requesting to enter
4674  if (!dpi.myLink->isExitLink() || !lfLinks[removalBegin - 1].mySetRequest) {
4675  dpi.mySetRequest = false;
4676  }
4677  }
4678  ++removalBegin;
4679  }
4680  }
4681  }
4682 }
4683 
4684 
4685 void
4687  if (!checkActionStep(t)) {
4688  return;
4689  }
4691  for (DriveProcessItem& dpi : myLFLinkLanes) {
4692  if (dpi.myLink != nullptr) {
4693  if (dpi.myLink->getState() == LINKSTATE_ALLWAY_STOP) {
4694  dpi.myArrivalTime += (SUMOTime)RandHelper::rand((int)2, getRNG()); // tie braker
4695  }
4696  dpi.myLink->setApproaching(this, dpi.myArrivalTime, dpi.myArrivalSpeed, dpi.getLeaveSpeed(),
4697  dpi.mySetRequest, dpi.myArrivalTimeBraking, dpi.myArrivalSpeedBraking, getWaitingTime(), dpi.myDistance, getLateralPositionOnLane());
4698  }
4699  }
4700  if (myLaneChangeModel->getShadowLane() != nullptr) {
4701  // register on all shadow links
4702  for (const DriveProcessItem& dpi : myLFLinkLanes) {
4703  if (dpi.myLink != nullptr) {
4704  MSLink* parallelLink = dpi.myLink->getParallelLink(myLaneChangeModel->getShadowDirection());
4705  if (parallelLink == nullptr && getLaneChangeModel().isOpposite() && dpi.myLink->isEntryLink()) {
4706  // register on opposite direction entry link to warn foes at minor side road
4707  parallelLink = dpi.myLink->getOppositeDirectionLink();
4708  }
4709  if (parallelLink != nullptr) {
4710  const double latOffset = getLane()->getRightSideOnEdge() - myLaneChangeModel->getShadowLane()->getRightSideOnEdge();
4711  parallelLink->setApproaching(this, dpi.myArrivalTime, dpi.myArrivalSpeed, dpi.getLeaveSpeed(),
4712  dpi.mySetRequest, dpi.myArrivalTimeBraking, dpi.myArrivalSpeedBraking, getWaitingTime(), dpi.myDistance,
4713  latOffset);
4715  }
4716  }
4717  }
4718  }
4719 #ifdef DEBUG_PLAN_MOVE
4720  if (DEBUG_COND) {
4721  std::cout << SIMTIME
4722  << " veh=" << getID()
4723  << " after checkRewindLinkLanes\n";
4724  for (DriveProcessItem& dpi : myLFLinkLanes) {
4725  std::cout
4726  << " vPass=" << dpi.myVLinkPass
4727  << " vWait=" << dpi.myVLinkWait
4728  << " linkLane=" << (dpi.myLink == 0 ? "NULL" : dpi.myLink->getViaLaneOrLane()->getID())
4729  << " request=" << dpi.mySetRequest
4730  << " atime=" << dpi.myArrivalTime
4731  << " atimeB=" << dpi.myArrivalTimeBraking
4732  << "\n";
4733  }
4734  }
4735 #endif
4736 }
4737 
4738 void
4740  for (MoveReminderCont::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end();) {
4741  // skip the reminder if it is a lane reminder but not for my lane (indicated by rem->second > 0.)
4742  if (rem->first->getLane() != nullptr && rem->second > 0.) {
4743 #ifdef _DEBUG
4744  if (myTraceMoveReminders) {
4745  traceMoveReminder("notifyEnter_skipped", rem->first, rem->second, true);
4746  }
4747 #endif
4748  ++rem;
4749  } else {
4750  if (rem->first->notifyEnter(*this, reason, enteredLane)) {
4751 #ifdef _DEBUG
4752  if (myTraceMoveReminders) {
4753  traceMoveReminder("notifyEnter", rem->first, rem->second, true);
4754  }
4755 #endif
4756  ++rem;
4757  } else {
4758 #ifdef _DEBUG
4759  if (myTraceMoveReminders) {
4760  traceMoveReminder("notifyEnter", rem->first, rem->second, false);
4761  }
4762 // std::cout << SIMTIME << " Vehicle '" << getID() << "' erases MoveReminder (with offset " << rem->second << ")" << std::endl;
4763 #endif
4764  rem = myMoveReminders.erase(rem);
4765  }
4766  }
4767  }
4768 }
4769 
4770 
4771 void
4772 MSVehicle::enterLaneAtMove(MSLane* enteredLane, bool onTeleporting) {
4773  myAmOnNet = !onTeleporting;
4774  // vaporizing edge?
4775  /*
4776  if (enteredLane->getEdge().isVaporizing()) {
4777  // yep, let's do the vaporization...
4778  myLane = enteredLane;
4779  return true;
4780  }
4781  */
4782  // Adjust MoveReminder offset to the next lane
4783  adaptLaneEntering2MoveReminder(*enteredLane);
4784  // set the entered lane as the current lane
4785  MSLane* oldLane = myLane;
4786  myLane = enteredLane;
4787  myLastBestLanesEdge = nullptr;
4788 
4789  // internal edges are not a part of the route...
4790  if (!enteredLane->getEdge().isInternal()) {
4791  ++myCurrEdge;
4793  }
4794  if (myInfluencer != nullptr) {
4796  }
4797  if (!onTeleporting) {
4800  // transform lateral position when the lane width changes
4801  assert(oldLane != nullptr);
4802  const MSLink* const link = oldLane->getLinkTo(myLane);
4803  if (link != nullptr) {
4805  myState.myPosLat += link->getLateralShift();
4806  }
4807  }
4808 
4809  } else {
4810  // normal move() isn't called so reset position here. must be done
4811  // before calling reminders
4812  myState.myPos = 0;
4815  }
4816  // update via
4817  if (myParameter->via.size() > 0 && myLane->getEdge().getID() == myParameter->via.front()) {
4818  myParameter->via.erase(myParameter->via.begin());
4819  }
4820 }
4821 
4822 
4823 void
4825  myAmOnNet = true;
4826  myLane = enteredLane;
4828  // need to update myCurrentLaneInBestLanes
4829  updateBestLanes();
4830  // switch to and activate the new lane's reminders
4831  // keep OldLaneReminders
4832  for (std::vector< MSMoveReminder* >::const_iterator rem = enteredLane->getMoveReminders().begin(); rem != enteredLane->getMoveReminders().end(); ++rem) {
4833  addReminder(*rem);
4834  }
4836  MSLane* lane = myLane;
4837  double leftLength = getVehicleType().getLength() - myState.myPos;
4838  for (int i = 0; i < (int)myFurtherLanes.size(); i++) {
4839  if (lane != nullptr) {
4840  lane = lane->getLogicalPredecessorLane(myFurtherLanes[i]->getEdge());
4841  }
4842  if (lane != nullptr) {
4843 #ifdef DEBUG_SETFURTHER
4844  if (DEBUG_COND) {
4845  std::cout << SIMTIME << " enterLaneAtLaneChange \n";
4846  }
4847 #endif
4848  myFurtherLanes[i]->resetPartialOccupation(this);
4849  myFurtherLanes[i] = lane;
4851 #ifdef DEBUG_SETFURTHER
4852  if (DEBUG_COND) {
4853  std::cout << SIMTIME << " enterLaneAtLaneChange \n";
4854  }
4855 #endif
4856  leftLength -= (lane)->setPartialOccupation(this);
4857  myState.myBackPos = -leftLength;
4858  } else {
4859  // keep the old values, but ensure there is no shadow
4862  }
4863  }
4864  }
4865 #ifdef DEBUG_SETFURTHER
4866  if (DEBUG_COND) {
4867  std::cout << SIMTIME << " enterLaneAtLaneChange new furtherLanes=" << toString(myFurtherLanes)
4868  << " furterLanesPosLat=" << toString(myFurtherLanesPosLat) << "\n";
4869  }
4870 #endif
4871  myAngle = computeAngle();
4872 }
4873 
4874 
4875 void
4876 MSVehicle::computeFurtherLanes(MSLane* enteredLane, double pos, bool collision) {
4877  // build the list of lanes the vehicle is lapping into
4878  if (!myLaneChangeModel->isOpposite()) {
4879  double leftLength = myType->getLength() - pos;
4880  MSLane* clane = enteredLane;
4881  int routeIndex = getRoutePosition();
4882  while (leftLength > 0) {
4883  if (routeIndex > 0 && clane->getEdge().isNormal()) {
4884  // get predecessor lane that corresponds to prior route
4885  routeIndex--;
4886  const MSEdge* fromRouteEdge = myRoute->getEdges()[routeIndex];
4887  MSLane* target = clane;
4888  clane = nullptr;
4889  for (auto ili : target->getIncomingLanes()) {
4890  if (ili.lane->getEdge().getNormalBefore() == fromRouteEdge) {
4891  clane = ili.lane;
4892  break;
4893  }
4894  }
4895  } else {
4896  clane = clane->getLogicalPredecessorLane();
4897  }
4898  if (clane == nullptr || clane == myLane || clane == myLane->getBidiLane()
4899  || (clane->isInternal() && (
4900  clane->getLinkCont()[0]->getDirection() == LinkDirection::TURN
4901  || clane->getLinkCont()[0]->getDirection() == LinkDirection::TURN_LEFTHAND))) {
4902  break;
4903  }
4904  if (!collision || std::find(myFurtherLanes.begin(), myFurtherLanes.end(), clane) == myFurtherLanes.end()) {
4905  myFurtherLanes.push_back(clane);
4907  clane->setPartialOccupation(this);
4908  }
4909  leftLength -= clane->getLength();
4910  }
4911  myState.myBackPos = -leftLength;
4912  } else {
4913  // clear partial occupation
4914  for (std::vector<MSLane*>::iterator i = myFurtherLanes.begin(); i != myFurtherLanes.end(); ++i) {
4915 #ifdef DEBUG_FURTHER
4916  if (DEBUG_COND) {
4917  std::cout << SIMTIME << " enterLaneAtInsertion \n";
4918  }
4919 #endif
4920  (*i)->resetPartialOccupation(this);
4921  }
4922  myFurtherLanes.clear();
4923  myFurtherLanesPosLat.clear();
4924  }
4925 }
4926 
4927 
4928 void
4929 MSVehicle::enterLaneAtInsertion(MSLane* enteredLane, double pos, double speed, double posLat, MSMoveReminder::Notification notification) {
4930  myState = State(pos, speed, posLat, pos - getVehicleType().getLength());
4931  if (myDeparture == NOT_YET_DEPARTED) {
4932  onDepart();
4933  }
4935  assert(myState.myPos >= 0);
4936  assert(myState.mySpeed >= 0);
4937  myLane = enteredLane;
4938  myAmOnNet = true;
4939  // schedule action for the next timestep
4941  if (notification != MSMoveReminder::NOTIFICATION_TELEPORT) {
4942  // set and activate the new lane's reminders, teleports already did that at enterLaneAtMove
4943  for (std::vector< MSMoveReminder* >::const_iterator rem = enteredLane->getMoveReminders().begin(); rem != enteredLane->getMoveReminders().end(); ++rem) {
4944  addReminder(*rem);
4945  }
4946  activateReminders(notification, enteredLane);
4947  }
4948  computeFurtherLanes(enteredLane, pos);
4952  } else if (MSGlobals::gLaneChangeDuration > 0) {
4954  }
4955  if (notification != MSMoveReminder::NOTIFICATION_LOAD_STATE) {
4956  myAngle = computeAngle();
4957  if (myLaneChangeModel->isOpposite()) {
4958  myAngle += M_PI;
4959  }
4960  }
4961 }
4962 
4963 
4964 void
4965 MSVehicle::leaveLane(const MSMoveReminder::Notification reason, const MSLane* approachedLane) {
4966  for (MoveReminderCont::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end();) {
4967  if (rem->first->notifyLeave(*this, myState.myPos + rem->second, reason, approachedLane)) {
4968 #ifdef _DEBUG
4969  if (myTraceMoveReminders) {
4970  traceMoveReminder("notifyLeave", rem->first, rem->second, true);
4971  }
4972 #endif
4973  ++rem;
4974  } else {
4975 #ifdef _DEBUG
4976  if (myTraceMoveReminders) {
4977  traceMoveReminder("notifyLeave", rem->first, rem->second, false);
4978  }
4979 #endif
4980  rem = myMoveReminders.erase(rem);
4981  }
4982  }
4983  if ((reason == MSMoveReminder::NOTIFICATION_JUNCTION || reason == MSMoveReminder::NOTIFICATION_TELEPORT) && myLane != nullptr) {
4984  myOdometer += getLane()->getLength();
4985  }
4987  // @note. In case of lane change, myFurtherLanes and partial occupation
4988  // are handled in enterLaneAtLaneChange()
4989  for (std::vector<MSLane*>::iterator i = myFurtherLanes.begin(); i != myFurtherLanes.end(); ++i) {
4990 #ifdef DEBUG_FURTHER
4991  if (DEBUG_COND) {
4992  std::cout << SIMTIME << " leaveLane \n";
4993  }
4994 #endif
4995  (*i)->resetPartialOccupation(this);
4996  }
4997  myFurtherLanes.clear();
4998  myFurtherLanesPosLat.clear();
4999  }
5000  if (reason >= MSMoveReminder::NOTIFICATION_TELEPORT) {
5001  myAmOnNet = false;
5002  myWaitingTime = 0;
5003  }
5005  myStopDist = std::numeric_limits<double>::max();
5006  if (myPastStops.back().speed <= 0) {
5007  WRITE_WARNING("Vehicle '" + getID() + "' aborts stop.");
5008  }
5009  }
5011  while (!myStops.empty() && myStops.front().edge == myCurrEdge && &myStops.front().lane->getEdge() == &myLane->getEdge()) {
5012  if (myStops.front().pars.speed <= 0) {
5013  WRITE_WARNING("Vehicle '" + getID() + "' skips stop on lane '" + myStops.front().lane->getID()
5014  + "' time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".")
5015  myStops.pop_front();
5016  } else {
5017  MSStop& stop = myStops.front();
5018  // passed waypoint at the end of the lane
5019  if (!stop.reached) {
5020  if (MSStopOut::active()) {
5022  }
5023  stop.reached = true;
5024  // enter stopping place so leaveFrom works as expected
5025  if (stop.busstop != nullptr) {
5026  // let the bus stop know the vehicle
5027  stop.busstop->enter(this, stop.pars.parking);
5028  }
5029  if (stop.containerstop != nullptr) {
5030  // let the container stop know the vehicle
5031  stop.containerstop->enter(this, stop.pars.parking);
5032  }
5033  if (stop.parkingarea != nullptr) {
5034  // let the parking area know the vehicle
5035  stop.parkingarea->enter(this);
5036  }
5037  if (stop.chargingStation != nullptr) {
5038  // let the container stop know the vehicle
5039  stop.chargingStation->enter(this, stop.pars.parking);
5040  }
5041  }
5043  }
5044  myStopDist = std::numeric_limits<double>::max();
5045  }
5046  }
5047 }
5048 
5049 
5052  return *myLaneChangeModel;
5053 }
5054 
5055 
5058  return *myLaneChangeModel;
5059 }
5060 
5061 
5062 const std::vector<MSVehicle::LaneQ>&
5064  return *myBestLanes.begin();
5065 }
5066 
5067 
5068 void
5069 MSVehicle::updateBestLanes(bool forceRebuild, const MSLane* startLane) {
5070 #ifdef DEBUG_BESTLANES
5071  if (DEBUG_COND) {
5072  std::cout << SIMTIME << " updateBestLanes veh=" << getID() << " force=" << forceRebuild << " startLane1=" << Named::getIDSecure(startLane) << " myLane=" << Named::getIDSecure(myLane) << "\n";
5073  }
5074 #endif
5075  if (startLane == nullptr) {
5076  startLane = myLane;
5077  }
5078  assert(startLane != 0);
5079  if (myLaneChangeModel->isOpposite()) {
5080  // depending on the calling context, startLane might be the forward lane
5081  // or the reverse-direction lane. In the latter case we need to
5082  // transform it to the forward lane.
5083  bool startLaneIsOpposite = (startLane->isInternal()
5084  ? & (startLane->getLinkCont()[0]->getLane()->getEdge()) != *(myCurrEdge + 1)
5085  : &startLane->getEdge() != *myCurrEdge);
5086  if (startLaneIsOpposite) {
5087  // use leftmost lane of forward edge
5088  startLane = startLane->getEdge().getOppositeEdge()->getLanes().back();
5089  assert(startLane != 0);
5090  }
5091  }
5092  if (forceRebuild) {
5093  myLastBestLanesEdge = nullptr;
5094  myLastBestLanesInternalLane = nullptr;
5095  }
5096  if (myBestLanes.size() > 0 && !forceRebuild && myLastBestLanesEdge == &startLane->getEdge()) {
5098 #ifdef DEBUG_BESTLANES
5099  if (DEBUG_COND) {
5100  std::cout << " only updateOccupancyAndCurrentBestLane\n";
5101  }
5102 #endif
5103  return;
5104  }
5105  if (startLane->getEdge().isInternal()) {
5106  if (myBestLanes.size() == 0 || forceRebuild) {
5107  // rebuilt from previous non-internal lane (may backtrack twice if behind an internal junction)
5108  updateBestLanes(true, startLane->getLogicalPredecessorLane());
5109  }
5110  if (myLastBestLanesInternalLane == startLane && !forceRebuild) {
5111 #ifdef DEBUG_BESTLANES
5112  if (DEBUG_COND) {
5113  std::cout << " nothing to do on internal\n";
5114  }
5115 #endif
5116  return;
5117  }
5118  // adapt best lanes to fit the current internal edge:
5119  // keep the entries that are reachable from this edge
5120  const MSEdge* nextEdge = startLane->getNextNormal();
5121  assert(!nextEdge->isInternal());
5122  for (std::vector<std::vector<LaneQ> >::iterator it = myBestLanes.begin(); it != myBestLanes.end();) {
5123  std::vector<LaneQ>& lanes = *it;
5124  assert(lanes.size() > 0);
5125  if (&(lanes[0].lane->getEdge()) == nextEdge) {
5126  // keep those lanes which are successors of internal lanes from the edge of startLane
5127  std::vector<LaneQ> oldLanes = lanes;
5128  lanes.clear();
5129  const std::vector<MSLane*>& sourceLanes = startLane->getEdge().getLanes();
5130  for (std::vector<MSLane*>::const_iterator it_source = sourceLanes.begin(); it_source != sourceLanes.end(); ++it_source) {
5131  for (std::vector<LaneQ>::iterator it_lane = oldLanes.begin(); it_lane != oldLanes.end(); ++it_lane) {
5132  if ((*it_source)->getLinkCont()[0]->getLane() == (*it_lane).lane) {
5133  lanes.push_back(*it_lane);
5134  break;
5135  }
5136  }
5137  }
5138  assert(lanes.size() == startLane->getEdge().getLanes().size());
5139  // patch invalid bestLaneOffset and updated myCurrentLaneInBestLanes
5140  for (int i = 0; i < (int)lanes.size(); ++i) {
5141  if (i + lanes[i].bestLaneOffset < 0) {
5142  lanes[i].bestLaneOffset = -i;
5143  }
5144  if (i + lanes[i].bestLaneOffset >= (int)lanes.size()) {
5145  lanes[i].bestLaneOffset = (int)lanes.size() - i - 1;
5146  }
5147  assert(i + lanes[i].bestLaneOffset >= 0);
5148  assert(i + lanes[i].bestLaneOffset < (int)lanes.size());
5149  if (lanes[i].bestContinuations[0] != 0) {
5150  // patch length of bestContinuation to match expectations (only once)
5151  lanes[i].bestContinuations.insert(lanes[i].bestContinuations.begin(), (MSLane*)nullptr);
5152  }
5153  if (startLane->getLinkCont()[0]->getLane() == lanes[i].lane) {
5154  myCurrentLaneInBestLanes = lanes.begin() + i;
5155  }
5156  assert(&(lanes[i].lane->getEdge()) == nextEdge);
5157  }
5158  myLastBestLanesInternalLane = startLane;
5160 #ifdef DEBUG_BESTLANES
5161  if (DEBUG_COND) {
5162  std::cout << " updated for internal\n";
5163  }
5164 #endif
5165  return;
5166  } else {
5167  // remove passed edges
5168  it = myBestLanes.erase(it);
5169  }
5170  }
5171  assert(false); // should always find the next edge
5172  }
5173  // start rebuilding
5174  myLastBestLanesEdge = &startLane->getEdge();
5175  myBestLanes.clear();
5176 
5177  // get information about the next stop
5178  MSRouteIterator nextStopEdge = myRoute->end();
5179  const MSLane* nextStopLane = nullptr;
5180  double nextStopPos = 0;
5181  bool nextStopIsWaypoint = false;
5182  if (!myStops.empty()) {
5183  const MSStop& nextStop = myStops.front();
5184  nextStopLane = nextStop.lane;
5185  if (nextStop.isOpposite) {
5186  // target leftmost lane in forward direction
5187  nextStopLane = nextStopLane->getEdge().getOppositeEdge()->getLanes().back();
5188  }
5189  nextStopEdge = nextStop.edge;
5190  nextStopPos = nextStop.pars.startPos;
5191  nextStopIsWaypoint = nextStop.pars.speed > 0;
5192  }
5194  nextStopEdge = (myRoute->end() - 1);
5195  nextStopLane = (*nextStopEdge)->getLanes()[myArrivalLane];
5196  nextStopPos = myArrivalPos;
5197  }
5198  if (nextStopEdge != myRoute->end()) {
5199  // make sure that the "wrong" lanes get a penalty. (penalty needs to be
5200  // large enough to overcome a magic threshold in MSLaneChangeModel::DK2004.cpp:383)
5201  nextStopPos = MAX2(POSITION_EPS, MIN2((double)nextStopPos, (double)(nextStopLane->getLength() - 2 * POSITION_EPS)));
5202  if (nextStopLane->isInternal()) {
5203  // switch to the correct lane before entering the intersection
5204  nextStopPos = (*nextStopEdge)->getLength();
5205  }
5206  }
5207 
5208  // go forward along the next lanes;
5209  // trains do not have to deal with lane-changing for stops but their best
5210  // lanes lookahead is needed for rail signal control
5211  const bool continueAfterStop = nextStopIsWaypoint || isRailway(getVClass());
5212  int seen = 0;
5213  double seenLength = 0;
5214  bool progress = true;
5215  // bestLanes must cover the braking distance even when at the very end of the current lane to avoid unecessary slow down
5216  const double maxBrakeDist = startLane->getLength() + getCarFollowModel().getHeadwayTime() * getMaxSpeed() + getCarFollowModel().brakeGap(getMaxSpeed()) + getVehicleType().getMinGap();
5217  for (MSRouteIterator ce = myCurrEdge; progress;) {
5218  std::vector<LaneQ> currentLanes;
5219  const std::vector<MSLane*>* allowed = nullptr;
5220  const MSEdge* nextEdge = nullptr;
5221  if (ce != myRoute->end() && ce + 1 != myRoute->end()) {
5222  nextEdge = *(ce + 1);
5223  allowed = (*ce)->allowedLanes(*nextEdge, myType->getVehicleClass());
5224  }
5225  const std::vector<MSLane*>& lanes = (*ce)->getLanes();
5226  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
5227  LaneQ q;
5228  MSLane* cl = *i;
5229  q.lane = cl;
5230  q.bestContinuations.push_back(cl);
5231  q.bestLaneOffset = 0;
5232  q.length = cl->allowsVehicleClass(myType->getVehicleClass()) ? cl->getLength() : 0;
5233  q.currentLength = q.length;
5234  q.allowsContinuation = allowed == nullptr || std::find(allowed->begin(), allowed->end(), cl) != allowed->end();
5235  q.occupation = 0;
5236  q.nextOccupation = 0;
5237  currentLanes.push_back(q);
5238  }
5239  //
5240  if (nextStopEdge == ce
5241  // already past the stop edge
5242  && !(ce == myCurrEdge && myLane != nullptr && myLane->isInternal())) {
5243  if (!nextStopLane->isInternal() && !continueAfterStop) {
5244  progress = false;
5245  }
5246  const MSLane* normalStopLane = nextStopLane->getNormalPredecessorLane();
5247  for (std::vector<LaneQ>::iterator q = currentLanes.begin(); q != currentLanes.end(); ++q) {
5248  if (nextStopLane != nullptr && normalStopLane != (*q).lane) {
5249  (*q).allowsContinuation = false;
5250  (*q).length = nextStopPos;
5251  (*q).currentLength = (*q).length;
5252  }
5253  }
5254  }
5255 
5256  myBestLanes.push_back(currentLanes);
5257  ++seen;
5258  seenLength += currentLanes[0].lane->getLength();
5259  ++ce;
5260  progress &= (seen <= 4 || seenLength < MAX2(maxBrakeDist, 3000.0)); // motorway
5261  progress &= (seen <= 8 || seenLength < MAX2(maxBrakeDist, 200.0) || isRailway(getVClass())); // urban
5262  progress &= ce != myRoute->end();
5263  /*
5264  if(progress) {
5265  progress &= (currentLanes.size()!=1||(*ce)->getLanes().size()!=1);
5266  }
5267  */
5268  }
5269 
5270  // we are examining the last lane explicitly
5271  if (myBestLanes.size() != 0) {
5272  double bestLength = -1;
5273  int bestThisIndex = 0;
5274  int index = 0;
5275  std::vector<LaneQ>& last = myBestLanes.back();
5276  for (std::vector<LaneQ>::iterator j = last.begin(); j != last.end(); ++j, ++index) {
5277  if ((*j).length > bestLength) {
5278  bestLength = (*j).length;
5279  bestThisIndex = index;
5280  }
5281  }
5282  index = 0;
5283  bool requiredChangeRightForbidden = false;
5284  int requireChangeToLeftForbidden = -1;
5285  for (std::vector<LaneQ>::iterator j = last.begin(); j != last.end(); ++j, ++index) {
5286  if ((*j).length < bestLength) {
5287  (*j).bestLaneOffset = bestThisIndex - index;
5288 
5289  if ((*j).bestLaneOffset < 0 && (!(*j).lane->allowsChangingRight(getVClass()) || requiredChangeRightForbidden)) {
5290  // this lane and all further lanes to the left cannot be used
5291  requiredChangeRightForbidden = true;
5292  (*j).length -= (*j).currentLength;
5293  } else if ((*j).bestLaneOffset > 0 && !(*j).lane->allowsChangingLeft(getVClass())) {
5294  // this lane and all previous lanes to the right cannot be used
5295  requireChangeToLeftForbidden = (*j).lane->getIndex();
5296  }
5297  }
5298  }
5299  for (int i = requireChangeToLeftForbidden; i >= 0; i--) {
5300  last[i].length -= last[i].currentLength;
5301  }
5302  }
5303 #ifdef DEBUG_BESTLANES
5304  if (DEBUG_COND) {
5305  std::cout << " last edge:\n";
5306  std::vector<LaneQ>& laneQs = myBestLanes.back();
5307  for (std::vector<LaneQ>::iterator j = laneQs.begin(); j != laneQs.end(); ++j) {
5308  std::cout << " lane=" << (*j).lane->getID() << " length=" << (*j).length << " bestOffset=" << (*j).bestLaneOffset << "\n";
5309  }
5310  }
5311 #endif
5312  // go backward through the lanes
5313  // track back best lane and compute the best prior lane(s)
5314  for (std::vector<std::vector<LaneQ> >::reverse_iterator i = myBestLanes.rbegin() + 1; i != myBestLanes.rend(); ++i) {
5315  std::vector<LaneQ>& nextLanes = (*(i - 1));
5316  std::vector<LaneQ>& clanes = (*i);
5317  MSEdge& cE = clanes[0].lane->getEdge();
5318  int index = 0;
5319  double bestConnectedLength = -1;
5320  double bestLength = -1;
5321  for (std::vector<LaneQ>::iterator j = nextLanes.begin(); j != nextLanes.end(); ++j, ++index) {
5322  if ((*j).lane->isApproachedFrom(&cE) && bestConnectedLength < (*j).length) {
5323  bestConnectedLength = (*j).length;
5324  }
5325  if (bestLength < (*j).length) {
5326  bestLength = (*j).length;
5327  }
5328  }
5329  // compute index of the best lane (highest length and least offset from the best next lane)
5330  int bestThisIndex = 0;
5331  if (bestConnectedLength > 0) {
5332  index = 0;
5333  for (std::vector<LaneQ>::iterator j = clanes.begin(); j != clanes.end(); ++j, ++index) {
5334  LaneQ bestConnectedNext;
5335  bestConnectedNext.length = -1;
5336  if ((*j).allowsContinuation) {
5337  for (std::vector<LaneQ>::const_iterator m = nextLanes.begin(); m != nextLanes.end(); ++m) {
5338  if (((*m).lane->allowsVehicleClass(getVClass()) || (*m).lane->hadPermissionChanges())
5339  && (*m).lane->isApproachedFrom(&cE, (*j).lane)) {
5340  if (bestConnectedNext.length < (*m).length || (bestConnectedNext.length == (*m).length && abs(bestConnectedNext.bestLaneOffset) > abs((*m).bestLaneOffset))) {
5341  bestConnectedNext = *m;
5342  }
5343  }
5344  }
5345  if (bestConnectedNext.length == bestConnectedLength && abs(bestConnectedNext.bestLaneOffset) < 2) {
5346  (*j).length += bestLength;
5347  } else {
5348  (*j).length += bestConnectedNext.length;
5349  }
5350  (*j).bestLaneOffset = bestConnectedNext.bestLaneOffset;
5351  }
5352  copy(bestConnectedNext.bestContinuations.begin(), bestConnectedNext.bestContinuations.end(), back_inserter((*j).bestContinuations));
5353  if (clanes[bestThisIndex].length < (*j).length
5354  || (clanes[bestThisIndex].length == (*j).length && abs(clanes[bestThisIndex].bestLaneOffset) > abs((*j).bestLaneOffset))
5355  || (clanes[bestThisIndex].length == (*j).length && abs(clanes[bestThisIndex].bestLaneOffset) == abs((*j).bestLaneOffset) &&
5356  nextLinkPriority(clanes[bestThisIndex].bestContinuations) < nextLinkPriority((*j).bestContinuations))
5357  ) {
5358  bestThisIndex = index;
5359  }
5360  }
5361 
5362  //vehicle with elecHybrid device prefers running under an overhead wire
5363  if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
5364  index = 0;
5365  for (std::vector<LaneQ>::iterator j = clanes.begin(); j != clanes.end(); ++j, ++index) {
5366  std::string overheadWireSegmentID = MSNet::getInstance()->getStoppingPlaceID((*j).lane, ((*j).currentLength) / 2, SUMO_TAG_OVERHEAD_WIRE_SEGMENT);
5367  if (overheadWireSegmentID != "") {
5368  bestThisIndex = index;
5369  }
5370  }
5371  }
5372 
5373  } else {
5374  // only needed in case of disconnected routes
5375  int bestNextIndex = 0;
5376  int bestDistToNeeded = (int) clanes.size();
5377  index = 0;
5378  for (std::vector<LaneQ>::iterator j = clanes.begin(); j != clanes.end(); ++j, ++index) {
5379  if ((*j).allowsContinuation) {
5380  int nextIndex = 0;
5381  for (std::vector<LaneQ>::const_iterator m = nextLanes.begin(); m != nextLanes.end(); ++m, ++nextIndex) {
5382  if ((*m).lane->isApproachedFrom(&cE, (*j).lane)) {
5383  if (bestDistToNeeded > abs((*m).bestLaneOffset)) {
5384  bestDistToNeeded = abs((*m).bestLaneOffset);
5385  bestThisIndex = index;
5386  bestNextIndex = nextIndex;
5387  }
5388  }
5389  }
5390  }
5391  }
5392  clanes[bestThisIndex].length += nextLanes[bestNextIndex].length;
5393  copy(nextLanes[bestNextIndex].bestContinuations.begin(), nextLanes[bestNextIndex].bestContinuations.end(), back_inserter(clanes[bestThisIndex].bestContinuations));
5394 
5395  }
5396  // set bestLaneOffset for all lanes
5397  index = 0;
5398  bool requiredChangeRightForbidden = false;
5399  int requireChangeToLeftForbidden = -1;
5400  for (std::vector<LaneQ>::iterator j = clanes.begin(); j != clanes.end(); ++j, ++index) {
5401  if ((*j).length < clanes[bestThisIndex].length
5402  || ((*j).length == clanes[bestThisIndex].length && abs((*j).bestLaneOffset) > abs(clanes[bestThisIndex].bestLaneOffset))
5403  || (nextLinkPriority((*j).bestContinuations)) < nextLinkPriority(clanes[bestThisIndex].bestContinuations)
5404  ) {
5405  (*j).bestLaneOffset = bestThisIndex - index;
5406  if ((nextLinkPriority((*j).bestContinuations)) < nextLinkPriority(clanes[bestThisIndex].bestContinuations)) {
5407  // try to move away from the lower-priority lane before it ends
5408  (*j).length = (*j).currentLength;
5409  }
5410  if ((*j).bestLaneOffset < 0 && (!(*j).lane->allowsChangingRight(getVClass()) || requiredChangeRightForbidden)) {
5411  // this lane and all further lanes to the left cannot be used
5412  requiredChangeRightForbidden = true;
5413  (*j).length -= (*j).currentLength;
5414  } else if ((*j).bestLaneOffset > 0 && !(*j).lane->allowsChangingLeft(getVClass())) {
5415  // this lane and all previous lanes to the right cannot be used
5416  requireChangeToLeftForbidden = (*j).lane->getIndex();
5417  }
5418  } else {
5419  (*j).bestLaneOffset = 0;
5420  }
5421  }
5422  for (int idx = requireChangeToLeftForbidden; idx >= 0; idx--) {
5423  clanes[idx].length -= clanes[idx].currentLength;
5424  }
5425 
5426  //vehicle with elecHybrid device prefers running under an overhead wire
5427  if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
5428  index = 0;
5429  std::string overheadWireID = MSNet::getInstance()->getStoppingPlaceID(clanes[bestThisIndex].lane, (clanes[bestThisIndex].currentLength) / 2, SUMO_TAG_OVERHEAD_WIRE_SEGMENT);
5430  if (overheadWireID != "") {
5431  for (std::vector<LaneQ>::iterator j = clanes.begin(); j != clanes.end(); ++j, ++index) {
5432  (*j).bestLaneOffset = bestThisIndex - index;
5433  }
5434  }
5435  }
5436 
5437 #ifdef DEBUG_BESTLANES
5438  if (DEBUG_COND) {
5439  std::cout << " edge=" << cE.getID() << "\n";
5440  std::vector<LaneQ>& laneQs = clanes;
5441  for (std::vector<LaneQ>::iterator j = laneQs.begin(); j != laneQs.end(); ++j) {
5442  std::cout << " lane=" << (*j).lane->getID() << " length=" << (*j).length << " bestOffset=" << (*j).bestLaneOffset << "\n";
5443  }
5444  }
5445 #endif
5446 
5447  }
5449 #ifdef DEBUG_BESTLANES
5450  if (DEBUG_COND) {
5451  std::cout << SIMTIME << " veh=" << getID() << " bestCont=" << toString(getBestLanesContinuation()) << "\n";
5452  }
5453 #endif
5454  return;
5455 }
5456 
5457 
5458 int
5459 MSVehicle::nextLinkPriority(const std::vector<MSLane*>& conts) {
5460  if (conts.size() < 2) {
5461  return -1;
5462  } else {
5463  const MSLink* const link = conts[0]->getLinkTo(conts[1]);
5464  if (link != nullptr) {
5465  return link->havePriority() ? 1 : 0;
5466  } else {
5467  // disconnected route
5468  return -1;
5469  }
5470  }
5471 }
5472 
5473 
5474 void
5476  std::vector<LaneQ>& currLanes = *myBestLanes.begin();
5477  std::vector<LaneQ>::iterator i;
5478  for (i = currLanes.begin(); i != currLanes.end(); ++i) {
5479  double nextOccupation = 0;
5480  for (std::vector<MSLane*>::const_iterator j = (*i).bestContinuations.begin() + 1; j != (*i).bestContinuations.end(); ++j) {
5481  nextOccupation += (*j)->getBruttoVehLenSum();
5482  }
5483  (*i).nextOccupation = nextOccupation;
5484 #ifdef DEBUG_BESTLANES
5485  if (DEBUG_COND) {
5486  std::cout << " lane=" << (*i).lane->getID() << " nextOccupation=" << nextOccupation << "\n";
5487  }
5488 #endif
5489  if ((*i).lane == startLane) {
5491  }
5492  }
5493 }
5494 
5495 
5496 const std::vector<MSLane*>&
5498  if (myBestLanes.empty() || myBestLanes[0].empty()) {
5499  return myEmptyLaneVector;
5500  }
5501  return (*myCurrentLaneInBestLanes).bestContinuations;
5502 }
5503 
5504 
5505 const std::vector<MSLane*>&
5507  const MSLane* lane = l;
5508  // XXX: shouldn't this be a "while" to cover more than one internal lane? (Leo) Refs. #2575
5509  if (lane->getEdge().isInternal()) {
5510  // internal edges are not kept inside the bestLanes structure
5511  lane = lane->getLinkCont()[0]->getLane();
5512  }
5513  if (myBestLanes.size() == 0) {
5514  return myEmptyLaneVector;
5515  }
5516  for (std::vector<LaneQ>::const_iterator i = myBestLanes[0].begin(); i != myBestLanes[0].end(); ++i) {
5517  if ((*i).lane == lane) {
5518  return (*i).bestContinuations;
5519  }
5520  }
5521  return myEmptyLaneVector;
5522 }
5523 
5524 const std::vector<const MSLane*>
5525 MSVehicle::getUpcomingLanesUntil(double distance) const {
5526  std::vector<const MSLane*> lanes;
5527 
5528  if (distance <= 0.) {
5529  // WRITE_WARNINGF("MSVehicle::getUpcomingLanesUntil(): distance ('%') should be greater than 0.", distance);
5530  return lanes;
5531  }
5532 
5533  if (!myLaneChangeModel->isOpposite()) {
5534  distance += getPositionOnLane();
5535  } else {
5536  distance += myLane->getOppositePos(getPositionOnLane());
5537  }
5539  while (lane->isInternal() && (distance > 0.)) { // include initial internal lanes
5540  lanes.insert(lanes.end(), lane);
5541  distance -= lane->getLength();
5542  lane = lane->getLinkCont().front()->getViaLaneOrLane();
5543  }
5544 
5545  const std::vector<MSLane*>& contLanes = getBestLanesContinuation();
5546  if (contLanes.empty()) {
5547  return lanes;
5548  }
5549  auto contLanesIt = contLanes.begin();
5550  MSRouteIterator routeIt = myCurrEdge; // keep track of covered edges in myRoute
5551  while (distance > 0.) {
5552  MSLane* l = nullptr;
5553  if (contLanesIt != contLanes.end()) {
5554  l = *contLanesIt;
5555  if (l != nullptr) {
5556  assert(l->getEdge().getID() == (*routeIt)->getLanes().front()->getEdge().getID());
5557  }
5558  ++contLanesIt;
5559  if (l != nullptr || myLane->isInternal()) {
5560  ++routeIt;
5561  }
5562  if (l == nullptr) {
5563  continue;
5564  }
5565  } else if (routeIt != myRoute->end()) { // bestLanes didn't get us far enough
5566  // choose left-most lane as default (avoid sidewalks, bike lanes etc)
5567  l = (*routeIt)->getLanes().back();
5568  ++routeIt;
5569  } else { // the search distance goes beyond our route
5570  break;
5571  }
5572 
5573  assert(l != nullptr);
5574 
5575  // insert internal lanes if applicable
5576  const MSLane* internalLane = lanes.size() > 0 ? lanes.back()->getInternalFollowingLane(l) : nullptr;
5577  while ((internalLane != nullptr) && internalLane->isInternal() && (distance > 0.)) {
5578  lanes.insert(lanes.end(), internalLane);
5579  distance -= internalLane->getLength();
5580  internalLane = internalLane->getLinkCont().front()->getViaLaneOrLane();
5581  }
5582  if (distance <= 0.) {
5583  break;
5584  }
5585 
5586  lanes.insert(lanes.end(), l);
5587  distance -= l->getLength();
5588  }
5589 
5590  return lanes;
5591 }
5592 
5593 const std::vector<const MSLane*>
5594 MSVehicle::getPastLanesUntil(double distance) const {
5595  std::vector<const MSLane*> lanes;
5596 
5597  if (distance <= 0.) {
5598  // WRITE_WARNINGF("MSVehicle::getPastLanesUntil(): distance ('%') should be greater than 0.", distance);
5599  return lanes;
5600  }
5601 
5602  MSRouteIterator routeIt = myCurrEdge;
5603  if (!myLaneChangeModel->isOpposite()) {
5604  distance += myLane->getLength() - getPositionOnLane();
5605  } else {
5607  }
5609  while (lane->isInternal() && (distance > 0.)) { // include initial internal lanes
5610  lanes.insert(lanes.end(), lane);
5611  distance -= lane->getLength();
5612  lane = lane->getLogicalPredecessorLane();
5613  }
5614 
5615  while (distance > 0.) {
5616  // choose left-most lane as default (avoid sidewalks, bike lanes etc)
5617  MSLane* l = (*routeIt)->getLanes().back();
5618 
5619  // insert internal lanes if applicable
5620  const MSEdge* internalEdge = lanes.size() > 0 ? (*routeIt)->getInternalFollowingEdge(&(lanes.back()->getEdge())) : nullptr;
5621  const MSLane* internalLane = internalEdge != nullptr ? internalEdge->getLanes().front() : nullptr;
5622  std::vector<const MSLane*> internalLanes;
5623  while ((internalLane != nullptr) && internalLane->isInternal()) { // collect all internal successor lanes
5624  internalLanes.insert(internalLanes.begin(), internalLane);
5625  internalLane = internalLane->getLinkCont().front()->getViaLaneOrLane();
5626  }
5627  for (auto it = internalLanes.begin(); (it != internalLanes.end()) && (distance > 0.); ++it) { // check remaining distance in correct order
5628  lanes.insert(lanes.end(), *it);
5629  distance -= (*it)->getLength();
5630  }
5631  if (distance <= 0.) {
5632  break;
5633  }
5634 
5635  lanes.insert(lanes.end(), l);
5636  distance -= l->getLength();
5637 
5638  // NOTE: we're going backwards with the (bi-directional) Iterator
5639  // TODO: consider make reverse_iterator() when moving on to C++14 or later
5640  if (routeIt != myRoute->begin()) {
5641  --routeIt;
5642  } else { // we went backwards to begin() and already processed the first and final element
5643  break;
5644  }
5645  }
5646 
5647  return lanes;
5648 }
5649 
5650 
5651 const std::vector<MSLane*>
5653  const std::vector<const MSLane*> routeLanes = getPastLanesUntil(myLane->getMaximumBrakeDist());
5654  std::vector<MSLane*> result;
5655  for (const MSLane* lane : routeLanes) {
5656  MSLane* opposite = lane->getOpposite();
5657  if (opposite != nullptr) {
5658  result.push_back(opposite);
5659  } else {
5660  break;
5661  }
5662  }
5663  return result;
5664 }
5665 
5666 
5667 int
5669  if (myBestLanes.empty() || myBestLanes[0].empty()) {
5670  return 0;
5671  } else {
5672  return (*myCurrentLaneInBestLanes).bestLaneOffset;
5673  }
5674 }
5675 
5676 
5677 void
5678 MSVehicle::adaptBestLanesOccupation(int laneIndex, double density) {
5679  std::vector<MSVehicle::LaneQ>& preb = myBestLanes.front();
5680  assert(laneIndex < (int)preb.size());
5681  preb[laneIndex].occupation = density + preb[laneIndex].nextOccupation;
5682 }
5683 
5684 
5685 void
5688  myState.myPosLat = 0;
5689  }
5690 }
5691 
5692 std::pair<const MSLane*, double>
5693 MSVehicle::getLanePosAfterDist(double distance) const {
5694  if (distance == 0) {
5695  return std::make_pair(myLane, getPositionOnLane());
5696  }
5697  const std::vector<const MSLane*> lanes = getUpcomingLanesUntil(distance);
5698  distance += getPositionOnLane();
5699  for (const MSLane* lane : lanes) {
5700  if (lane->getLength() > distance) {
5701  return std::make_pair(lane, distance);
5702  }
5703  distance -= lane->getLength();
5704  }
5705  return std::make_pair(nullptr, -1);
5706 }
5707 
5708 
5709 double
5710 MSVehicle::getDistanceToPosition(double destPos, const MSEdge* destEdge) const {
5711  double distance = std::numeric_limits<double>::max();
5712  if (isOnRoad() && destEdge != nullptr) {
5713  if (myLane->isInternal()) {
5714  // vehicle is on inner junction edge
5715  distance = myLane->getLength() - getPositionOnLane();
5716  distance += myRoute->getDistanceBetween(0, destPos, *(myCurrEdge + 1), destEdge);
5717  } else {
5718  // vehicle is on a normal edge
5719  distance = myRoute->getDistanceBetween(getPositionOnLane(), destPos, *myCurrEdge, destEdge);
5720  }
5721  }
5722  return distance;
5723 }
5724 
5725 
5726 std::pair<const MSVehicle* const, double>
5727 MSVehicle::getLeader(double dist) const {
5728  if (myLane == nullptr) {
5729  return std::make_pair(static_cast<const MSVehicle*>(nullptr), -1);
5730  }
5731  if (dist == 0) {
5733  }
5734  const MSVehicle* lead = nullptr;
5735  const MSLane* lane = myLane; // ensure lane does not change between getVehiclesSecure and releaseVehicles;
5736  const MSLane::VehCont& vehs = lane->getVehiclesSecure();
5737  // vehicle might be outside the road network
5738  MSLane::VehCont::const_iterator it = std::find(vehs.begin(), vehs.end(), this);
5739  if (it != vehs.end() && it + 1 != vehs.end()) {
5740  lead = *(it + 1);
5741  }
5742  if (lead != nullptr) {
5743  std::pair<const MSVehicle* const, double> result(
5744  lead, lead->getBackPositionOnLane(myLane) - getPositionOnLane() - getVehicleType().getMinGap());
5745  lane->releaseVehicles();
5746  return result;
5747  }
5748  const double seen = myLane->getLength() - getPositionOnLane();
5749  const std::vector<MSLane*>& bestLaneConts = getBestLanesContinuation(myLane);
5750  std::pair<const MSVehicle* const, double> result = myLane->getLeaderOnConsecutive(dist, seen, getSpeed(), *this, bestLaneConts);
5751  lane->releaseVehicles();
5752  return result;
5753 }
5754 
5755 
5756 std::pair<const MSVehicle* const, double>
5757 MSVehicle::getFollower(double dist) const {
5758  if (myLane == nullptr) {
5759  return std::make_pair(static_cast<const MSVehicle*>(nullptr), -1);
5760  }
5761  if (dist == 0) {
5762  dist = getCarFollowModel().brakeGap(myLane->getEdge().getSpeedLimit() * 2, 4.5, 0);
5763  }
5764  return myLane->getFollower(this, getPositionOnLane(), dist, true);
5765 }
5766 
5767 
5768 double
5770  // calling getLeader with 0 would induce a dist calculation but we only want to look for the leaders on the current lane
5771  std::pair<const MSVehicle* const, double> leaderInfo = getLeader(-1);
5772  if (leaderInfo.first == nullptr || getSpeed() == 0) {
5773  return -1;
5774  }
5775  return (leaderInfo.second + getVehicleType().getMinGap()) / getSpeed();
5776 }
5777 
5778 
5779 void
5781  MSBaseVehicle::addTransportable(transportable);
5782  if (myStops.size() > 0 && myStops.front().reached) {
5783  if (transportable->isPerson()) {
5784  if (myStops.front().triggered && myStops.front().numExpectedPerson > 0) {
5785  myStops.front().numExpectedPerson -= (int)myStops.front().pars.awaitedPersons.count(transportable->getID());
5786  }
5787  } else {
5788  if (myStops.front().pars.containerTriggered && myStops.front().numExpectedContainer > 0) {
5789  myStops.front().numExpectedContainer -= (int)myStops.front().pars.awaitedContainers.count(transportable->getID());
5790  }
5791  }
5792  }
5793 }
5794 
5795 
5796 void
5799  int state = myLaneChangeModel->getOwnState();
5800  // do not set blinker for sublane changes or when blocked from changing to the right
5801  const bool blinkerManoeuvre = (((state & LCA_SUBLANE) == 0) && (
5802  (state & LCA_KEEPRIGHT) == 0 || (state & LCA_BLOCKED) == 0));
5805  if (MSGlobals::gLefthand) {
5806  // lane indices increase from left to right
5807  std::swap(left, right);
5808  }
5809  if ((state & LCA_LEFT) != 0 && blinkerManoeuvre) {
5810  switchOnSignal(left);
5811  } else if ((state & LCA_RIGHT) != 0 && blinkerManoeuvre) {
5812  switchOnSignal(right);
5813  } else if (myLaneChangeModel->isChangingLanes()) {
5815  switchOnSignal(left);
5816  } else {
5817  switchOnSignal(right);
5818  }
5819  } else {
5820  const MSLane* lane = getLane();
5821  std::vector<MSLink*>::const_iterator link = MSLane::succLinkSec(*this, 1, *lane, getBestLanesContinuation());
5822  if (link != lane->getLinkCont().end() && lane->getLength() - getPositionOnLane() < lane->getVehicleMaxSpeed(this) * (double) 7.) {
5823  switch ((*link)->getDirection()) {
5824  case LinkDirection::TURN:
5825  case LinkDirection::LEFT:
5828  break;
5829  case LinkDirection::RIGHT:
5832  break;
5833  default:
5834  break;
5835  }
5836  }
5837  }
5838  // stopping related signals
5839  if (hasStops()
5840  && (myStops.begin()->reached ||
5842  && myStopDist < getCarFollowModel().brakeGap(myLane->getVehicleMaxSpeed(this), getCarFollowModel().getMaxDecel(), 3)))) {
5843  if (myStops.begin()->lane->getIndex() > 0 && myStops.begin()->lane->getParallelLane(-1)->allowsVehicleClass(getVClass())) {
5844  // not stopping on the right. Activate emergency blinkers
5846  } else if (!myStops.begin()->reached && myStops.begin()->pars.parking) {
5847  // signal upcoming parking stop on the current lane when within braking distance (~2 seconds before braking)
5849  }
5850  }
5851  if (myInfluencer != nullptr && myInfluencer->getSignals() >= 0) {
5853  myInfluencer->setSignals(-1); // overwrite computed signals only once
5854  }
5855 }
5856 
5857 void
5859 
5860  //TODO look if timestep ist SIMSTEP
5861  if (currentTime % 1000 == 0) {
5864  } else {
5866  }
5867  }
5868 }
5869 
5870 
5871 int
5873  return myLane == nullptr ? -1 : myLane->getIndex();
5874 }
5875 
5876 
5877 void
5878 MSVehicle::setTentativeLaneAndPosition(MSLane* lane, double pos, double posLat) {
5879  assert(lane != 0);
5880  myLane = lane;
5881  myState.myPos = pos;
5882  myState.myPosLat = posLat;
5884 }
5885 
5886 
5887 double
5889  return myState.myPosLat + 0.5 * myLane->getWidth() - 0.5 * getVehicleType().getWidth();
5890 }
5891 
5892 
5893 double
5895  return getCenterOnEdge(lane) - 0.5 * getVehicleType().getWidth();
5896 }
5897 
5898 
5899 double
5901  if (lane == nullptr || &lane->getEdge() == &myLane->getEdge()) {
5902  return myLane->getRightSideOnEdge() + myState.myPosLat + 0.5 * myLane->getWidth();
5903  } else if (lane == myLaneChangeModel->getShadowLane()) {
5904  if (myLaneChangeModel->isOpposite() && &lane->getEdge() != &myLane->getEdge()) {
5905  return lane->getRightSideOnEdge() + lane->getWidth() - myState.myPosLat + 0.5 * myLane->getWidth();
5906  }
5907  if (myLaneChangeModel->getShadowDirection() == -1) {
5908  return lane->getRightSideOnEdge() + lane->getWidth() + myState.myPosLat + 0.5 * myLane->getWidth();
5909  } else {
5910  return lane->getRightSideOnEdge() - myLane->getWidth() + myState.myPosLat + 0.5 * myLane->getWidth();
5911  }
5912  } else {
5913  assert(myFurtherLanes.size() == myFurtherLanesPosLat.size());
5914  for (int i = 0; i < (int)myFurtherLanes.size(); ++i) {
5915  if (myFurtherLanes[i] == lane) {
5916 #ifdef DEBUG_FURTHER
5917  if (DEBUG_COND) std::cout << " getCenterOnEdge veh=" << getID() << " lane=" << lane->getID() << " i=" << i << " furtherLat=" << myFurtherLanesPosLat[i]
5918  << " result=" << lane->getRightSideOnEdge() + myFurtherLanesPosLat[i] + 0.5 * lane->getWidth()
5919  << "\n";
5920 #endif
5921  return lane->getRightSideOnEdge() + myFurtherLanesPosLat[i] + 0.5 * lane->getWidth();
5922  }
5923  }
5924  //if (DEBUG_COND) std::cout << SIMTIME << " veh=" << getID() << " myShadowFurtherLanes=" << toString(myLaneChangeModel->getShadowFurtherLanes()) << "\n";
5925  const std::vector<MSLane*>& shadowFurther = myLaneChangeModel->getShadowFurtherLanes();
5926  for (int i = 0; i < (int)shadowFurther.size(); ++i) {
5927  //if (DEBUG_COND) std::cout << " comparing i=" << (*i)->getID() << " lane=" << lane->getID() << "\n";
5928  if (shadowFurther[i] == lane) {
5929  assert(myLaneChangeModel->getShadowLane() != 0);
5930  return (lane->getRightSideOnEdge() + myLaneChangeModel->getShadowFurtherLanesPosLat()[i] + 0.5 * lane->getWidth()
5932  }
5933  }
5934  assert(false);
5935  throw ProcessError("Request lateral pos of vehicle '" + getID() + "' for invalid lane '" + Named::getIDSecure(lane) + "'");
5936  }
5937 }
5938 
5939 
5940 double
5941 MSVehicle::getLatOffset(const MSLane* lane) const {
5942  assert(lane != 0);
5943  if (&lane->getEdge() == &myLane->getEdge()) {
5944  return myLane->getRightSideOnEdge() - lane->getRightSideOnEdge();
5945  } else if (myLane->getParallelOpposite() == lane) {
5946  return (myLane->getWidth() + lane->getWidth()) * 0.5 - 2 * getLateralPositionOnLane();
5947  } else {
5948  // Check whether the lane is a further lane for the vehicle
5949  for (int i = 0; i < (int)myFurtherLanes.size(); ++i) {
5950  if (myFurtherLanes[i] == lane) {
5951 #ifdef DEBUG_FURTHER
5952  if (DEBUG_COND) {
5953  std::cout << " getLatOffset veh=" << getID() << " lane=" << lane->getID() << " i=" << i << " posLat=" << myState.myPosLat << " furtherLat=" << myFurtherLanesPosLat[i] << "\n";
5954  }
5955 #endif
5957  }
5958  }
5959 #ifdef DEBUG_FURTHER
5960  if (DEBUG_COND) {
5961  std::cout << SIMTIME << " veh=" << getID() << " myShadowFurtherLanes=" << toString(myLaneChangeModel->getShadowFurtherLanes()) << "\n";
5962  }
5963 #endif
5964  // Check whether the lane is a "shadow further lane" for the vehicle
5965  const std::vector<MSLane*>& shadowFurther = myLaneChangeModel->getShadowFurtherLanes();
5966  for (int i = 0; i < (int)shadowFurther.size(); ++i) {
5967  if (shadowFurther[i] == lane) {
5968 #ifdef DEBUG_FURTHER
5969  if (DEBUG_COND) std::cout << " getLatOffset veh=" << getID()
5970  << " shadowLane=" << Named::getIDSecure(myLaneChangeModel->getShadowLane())
5971  << " lane=" << lane->getID()
5972  << " i=" << i
5973  << " posLat=" << myState.myPosLat
5974  << " shadowPosLat=" << getLatOffset(myLaneChangeModel->getShadowLane())
5975  << " shadowFurtherLat=" << myLaneChangeModel->getShadowFurtherLanesPosLat()[i]
5976  << "\n";
5977 #endif
5979  }
5980  }
5981  // Check whether the vehicle issued a maneuverReservation on the lane.
5982  const std::vector<MSLane*>& furtherTargets = myLaneChangeModel->getFurtherTargetLanes();
5983  for (int i = 0; i < (int)myFurtherLanes.size(); ++i) {
5984  // Further target lanes are just neighboring lanes of the vehicle's further lanes, @see MSAbstractLaneChangeModel::updateTargetLane()
5985  MSLane* targetLane = furtherTargets[i];
5986  if (targetLane == lane) {
5987  const double targetDir = myLaneChangeModel->getManeuverDist() < 0 ? -1. : 1.;
5988  const double latOffset = myFurtherLanesPosLat[i] - myState.myPosLat + targetDir * 0.5 * (myFurtherLanes[i]->getWidth() + targetLane->getWidth());
5989 #ifdef DEBUG_TARGET_LANE
5990  if (DEBUG_COND) {
5991  std::cout << " getLatOffset veh=" << getID()
5992  << " wrt targetLane=" << Named::getIDSecure(myLaneChangeModel->getTargetLane())
5993  << "\n i=" << i
5994  << " posLat=" << myState.myPosLat
5995  << " furtherPosLat=" << myFurtherLanesPosLat[i]
5996  << " maneuverDist=" << myLaneChangeModel->getManeuverDist()
5997  << " targetDir=" << targetDir
5998  << " latOffset=" << latOffset
5999  << std::endl;
6000  }
6001 #endif
6002  return latOffset;
6003  }
6004  }
6005  assert(false);
6006  throw ProcessError("Request lateral offset of vehicle '" + getID() + "' for invalid lane '" + Named::getIDSecure(lane) + "'");
6007  }
6008 }
6009 
6010 
6011 double
6012 MSVehicle::lateralDistanceToLane(const int offset) const {
6013  // compute the distance when changing to the neighboring lane
6014  // (ensure we do not lap into the line behind neighLane since there might be unseen blockers)
6015  assert(offset == 0 || offset == 1 || offset == -1);
6016  assert(myLane != nullptr);
6017  assert(myLane->getParallelLane(offset) != nullptr || myLane->getParallelOpposite() != nullptr);
6018  const double halfCurrentLaneWidth = 0.5 * myLane->getWidth();
6019  const double halfVehWidth = 0.5 * (getWidth() + NUMERICAL_EPS);
6020  const double latPos = getLateralPositionOnLane();
6021  const double oppositeSign = getLaneChangeModel().isOpposite() ? -1 : 1;
6022  double leftLimit = halfCurrentLaneWidth - halfVehWidth - oppositeSign * latPos;
6023  double rightLimit = -halfCurrentLaneWidth + halfVehWidth - oppositeSign * latPos;
6024  double latLaneDist = 0; // minimum distance to move the vehicle fully onto the new lane
6025  if (offset == 0) {
6026  if (latPos + halfVehWidth > halfCurrentLaneWidth) {
6027  // correct overlapping left
6028  latLaneDist = halfCurrentLaneWidth - latPos - halfVehWidth;
6029  } else if (latPos - halfVehWidth < -halfCurrentLaneWidth) {
6030  // correct overlapping right
6031  latLaneDist = -halfCurrentLaneWidth - latPos + halfVehWidth;
6032  }
6033  latLaneDist *= oppositeSign;
6034  } else if (offset == -1) {
6035  latLaneDist = rightLimit - (getWidth() + NUMERICAL_EPS);
6036  } else if (offset == 1) {
6037  latLaneDist = leftLimit + (getWidth() + NUMERICAL_EPS);
6038  }
6039 #ifdef DEBUG_ACTIONSTEPS
6040  if (DEBUG_COND) {
6041  std::cout << SIMTIME
6042  << " veh=" << getID()
6043  << " halfCurrentLaneWidth=" << halfCurrentLaneWidth
6044  << " halfVehWidth=" << halfVehWidth
6045  << " latPos=" << latPos
6046  << " latLaneDist=" << latLaneDist
6047  << " leftLimit=" << leftLimit
6048  << " rightLimit=" << rightLimit
6049  << "\n";
6050  }
6051 #endif
6052  return latLaneDist;
6053 }
6054 
6055 
6056 double
6057 MSVehicle::getLateralOverlap(double posLat) const {
6058  return (fabs(posLat) + 0.5 * getVehicleType().getWidth()
6059  - 0.5 * myLane->getWidth());
6060 }
6061 
6062 
6063 double
6066 }
6067 
6068 
6069 void
6071  for (const DriveProcessItem& dpi : lfLinks) {
6072  if (dpi.myLink != nullptr) {
6073  dpi.myLink->removeApproaching(this);
6074  }
6075  }
6076  // unregister on all shadow links
6078 }
6079 
6080 
6081 bool
6083  // the following links are unsafe:
6084  // - zipper links if they are close enough and have approaching vehicles in the relevant time range
6085  // - unprioritized links if the vehicle is currently approaching a prioritzed link and unable to stop in time
6086  double seen = myLane->getLength() - getPositionOnLane();
6087  const double dist = getCarFollowModel().brakeGap(getSpeed(), getCarFollowModel().getMaxDecel(), 0);
6088  if (seen < dist) {
6089  const std::vector<MSLane*>& bestLaneConts = getBestLanesContinuation(lane);
6090  int view = 1;
6091  std::vector<MSLink*>::const_iterator link = MSLane::succLinkSec(*this, view, *lane, bestLaneConts);
6092  DriveItemVector::const_iterator di = myLFLinkLanes.begin();
6093  while (!lane->isLinkEnd(link) && seen <= dist) {
6094  if (!lane->getEdge().isInternal()
6095  && (((*link)->getState() == LINKSTATE_ZIPPER && seen < (*link)->getFoeVisibilityDistance())
6096  || !(*link)->havePriority())) {
6097  // find the drive item corresponding to this link
6098  bool found = false;
6099  while (di != myLFLinkLanes.end() && !found) {
6100  if ((*di).myLink != nullptr) {
6101  const MSLane* diPredLane = (*di).myLink->getLaneBefore();
6102  if (diPredLane != nullptr) {
6103  if (&diPredLane->getEdge() == &lane->getEdge()) {
6104  found = true;
6105  }
6106  }
6107  }
6108  if (!found) {
6109  di++;
6110  }
6111  }
6112  if (found) {
6113  const SUMOTime leaveTime = (*link)->getLeaveTime((*di).myArrivalTime, (*di).myArrivalSpeed,
6114  (*di).getLeaveSpeed(), getVehicleType().getLength());
6115  if ((*link)->hasApproachingFoe((*di).myArrivalTime, leaveTime, (*di).myArrivalSpeed, getCarFollowModel().getMaxDecel())) {
6116  //std::cout << SIMTIME << " veh=" << getID() << " aborting changeTo=" << Named::getIDSecure(bestLaneConts.front()) << " linkState=" << toString((*link)->getState()) << " seen=" << seen << " dist=" << dist << "\n";
6117  return true;
6118  }
6119  }
6120  // no drive item is found if the vehicle aborts it's request within dist
6121  }
6122  lane = (*link)->getViaLaneOrLane();
6123  if (!lane->getEdge().isInternal()) {
6124  view++;
6125  }
6126  seen += lane->getLength();
6127  link = MSLane::succLinkSec(*this, view, *lane, bestLaneConts);
6128  }
6129  }
6130  return false;
6131 }
6132 
6133 
6135 MSVehicle::getBoundingBox(double offset) const {
6136  PositionVector centerLine;
6137  centerLine.push_back(getPosition());
6138  switch (myType->getGuiShape()) {
6145  for (MSLane* lane : myFurtherLanes) {
6146  centerLine.push_back(lane->getShape().back());
6147  }
6148  break;
6149  }
6150  default:
6151  break;
6152  }
6153  centerLine.push_back(getBackPosition());
6154  if (offset != 0) {
6155  centerLine.extrapolate2D(offset);
6156  }
6157  PositionVector result = centerLine;
6158  result.move2side(MAX2(0.0, 0.5 * myType->getWidth() + offset));
6159  centerLine.move2side(MIN2(0.0, -0.5 * myType->getWidth() - offset));
6160  result.append(centerLine.reverse(), POSITION_EPS);
6161  return result;
6162 }
6163 
6164 
6166 MSVehicle::getBoundingPoly(double offset) const {
6167  switch (myType->getGuiShape()) {
6173  // box with corners cut off
6174  PositionVector result;
6175  PositionVector centerLine;
6176  centerLine.push_back(getPosition());
6177  centerLine.push_back(getBackPosition());
6178  if (offset != 0) {
6179  centerLine.extrapolate2D(offset);
6180  }
6181  PositionVector line1 = centerLine;
6182  PositionVector line2 = centerLine;
6183  line1.move2side(MAX2(0.0, 0.3 * myType->getWidth() + offset));
6184  line2.move2side(MAX2(0.0, 0.5 * myType->getWidth() + offset));
6185  line2.scaleRelative(0.8);
6186  result.push_back(line1[0]);
6187  result.push_back(line2[0]);
6188  result.push_back(line2[1]);
6189  result.push_back(line1[1]);
6190  line1.move2side(MIN2(0.0, -0.6 * myType->getWidth() - offset));
6191  line2.move2side(MIN2(0.0, -1.0 * myType->getWidth() - offset));
6192  result.push_back(line1[1]);
6193  result.push_back(line2[1]);
6194  result.push_back(line2[0]);
6195  result.push_back(line1[0]);
6196  return result;
6197  }
6198  default:
6199  return getBoundingBox();
6200  }
6201 }
6202 
6203 
6204 bool
6205 MSVehicle::onFurtherEdge(const MSEdge* edge) const {
6206  for (std::vector<MSLane*>::const_iterator i = myFurtherLanes.begin(); i != myFurtherLanes.end(); ++i) {
6207  if (&(*i)->getEdge() == edge) {
6208  return true;
6209  }
6210  }
6211  return false;
6212 }
6213 
6214 bool
6215 MSVehicle::rerouteParkingArea(const std::string& parkingAreaID, std::string& errorMsg) {
6216  // this function is based on MSTriggeredRerouter::rerouteParkingArea in order to keep
6217  // consistency in the behaviour.
6218 
6219  // get vehicle params
6220  MSParkingArea* destParkArea = getNextParkingArea();
6221  const MSRoute& route = getRoute();
6222  const MSEdge* lastEdge = route.getLastEdge();
6223 
6224  if (destParkArea == nullptr) {
6225  // not driving towards a parking area
6226  errorMsg = "Vehicle " + getID() + " is not driving to a parking area so it cannot be rerouted.";
6227  return false;
6228  }
6229 
6230  // if the current route ends at the parking area, the new route will also and at the new area
6231  bool newDestination = (&destParkArea->getLane().getEdge() == route.getLastEdge()
6232  && getArrivalPos() >= destParkArea->getBeginLanePosition()
6233  && getArrivalPos() <= destParkArea->getEndLanePosition());
6234 
6235  // retrieve info on the new parking area
6237  parkingAreaID, SumoXMLTag::SUMO_TAG_PARKING_AREA);
6238 
6239  if (newParkingArea == nullptr) {
6240  errorMsg = "Parking area ID " + toString(parkingAreaID) + " not found in the network.";
6241  return false;
6242  }
6243 
6244  const MSEdge* newEdge = &(newParkingArea->getLane().getEdge());
6246 
6247  // Compute the route from the current edge to the parking area edge
6248  ConstMSEdgeVector edgesToPark;
6249  router.compute(getEdge(), newEdge, this, MSNet::getInstance()->getCurrentTimeStep(), edgesToPark);
6250 
6251  // Compute the route from the parking area edge to the end of the route
6252  ConstMSEdgeVector edgesFromPark;
6253  if (!newDestination) {
6254  router.compute(newEdge, lastEdge, this, MSNet::getInstance()->getCurrentTimeStep(), edgesFromPark);
6255  } else {
6256  // adapt plans of any riders
6257  for (MSTransportable* p : getPersons()) {
6258  p->rerouteParkingArea(getNextParkingArea(), newParkingArea);
6259  }
6260  }
6261 
6262  // we have a new destination, let's replace the vehicle route
6263  ConstMSEdgeVector edges = edgesToPark;
6264  if (edgesFromPark.size() > 0) {
6265  edges.insert(edges.end(), edgesFromPark.begin() + 1, edgesFromPark.end());
6266  }
6267 
6268  if (newDestination) {
6269  SUMOVehicleParameter* newParameter = new SUMOVehicleParameter();
6270  *newParameter = getParameter();
6272  newParameter->arrivalPos = newParkingArea->getEndLanePosition();
6273  replaceParameter(newParameter);
6274  }
6275  const double routeCost = router.recomputeCosts(edges, this, MSNet::getInstance()->getCurrentTimeStep());
6276  ConstMSEdgeVector prevEdges(myCurrEdge, myRoute->end());
6277  const double savings = router.recomputeCosts(prevEdges, this, MSNet::getInstance()->getCurrentTimeStep());
6278  if (replaceParkingArea(newParkingArea, errorMsg)) {
6279  const bool onInit = myLane == nullptr;
6280  replaceRouteEdges(edges, routeCost, savings, "TraCI:" + toString(SUMO_TAG_PARKING_AREA_REROUTE), onInit, false, false);
6281  } else {
6282  WRITE_WARNING("Vehicle '" + getID() + "' could not reroute to new parkingArea '" + newParkingArea->getID()
6283  + "' reason=" + errorMsg + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
6284  return false;
6285  }
6286  return true;
6287 }
6288 
6289 
6290 bool
6292  const int numStops = (int)myStops.size();
6293  const bool result = MSBaseVehicle::addTraciStop(stop, errorMsg);
6294  if (myLane != nullptr && numStops != (int)myStops.size()) {
6295  updateBestLanes(true);
6296  }
6297  return result;
6298 }
6299 
6300 
6301 bool
6302 MSVehicle::handleCollisionStop(MSStop& stop, const double distToStop) {
6303  if (myCurrEdge == stop.edge && distToStop + POSITION_EPS < getCarFollowModel().brakeGap(myState.mySpeed, getCarFollowModel().getMaxDecel(), 0)) {
6304  if (distToStop < getCarFollowModel().brakeGap(myState.mySpeed, getCarFollowModel().getEmergencyDecel(), 0)) {
6305  double vNew = getCarFollowModel().maximumSafeStopSpeed(distToStop, getCarFollowModel().getMaxDecel(), getSpeed(), false, 0);
6306  //std::cout << SIMTIME << " veh=" << getID() << " v=" << myState.mySpeed << " distToStop=" << distToStop
6307  // << " vMinNex=" << getCarFollowModel().minNextSpeed(getSpeed(), this)
6308  // << " bg1=" << getCarFollowModel().brakeGap(myState.mySpeed)
6309  // << " bg2=" << getCarFollowModel().brakeGap(myState.mySpeed, getCarFollowModel().getEmergencyDecel(), 0)
6310  // << " vNew=" << vNew
6311  // << "\n";
6312  myState.mySpeed = MIN2(myState.mySpeed, vNew + ACCEL2SPEED(getCarFollowModel().getEmergencyDecel()));
6315  if (myState.myPos < myType->getLength()) {
6317  myAngle = computeAngle();
6318  if (myLaneChangeModel->isOpposite()) {
6319  myAngle += M_PI;
6320  }
6321  }
6322  }
6323  }
6324  return true;
6325 }
6326 
6327 
6328 bool
6330  if (isStopped()) {
6335  }
6336  // we have waited long enough and fulfilled any passenger-requirements
6337  if (myStops.front().busstop != nullptr) {
6338  // inform bus stop about leaving it
6339  myStops.front().busstop->leaveFrom(this);
6340  }
6341  // we have waited long enough and fulfilled any container-requirements
6342  if (myStops.front().containerstop != nullptr) {
6343  // inform container stop about leaving it
6344  myStops.front().containerstop->leaveFrom(this);
6345  }
6346  if (myStops.front().parkingarea != nullptr) {
6347  // inform parking area about leaving it
6348  myStops.front().parkingarea->leaveFrom(this);
6349  }
6350  if (myStops.front().chargingStation != nullptr) {
6351  // inform charging station about leaving it
6352  myStops.front().chargingStation->leaveFrom(this);
6353  }
6354  // the current stop is no longer valid
6355  myLane->getEdge().removeWaiting(this);
6356  SUMOVehicleParameter::Stop pars = myStops.front().pars;
6358  MSDevice_Vehroutes* vehroutes = static_cast<MSDevice_Vehroutes*>(getDevice(typeid(MSDevice_Vehroutes)));
6359  if (vehroutes != nullptr) {
6360  vehroutes->stopEnded(pars);
6361  }
6362  if (MSStopOut::active()) {
6363  MSStopOut::getInstance()->stopEnded(this, pars, myStops.front().lane->getID());
6364  }
6365  if (myStops.front().collision && MSLane::getCollisionAction() == MSLane::COLLISION_ACTION_WARN) {
6366  myCollisionImmunity = TIME2STEPS(5); // leave the conflict area
6367  }
6368  if (pars.posLat != INVALID_DOUBLE && MSGlobals::gLateralResolution <= 0) {
6369  // reset lateral position to default
6370  myState.myPosLat = 0;
6371  }
6372  myPastStops.push_back(pars);
6373  myStops.pop_front();
6374  // do not count the stopping time towards gridlock time.
6375  // Other outputs use an independent counter and are not affected.
6376  myWaitingTime = 0;
6377  // maybe the next stop is on the same edge; let's rebuild best lanes
6378  updateBestLanes(true);
6379  // continue as wished...
6382  return true;
6383  }
6384  return false;
6385 }
6386 
6387 
6390  if (myInfluencer == nullptr) {
6391  myInfluencer = new Influencer();
6392  }
6393  return *myInfluencer;
6394 }
6395 
6398  return getInfluencer();
6399 }
6400 
6401 
6402 const MSVehicle::Influencer*
6404  return myInfluencer;
6405 }
6406 
6409  return myInfluencer;
6410 }
6411 
6412 
6413 double
6415  if (myInfluencer != nullptr && myInfluencer->getOriginalSpeed() >= 0) {
6416  // influencer original speed is -1 on initialization
6417  return myInfluencer->getOriginalSpeed();
6418  }
6419  return myState.mySpeed;
6420 }
6421 
6422 
6423 int
6425  if (hasInfluencer()) {
6427  MSNet::getInstance()->getCurrentTimeStep(),
6428  myLane->getEdge(),
6429  getLaneIndex(),
6430  state);
6431  }
6432  return state;
6433 }
6434 
6435 
6436 void
6438  myCachedPosition = xyPos;
6439 }
6440 
6441 
6442 bool
6444  return myInfluencer != nullptr && myInfluencer->isRemoteControlled();
6445 }
6446 
6447 
6448 bool
6450  return myInfluencer != nullptr && myInfluencer->getLastAccessTimeStep() + lookBack >= MSNet::getInstance()->getCurrentTimeStep();
6451 }
6452 
6453 
6454 bool
6455 MSVehicle::keepClear(const MSLink* link) const {
6456  if (link->hasFoes() && link->keepClear() /* && item.myLink->willHaveBlockedFoe()*/) {
6457  const double keepClearTime = getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_IGNORE_KEEPCLEAR_TIME, -1);
6458  //std::cout << SIMTIME << " veh=" << getID() << " keepClearTime=" << keepClearTime << " accWait=" << getAccumulatedWaitingSeconds() << " keepClear=" << (keepClearTime < 0 || getAccumulatedWaitingSeconds() < keepClearTime) << "\n";
6459  return keepClearTime < 0 || getAccumulatedWaitingSeconds() < keepClearTime;
6460  } else {
6461  return false;
6462  }
6463 }
6464 
6465 
6466 bool
6467 MSVehicle::ignoreRed(const MSLink* link, bool canBrake) const {
6468  if ((myInfluencer != nullptr && !myInfluencer->getEmergencyBrakeRedLight())) {
6469  return true;
6470  }
6471  const double ignoreRedTime = getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_DRIVE_AFTER_RED_TIME, -1);
6472 #ifdef DEBUG_IGNORE_RED
6473  if (DEBUG_COND) {
6474  std::cout << SIMTIME << " veh=" << getID() << " link=" << link->getViaLaneOrLane()->getID() << " state=" << toString(link->getState()) << "\n";
6475  }
6476 #endif
6477  if (ignoreRedTime < 0) {
6478  const double ignoreYellowTime = getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_DRIVE_AFTER_YELLOW_TIME, 0);
6479  if (ignoreYellowTime > 0 && link->haveYellow()) {
6480  assert(link->getTLLogic() != 0);
6481  const double yellowDuration = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep() - link->getLastStateChange());
6482  // when activating ignoreYellow behavior, vehicles will drive if they cannot brake
6483  return !canBrake || ignoreYellowTime > yellowDuration;
6484  } else {
6485  return false;
6486  }
6487  } else if (link->haveYellow()) {
6488  // always drive at yellow when ignoring red
6489  return true;
6490  } else if (link->haveRed()) {
6491  assert(link->getTLLogic() != 0);
6492  const double redDuration = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep() - link->getLastStateChange());
6493 #ifdef DEBUG_IGNORE_RED
6494  if (DEBUG_COND) {
6495  std::cout
6496  // << SIMTIME << " veh=" << getID() << " link=" << link->getViaLaneOrLane()->getID()
6497  << " ignoreRedTime=" << ignoreRedTime
6498  << " spentRed=" << redDuration
6499  << " canBrake=" << canBrake << "\n";
6500  }
6501 #endif
6502  // when activating ignoreRed behavior, vehicles will always drive if they cannot brake
6503  return !canBrake || ignoreRedTime > redDuration;
6504  } else {
6505  return false;
6506  }
6507 }
6508 
6509 
6510 bool
6512  // either on an internal lane that was entered via minor link
6513  // or on approach to minor link below visibility distance
6514  if (myLane == nullptr) {
6515  return false;
6516  }
6517  if (myLane->getEdge().isInternal()) {
6518  return !myLane->getIncomingLanes().front().viaLink->havePriority();
6519  } else if (myLFLinkLanes.size() > 0 && myLFLinkLanes.front().myLink != nullptr) {
6520  MSLink* link = myLFLinkLanes.front().myLink;
6521  return !link->havePriority() && myLFLinkLanes.front().myDistance <= link->getFoeVisibilityDistance();
6522  }
6523  return false;
6524 }
6525 
6526 bool
6527 MSVehicle::isLeader(const MSLink* link, const MSVehicle* veh) const {
6528  assert(link->fromInternalLane());
6529  if (veh == nullptr) {
6530  return false;
6531  }
6532  if (!myLane->isInternal() || myLane->getEdge().getToJunction() != link->getJunction()) {
6533  // if this vehicle is not yet on the junction, every vehicle is a leader
6534  return true;
6535  }
6536  if (veh->getLaneChangeModel().hasBlueLight()) {
6537  // blue light device automatically gets right of way
6538  return true;
6539  }
6540  const MSLane* foeLane = veh->getLane();
6541  if (foeLane->isInternal()) {
6542  if (foeLane->getEdge().getFromJunction() == link->getJunction()) {
6544  SUMOTime foeET = veh->myJunctionEntryTime;
6545  // check relationship between link and foeLane
6547  // we are entering the junction from the same lane
6549  foeET = veh->myJunctionEntryTimeNeverYield;
6552  }
6553  } else {
6554  const MSLink* foeLink = foeLane->getIncomingLanes()[0].viaLink;
6555  const MSJunctionLogic* logic = link->getJunction()->getLogic();
6556  assert(logic != nullptr);
6557  // determine who has right of way
6558  bool response; // ego response to foe
6559  bool response2; // foe response to ego
6560  // attempt 1: tlLinkState
6561  const MSLink* entry = link->getCorrespondingEntryLink();
6562  const MSLink* foeEntry = foeLink->getCorrespondingEntryLink();
6563  if (entry->haveRed() || foeEntry->haveRed()) {
6564  // ensure that vehicles which are stuck on the intersection may exit
6565  response = foeEntry->haveRed();
6566  response2 = entry->haveRed();
6567  } else if (entry->havePriority() != foeEntry->havePriority()) {
6568  response = !entry->havePriority();
6569  response2 = !foeEntry->havePriority();
6570  } else if (entry->haveYellow() && foeEntry->haveYellow()) {
6571  // let the faster vehicle keep moving
6572  response = veh->getSpeed() >= getSpeed();
6573  response2 = getSpeed() >= veh->getSpeed();
6574  } else {
6575  // fallback if pedestrian crossings are involved
6576  response = logic->getResponseFor(link->getIndex()).test(foeLink->getIndex());
6577  response2 = logic->getResponseFor(foeLink->getIndex()).test(link->getIndex());
6578  }
6579 #ifdef DEBUG_PLAN_MOVE_LEADERINFO
6580  if (DEBUG_COND) {
6581  std::cout << SIMTIME
6582  << " foeLane=" << foeLane->getID()
6583  << " foeLink=" << foeLink->getViaLaneOrLane()->getID()
6584  << " linkIndex=" << link->getIndex()
6585  << " foeLinkIndex=" << foeLink->getIndex()
6586  << " entryState=" << toString(entry->getState())
6587  << " entryState2=" << toString(foeEntry->getState())
6588  << " response=" << response
6589  << " response2=" << response2
6590  << "\n";
6591  }
6592 #endif
6593  if (!response) {
6594  // if we have right of way over the foe, entryTime does not matter
6595  foeET = veh->myJunctionConflictEntryTime;
6596  egoET = myJunctionEntryTime;
6597  } else if (response && response2) {
6598  // in a mutual conflict scenario, use entry time to avoid deadlock
6599  foeET = veh->myJunctionConflictEntryTime;
6601  }
6602  }
6603  if (egoET == foeET) {
6604  // try to use speed as tie braker
6605  if (getSpeed() == veh->getSpeed()) {
6606  // use ID as tie braker
6607 #ifdef DEBUG_PLAN_MOVE_LEADERINFO
6608  if (DEBUG_COND) {
6609  std::cout << SIMTIME << " veh=" << getID() << " equal ET " << egoET << " with foe " << veh->getID()
6610  << " foeIsLeaderByID=" << (getID() < veh->getID()) << "\n";
6611  }
6612 #endif
6613  return getID() < veh->getID();
6614  } else {
6615 #ifdef DEBUG_PLAN_MOVE_LEADERINFO
6616  if (DEBUG_COND) {
6617  std::cout << SIMTIME << " veh=" << getID() << " equal ET " << egoET << " with foe " << veh->getID()
6618  << " foeIsLeaderBySpeed=" << (getSpeed() < veh->getSpeed())
6619  << " v=" << getSpeed() << " foeV=" << veh->getSpeed()
6620  << "\n";
6621  }
6622 #endif
6623  return getSpeed() < veh->getSpeed();
6624  }
6625  } else {
6626  // leader was on the junction first
6627 #ifdef DEBUG_PLAN_MOVE_LEADERINFO
6628  if (DEBUG_COND) {
6629  std::cout << SIMTIME << " veh=" << getID() << " egoET " << egoET << " with foe " << veh->getID()
6630  << " foeET=" << foeET << " isLeader=" << (egoET > foeET) << "\n";
6631  }
6632 #endif
6633  return egoET > foeET;
6634  }
6635  } else {
6636  // vehicle can only be partially on the junction. Must be a leader
6637  return true;
6638  }
6639  } else {
6640  // vehicle can only be partially on the junction. Must be a leader
6641  return true;
6642  }
6643 }
6644 
6645 void
6648  // here starts the vehicle internal part (see loading)
6649  std::vector<std::string> internals;
6650  internals.push_back(toString(myParameter->parametersSet));
6651  internals.push_back(toString(myDeparture));
6652  internals.push_back(toString(distance(myRoute->begin(), myCurrEdge)));
6653  internals.push_back(toString(myDepartPos));
6654  internals.push_back(toString(myWaitingTime));
6655  internals.push_back(toString(myTimeLoss));
6656  internals.push_back(toString(myLastActionTime));
6657  internals.push_back(toString(isStopped()));
6658  internals.push_back(toString(myPastStops.size()));
6659  out.writeAttr(SUMO_ATTR_STATE, internals);
6661  out.writeAttr(SUMO_ATTR_SPEED, std::vector<double> { myState.mySpeed, myState.myPreviousSpeed });
6665  // save past stops
6667  stop.write(out, false);
6668  // do not write started and ended twice
6669  if ((stop.parametersSet & STOP_STARTED_SET) == 0) {
6670  out.writeAttr(SUMO_ATTR_STARTED, time2string(stop.started));
6671  }
6672  if ((stop.parametersSet & STOP_ENDED_SET) == 0) {
6673  out.writeAttr(SUMO_ATTR_ENDED, time2string(stop.ended));
6674  }
6675  out.closeTag();
6676  }
6677  // save upcoming stops
6678  for (MSStop& stop : myStops) {
6679  stop.write(out);
6680  }
6681  // save parameters and device states
6682  myParameter->writeParams(out);
6683  for (MSVehicleDevice* const dev : myDevices) {
6684  dev->saveState(out);
6685  }
6686  out.closeTag();
6687 }
6688 
6689 void
6690 MSVehicle::loadState(const SUMOSAXAttributes& attrs, const SUMOTime offset) {
6691  if (!attrs.hasAttribute(SUMO_ATTR_POSITION)) {
6692  throw ProcessError("Error: Invalid vehicles in state (may be a meso state)!");
6693  }
6694  int routeOffset;
6695  bool stopped;
6696  int pastStops;
6697  std::istringstream bis(attrs.getString(SUMO_ATTR_STATE));
6698  bis >> myParameter->parametersSet;
6699  bis >> myDeparture;
6700  bis >> routeOffset;
6701  bis >> myDepartPos;
6702  bis >> myWaitingTime;
6703  bis >> myTimeLoss;
6704  bis >> myLastActionTime;
6705  bis >> stopped;
6706  bis >> pastStops;
6707  if (hasDeparted()) {
6708  myCurrEdge = myRoute->begin() + routeOffset;
6709  myDeparture -= offset;
6710  // fix stops
6711  while (pastStops > 0) {
6712  myPastStops.push_back(myStops.front().pars);
6713  myStops.pop_front();
6714  pastStops--;
6715  }
6716  // see MSBaseVehicle constructor
6718  calculateArrivalParams(true);
6719  }
6720  }
6721  std::istringstream pis(attrs.getString(SUMO_ATTR_POSITION));
6723  std::istringstream sis(attrs.getString(SUMO_ATTR_SPEED));
6728  std::istringstream dis(attrs.getString(SUMO_ATTR_DISTANCE));
6729  dis >> myOdometer >> myNumberReroutes;
6731  if (stopped) {
6732  myStopDist = 0;
6733  }
6734  // no need to reset myCachedPosition here since state loading happens directly after creation
6735 }
6736 
6737 void
6739  SUMOTime arrivalTime, double arrivalSpeed,
6740  SUMOTime arrivalTimeBraking, double arrivalSpeedBraking,
6741  double dist, double leaveSpeed) {
6742  // ensure that approach information is reset on the next call to setApproachingForAllLinks
6743  myLFLinkLanes.push_back(DriveProcessItem(link, 0, 0, setRequest,
6744  arrivalTime, arrivalSpeed, arrivalTimeBraking, arrivalSpeedBraking, dist, leaveSpeed));
6745 
6746 }
6747 
6748 
6749 std::shared_ptr<MSSimpleDriverState>
6751  return myDriverState->getDriverState();
6752 }
6753 
6754 
6755 void
6756 MSVehicle::setPreviousSpeed(double prevspeed) {
6757  myState.mySpeed = MAX2(0., prevspeed);
6758  // also retcon acceleration
6760 }
6761 
6762 
6763 double
6765  //return MAX2(-myAcceleration, getCarFollowModel().getApparentDecel());
6767 }
6768 
6769 /****************************************************************************/
6770 bool
6772  return (myManoeuvre.configureExitManoeuvre(this));
6773 }
6774 
6775 /* -------------------------------------------------------------------------
6776  * methods of MSVehicle::manoeuvre
6777  * ----------------------------------------------------------------------- */
6778 
6779 MSVehicle::Manoeuvre::Manoeuvre() : myManoeuvreStop(""), myManoeuvreStartTime(0), myManoeuvreCompleteTime(0), myManoeuvreType(MSVehicle::MANOEUVRE_NONE), myGUIIncrement(0) {}
6780 
6782  myManoeuvreStop = manoeuvre.myManoeuvreStop;
6783  myManoeuvreStartTime = manoeuvre.myManoeuvreStartTime;
6784  myManoeuvreCompleteTime = manoeuvre.myManoeuvreCompleteTime;
6785  myManoeuvreType = manoeuvre.myManoeuvreType;
6786  myGUIIncrement = manoeuvre.myGUIIncrement;
6787 }
6788 
6791  myManoeuvreStop = manoeuvre.myManoeuvreStop;
6792  myManoeuvreStartTime = manoeuvre.myManoeuvreStartTime;
6793  myManoeuvreCompleteTime = manoeuvre.myManoeuvreCompleteTime;
6794  myManoeuvreType = manoeuvre.myManoeuvreType;
6795  myGUIIncrement = manoeuvre.myGUIIncrement;
6796  return *this;
6797 }
6798 
6799 bool
6801  return (myManoeuvreStop != manoeuvre.myManoeuvreStop ||
6802  myManoeuvreStartTime != manoeuvre.myManoeuvreStartTime ||
6803  myManoeuvreCompleteTime != manoeuvre.myManoeuvreCompleteTime ||
6804  myManoeuvreType != manoeuvre.myManoeuvreType ||
6805  myGUIIncrement != manoeuvre.myGUIIncrement
6806  );
6807 }
6808 
6809 double
6811  return (myGUIIncrement);
6812 }
6813 
6816  return (myManoeuvreType);
6817 }
6818 
6821  return (myManoeuvre.getManoeuvreType());
6822 }
6823 
6824 
6825 void
6828 }
6829 
6830 void
6832  myManoeuvreType = mType;
6833 }
6834 
6835 
6836 bool
6838  if (!veh->hasStops()) {
6839  return false; // should never happen - checked before call
6840  }
6841 
6842  const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
6843  const MSStop& stop = veh->getNextStop();
6844 
6845  int manoeuverAngle = stop.parkingarea->getLastFreeLotAngle();
6846  double GUIAngle = stop.parkingarea->getLastFreeLotGUIAngle();
6847  if (abs(GUIAngle) < 0.1) {
6848  GUIAngle = -0.1; // Wiggle vehicle on parallel entry
6849  }
6850  myManoeuvreVehicleID = veh->getID();
6851  myManoeuvreStop = stop.parkingarea->getID();
6852  myManoeuvreType = MSVehicle::MANOEUVRE_ENTRY;
6853  myManoeuvreStartTime = currentTime;
6854  myManoeuvreCompleteTime = currentTime + veh->myType->getEntryManoeuvreTime(manoeuverAngle);
6855  myGUIIncrement = GUIAngle / ((myManoeuvreCompleteTime - myManoeuvreStartTime) / (TS * 1000.));
6856 
6857 #ifdef DEBUG_STOPS
6858  if (veh->isSelected()) {
6859  std::cout << "ENTRY manoeuvre start: vehicle=" << veh->getID() << " Manoeuvre Angle=" << manoeuverAngle << " Rotation angle=" << RAD2DEG(GUIAngle) << " Road Angle" << RAD2DEG(veh->getAngle()) << " increment=" << RAD2DEG(myGUIIncrement) << " currentTime=" << currentTime <<
6860  " endTime=" << myManoeuvreCompleteTime << " manoeuvre time=" << myManoeuvreCompleteTime - currentTime << " parkArea=" << myManoeuvreStop << std::endl;
6861  }
6862 #endif
6863 
6864  return (true);
6865 }
6866 
6867 bool
6869  // At the moment we only want to set for parking areas
6870  if (!veh->hasStops()) {
6871  return true;
6872  }
6873  if (veh->getNextStop().parkingarea == nullptr) {
6874  return true;
6875  }
6876 
6877  if (myManoeuvreType != MSVehicle::MANOEUVRE_NONE) {
6878  return (false);
6879  }
6880 
6881  const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
6882 
6883  int manoeuverAngle = veh->getCurrentParkingArea()->getManoeuverAngle(*veh);
6884  double GUIAngle = veh->getCurrentParkingArea()->getGUIAngle(*veh);
6885  if (abs(GUIAngle) < 0.1) {
6886  GUIAngle = 0.1; // Wiggle vehicle on parallel exit
6887  }
6888 
6889  myManoeuvreVehicleID = veh->getID();
6890  myManoeuvreStop = veh->getCurrentParkingArea()->getID();
6891  myManoeuvreType = MSVehicle::MANOEUVRE_EXIT;
6892  myManoeuvreStartTime = currentTime;
6893  myManoeuvreCompleteTime = currentTime + veh->myType->getExitManoeuvreTime(manoeuverAngle);
6894  myGUIIncrement = (-GUIAngle) / ((myManoeuvreCompleteTime - myManoeuvreStartTime) / (TS * 1000.));
6895  if (veh->remainingStopDuration() > 0) {
6896  myManoeuvreCompleteTime += veh->remainingStopDuration();
6897  }
6898 
6899 #ifdef DEBUG_STOPS
6900  if (veh->isSelected()) {
6901  std::cout << "EXIT manoeuvre start: vehicle=" << veh->getID() << " Manoeuvre Angle=" << manoeuverAngle << " increment=" << RAD2DEG(myGUIIncrement) << " currentTime=" << currentTime
6902  << " endTime=" << myManoeuvreCompleteTime << " manoeuvre time=" << myManoeuvreCompleteTime - currentTime << " parkArea=" << myManoeuvreStop << std::endl;
6903  }
6904 #endif
6905 
6906  return (true);
6907 }
6908 
6909 bool
6911  // At the moment we only want to consider parking areas - need to check because we could be setting up a manoeuvre
6912  if (!veh->hasStops()) {
6913  return (true);
6914  }
6915  MSStop* currentStop = &veh->myStops.front();
6916  if (currentStop->parkingarea == nullptr) {
6917  return true;
6918  } else if (currentStop->parkingarea->getID() != myManoeuvreStop || MSVehicle::MANOEUVRE_ENTRY != myManoeuvreType) {
6919  if (configureEntryManoeuvre(veh)) {
6921  return (false);
6922  } else { // cannot configure entry so stop trying
6923  return true;
6924  }
6925  } else if (MSNet::getInstance()->getCurrentTimeStep() < myManoeuvreCompleteTime) {
6926  return false;
6927  } else { // manoeuvre complete
6928  myManoeuvreType = MSVehicle::MANOEUVRE_NONE;
6929  return true;
6930  }
6931 }
6932 
6933 
6934 bool
6936  if (checkType != myManoeuvreType) {
6937  return true; // we're not manoeuvering / wrong manoeuvre
6938  }
6939 
6940  if (MSNet::getInstance()->getCurrentTimeStep() < myManoeuvreCompleteTime) {
6941  return false;
6942  } else {
6943  return true;
6944  }
6945 }
6946 
6947 
6948 bool
6950  return (MSNet::getInstance()->getCurrentTimeStep() >= myManoeuvreCompleteTime);
6951 }
6952 bool
6954  return (myManoeuvre.manoeuvreIsComplete());
6955 }
6956 
6957 double
6959  if (hasStops()) {
6960  MSLane* lane = myLane;
6961  if (lane == nullptr) {
6962  // not in network
6963  lane = getEdge()->getLanes()[0];
6964  }
6965  const MSStop& stop = myStops.front();
6966  auto it = myCurrEdge + 1;
6967  // drive to end of current edge
6968  double dist = (lane->getLength() - getPositionOnLane());
6969  double travelTime = lane->getEdge().getMinimumTravelTime(this) * dist / lane->getLength();
6970  // drive until stop edge
6971  while (it != myRoute->end() && it < stop.edge) {
6972  travelTime += (*it)->getMinimumTravelTime(this);
6973  dist += (*it)->getLength();
6974  it++;
6975  }
6976  // drive up to the stop position
6977  const double stopEdgeDist = stop.pars.endPos - (lane == stop.lane ? lane->getLength() : 0);
6978  dist += stopEdgeDist;
6979  travelTime += stop.lane->getEdge().getMinimumTravelTime(this) * (stopEdgeDist / stop.lane->getLength());
6980  // estimate time loss due to acceleration and deceleration
6981  // maximum speed is limited by available distance:
6982  const double a = getCarFollowModel().getMaxAccel();
6983  const double b = getCarFollowModel().getMaxDecel();
6984  const double c = getSpeed();
6985  const double d = dist;
6986  const double len = getVehicleType().getLength();
6987  const double vs = MIN2(MAX2(stop.pars.speed, 0.0), stop.lane->getVehicleMaxSpeed(this));
6988  // distAccel = (v - c)^2 / (2a)
6989  // distDecel = (v + vs)*(v - vs) / 2b = (v^2 - vs^2) / (2b)
6990  // distAccel + distDecel < d
6991  const double maxVD = MAX2(c, ((sqrt(MAX2(0.0, pow(2 * c * b, 2) + (4 * ((b * ((a * (2 * d * (b + a) + (vs * vs) - (c * c))) - (b * (c * c))))
6992  + pow((a * vs), 2))))) * 0.5) + (c * b)) / (b + a));
6993  it = myCurrEdge;
6994  double v0 = c;
6995  bool v0Stable = getAcceleration() == 0 && v0 > 0;
6996  double timeLossAccel = 0;
6997  double timeLossDecel = 0;
6998  double timeLossLength = 0;
6999  while (it != myRoute->end() && it <= stop.edge) {
7000  double v = MIN2(maxVD, (*it)->getVehicleMaxSpeed(this));
7001  double edgeLength = (it == stop.edge ? stop.pars.endPos : (*it)->getLength()) - (it == myCurrEdge ? getPositionOnLane() : 0);
7002  if (edgeLength <= len && v0Stable && v0 < v) {
7003  const double lengthDist = MIN2(len, edgeLength);
7004  const double dTL = lengthDist / v0 - lengthDist / v;
7005  //std::cout << " e=" << (*it)->getID() << " v0=" << v0 << " v=" << v << " el=" << edgeLength << " lDist=" << lengthDist << " newTLL=" << dTL<< "\n";
7006  timeLossLength += dTL;
7007  }
7008  if (edgeLength > len) {
7009  const double dv = v - v0;
7010  if (dv > 0) {
7011  // timeLossAccel = timeAccel - timeMaxspeed = dv / a - distAccel / v
7012  const double dTA = dv / a - dv * (v + v0) / (2 * a * v);
7013  //std::cout << " e=" << (*it)->getID() << " v0=" << v0 << " v=" << v << " newTLA=" << dTA << "\n";
7014  timeLossAccel += dTA;
7015  // time loss from vehicle length
7016  } else if (dv < 0) {
7017  // timeLossDecel = timeDecel - timeMaxspeed = dv / b - distDecel / v
7018  const double dTD = -dv / b + dv * (v + v0) / (2 * b * v0);
7019  //std::cout << " e=" << (*it)->getID() << " v0=" << v0 << " v=" << v << " newTLD=" << dTD << "\n";
7020  timeLossDecel += dTD;
7021  }
7022  v0 = v;
7023  v0Stable = true;
7024  }
7025  it++;
7026  }
7027  // final deceleration to stop (may also be acceleration or deceleration to waypoint speed)
7028  double v = vs;
7029  const double dv = v - v0;
7030  if (dv > 0) {
7031  // timeLossAccel = timeAccel - timeMaxspeed = dv / a - distAccel / v
7032  const double dTA = dv / a - dv * (v + v0) / (2 * a * v);
7033  //std::cout << " final e=" << (*it)->getID() << " v0=" << v0 << " v=" << v << " newTLA=" << dTA << "\n";
7034  timeLossAccel += dTA;
7035  // time loss from vehicle length
7036  } else if (dv < 0) {
7037  // timeLossDecel = timeDecel - timeMaxspeed = dv / b - distDecel / v
7038  const double dTD = -dv / b + dv * (v + v0) / (2 * b * v0);
7039  //std::cout << " final e=" << (*it)->getID() << " v0=" << v0 << " v=" << v << " newTLD=" << dTD << "\n";
7040  timeLossDecel += dTD;
7041  }
7042  const double result = travelTime + timeLossAccel + timeLossDecel + timeLossLength;
7043  //std::cout << SIMTIME << " v=" << c << " a=" << a << " b=" << b << " maxVD=" << maxVD << " tt=" << travelTime
7044  // << " ta=" << timeLossAccel << " td=" << timeLossDecel << " tl=" << timeLossLength << " res=" << result << "\n";
7045  return MAX2(0.0, result);
7046  } else {
7047  return INVALID_DOUBLE;
7048  }
7049 }
7050 
7051 double
7053  if (hasStops() && myStops.front().pars.until >= 0) {
7054  const MSStop& stop = myStops.front();
7055  SUMOTime estimatedDepart = MSNet::getInstance()->getCurrentTimeStep() - DELTA_T;
7056  if (stop.reached) {
7057  return STEPS2TIME(estimatedDepart + stop.duration - stop.pars.until);
7058  }
7059  if (stop.pars.duration > 0) {
7060  estimatedDepart += stop.pars.duration;
7061  }
7062  estimatedDepart += TIME2STEPS(estimateTimeToNextStop());
7063  const double result = MAX2(0.0, STEPS2TIME(estimatedDepart - stop.pars.until));
7064  return result;
7065  } else {
7066  // vehicles cannot drive before 'until' so stop delay can never be
7067  // negative and we can use -1 to signal "undefined"
7068  return -1;
7069  }
7070 }
7071 
7072 double
7074  if (hasStops() && myStops.front().pars.arrival >= 0) {
7075  const MSStop& stop = myStops.front();
7076  if (stop.reached) {
7077  return STEPS2TIME(stop.pars.started - stop.pars.arrival);
7078  } else {
7079  return STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()) + estimateTimeToNextStop() - STEPS2TIME(stop.pars.arrival);
7080  }
7081  } else {
7082  // vehicles can arrival earlier than planned so arrival delay can be negative
7083  return INVALID_DOUBLE;
7084  }
7085 }
7086 
7087 /****************************************************************************/
#define DEG2RAD(x)
Definition: GeomHelper.h:35
#define RAD2DEG(x)
Definition: GeomHelper.h:36
std::vector< const MSEdge * > ConstMSEdgeVector
Definition: MSEdge.h:74
std::vector< MSEdge * > MSEdgeVector
Definition: MSEdge.h:73
std::pair< const MSVehicle *, double > CLeaderDist
Definition: MSLeaderInfo.h:32
std::pair< const MSPerson *, double > PersonDist
Definition: MSPModel.h:39
ConstMSEdgeVector::const_iterator MSRouteIterator
Definition: MSRoute.h:54
#define NUMERICAL_EPS_SPEED
Definition: MSVehicle.cpp:118
#define STOPPING_PLACE_OFFSET
Definition: MSVehicle.cpp:109
#define JUNCTION_BLOCKAGE_TIME
Definition: MSVehicle.cpp:113
#define DEBUG_COND
Definition: MSVehicle.cpp:103
#define DIST_TO_STOPLINE_EXPECT_PRIORITY
Definition: MSVehicle.cpp:116
#define DEBUG_COND2(obj)
Definition: MSVehicle.cpp:105
#define CRLL_LOOK_AHEAD
Definition: MSVehicle.cpp:111
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:281
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:288
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:280
SUMOTime DELTA_T
Definition: SUMOTime.cpp:37
std::string time2string(SUMOTime t)
convert SUMOTime to string
Definition: SUMOTime.cpp:68
#define STEPS2TIME(x)
Definition: SUMOTime.h:53
#define SPEED2DIST(x)
Definition: SUMOTime.h:43
#define SIMSTEP
Definition: SUMOTime.h:59
#define ACCEL2SPEED(x)
Definition: SUMOTime.h:49
#define SUMOTime_MAX
Definition: SUMOTime.h:33
#define TS
Definition: SUMOTime.h:40
#define SIMTIME
Definition: SUMOTime.h:60
#define TIME2STEPS(x)
Definition: SUMOTime.h:55
#define DIST2SPEED(x)
Definition: SUMOTime.h:45
long long int SUMOTime
Definition: SUMOTime.h:32
#define SPEED2ACCEL(x)
Definition: SUMOTime.h:51
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission is a railway edge.
@ SVC_RAIL_CLASSES
classes which drive on tracks
@ SVC_EMERGENCY
public emergency vehicles
@ RAIL_CARGO
render as a cargo train
@ RAIL
render as a rail
@ PASSENGER_VAN
render as a van
@ PASSENGER
render as a passenger vehicle
@ RAIL_CAR
render as a (city) rail without locomotive
@ PASSENGER_HATCHBACK
render as a hatchback passenger vehicle ("Fliessheck")
@ BUS_FLEXIBLE
render as a flexible city bus
@ TRUCK_1TRAILER
render as a transport vehicle with one trailer
@ PASSENGER_SEDAN
render as a sedan passenger vehicle ("Stufenheck")
@ PASSENGER_WAGON
render as a wagon passenger vehicle ("Combi")
@ TRUCK_SEMITRAILER
render as a semi-trailer transport vehicle ("Sattelschlepper")
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
@ GIVEN
The lane is given.
@ GIVEN
The speed is given.
@ GIVEN
The arrival lane is given.
@ GIVEN
The speed is given.
const int VEHPARS_FORCE_REROUTE
const int STOP_ENDED_SET
@ GIVEN
The arrival position is given.
const int STOP_STARTED_SET
@ SUMO_TAG_PARKING_AREA_REROUTE
entry for an alternative parking zone
@ SUMO_TAG_PARKING_AREA
A parking area.
@ SUMO_TAG_OVERHEAD_WIRE_SEGMENT
An overhead wire segment.
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)....
@ PARTLEFT
The link is a partial left direction.
@ RIGHT
The link is a (hard) right direction.
@ TURN
The link is a 180 degree turn.
@ LEFT
The link is a (hard) left direction.
@ STRAIGHT
The link is a straight direction.
@ TURN_LEFTHAND
The link is a 180 degree turn (left-hand network)
@ PARTRIGHT
The link is a partial right direction.
@ NODIR
The link has no direction (is a dead end link)
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic,...
@ LINKSTATE_ALLWAY_STOP
This is an uncontrolled, all-way stop link.
@ LINKSTATE_EQUAL
This is an uncontrolled, right-before-left link.
@ LINKSTATE_ZIPPER
This is an uncontrolled, zipper-merge link.
@ LCA_KEEPRIGHT
The action is due to the default of keeping right "Rechtsfahrgebot".
@ LCA_BLOCKED
blocked in all directions
@ LCA_URGENT
The action is urgent (to be defined by lc-model)
@ LCA_STAY
Needs to stay on the current lane.
@ LCA_SUBLANE
used by the sublane model
@ LCA_WANTS_LANECHANGE_OR_STAY
lane can change or stay
@ LCA_COOPERATIVE
The action is done to help someone else.
@ LCA_OVERLAPPING
The vehicle is blocked being overlapping.
@ LCA_LEFT
Wants go to the left.
@ LCA_STRATEGIC
The action is needed to follow the route (navigational lc)
@ LCA_TRACI
The action is due to a TraCI request.
@ LCA_SPEEDGAIN
The action is due to the wish to be faster (tactical lc)
@ LCA_RIGHT
Wants go to the right.
@ SUMO_ATTR_JM_IGNORE_KEEPCLEAR_TIME
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_STARTED
@ SUMO_ATTR_MAXIMUMPOWER
Maximum Power.
@ SUMO_ATTR_WAITINGTIME
@ SUMO_ATTR_JM_STOPLINE_GAP
@ SUMO_ATTR_POSITION_LAT
@ SUMO_ATTR_JM_DRIVE_AFTER_RED_TIME
@ SUMO_ATTR_JM_DRIVE_AFTER_YELLOW_TIME
@ SUMO_ATTR_ENDED
@ SUMO_ATTR_ANGLE
@ SUMO_ATTR_DISTANCE
@ SUMO_ATTR_JM_IGNORE_JUNCTION_FOE_PROB
@ SUMO_ATTR_POSITION
@ SUMO_ATTR_STATE
The state of a link.
@ SUMO_ATTR_JM_DRIVE_RED_SPEED
int gPrecision
the precision for floating point outputs
Definition: StdDefs.cpp:25
bool gDebugFlag1
global utility flags for debugging
Definition: StdDefs.cpp:32
const double INVALID_DOUBLE
Definition: StdDefs.h:63
const double SUMO_const_laneWidth
Definition: StdDefs.h:48
T MIN2(T a, T b)
Definition: StdDefs.h:74
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition: StdDefs.h:61
T MAX2(T a, T b)
Definition: StdDefs.h:80
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
#define SOFT_ASSERT(expr)
define SOFT_ASSERT raise an assertion in debug mode everywhere except on the windows test server
static double naviDegree(const double angle)
Definition: GeomHelper.cpp:192
static double fromNaviDegree(const double angle)
Definition: GeomHelper.cpp:209
Interface for lane-change models.
double getLaneChangeCompletion() const
Get the current lane change completion ratio.
const std::vector< double > & getShadowFurtherLanesPosLat() const
double getManeuverDist() const
Returns the remaining unblocked distance for the current maneuver. (only used by sublane model)
int getLaneChangeDirection() const
return the direction of the current lane change maneuver
void resetChanged()
reset the flag whether a vehicle already moved to false
MSLane * getShadowLane() const
Returns the lane the vehicle's shadow is on during continuous/sublane lane change.
void endLaneChangeManeuver(const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_LANE_CHANGE)
const std::vector< MSLane * > & getShadowFurtherLanes() const
void setNoShadowPartialOccupator(MSLane *lane)
SUMOTime remainingTime() const
Compute the remaining time until LC completion.
void setShadowApproachingInformation(MSLink *link) const
set approach information for the shadow vehicle
const std::vector< MSLane * > & getFurtherTargetLanes() const
static MSAbstractLaneChangeModel * build(LaneChangeModel lcm, MSVehicle &vehicle)
Factory method for instantiating new lane changing models.
void changedToOpposite()
called when a vehicle changes between lanes in opposite directions
int getShadowDirection() const
return the direction in which the current shadow lane lies
MSLane * getTargetLane() const
Returns the lane the vehicle has committed to enter during a sublane lane change.
double getAngleOffset() const
return the angle offset during a continuous change maneuver
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT(const int rngIndex, SUMOVehicleClass svc) const
The base class for microscopic and mesoscopic vehicles.
Definition: MSBaseVehicle.h:51
double getMaxSpeed() const
Returns the maximum speed.
MSVehicleDevice * getDevice(const std::type_info &type) const
Returns a device of the given type if it exists or 0.
virtual bool isSelected() const
whether this vehicle is selected in the GUI
std::list< MSStop > myStops
The vehicle's list of stops.
double getImpatience() const
Returns this vehicles impatience.
const std::vector< MSTransportable * > & getPersons() const
retrieve riding persons
virtual void initDevices()
void calculateArrivalParams(bool onInit)
(Re-)Calculates the arrival position and lane from the vehicle parameters
virtual double getArrivalPos() const
Returns this vehicle's desired arrivalPos for its current route (may change on reroute)
MSVehicleType * myType
This vehicle's type.
MoveReminderCont myMoveReminders
Currently relevant move reminders.
double myDepartPos
The real depart position.
const std::list< MSStop > & getStops() const
const SUMOVehicleParameter & getParameter() const
Returns the vehicle's parameter (including departure definition)
void addReminder(MSMoveReminder *rem)
Adds a MoveReminder dynamically.
void replaceParameter(const SUMOVehicleParameter *newParameter)
replace the vehicle parameter (deleting the old one)
std::vector< MSVehicleDevice * > myDevices
The devices this vehicle has.
virtual void addTransportable(MSTransportable *transportable)
Adds a person or container to this vehicle.
MSVehicleType & getSingularType()
Replaces the current vehicle type with a new one used by this vehicle only.
virtual void replaceVehicleType(MSVehicleType *type)
Replaces the current vehicle type by the one given.
double getLength() const
Returns the vehicle's length.
bool isParking() const
Returns whether the vehicle is parking.
const MSEdge * getEdge() const
Returns the edge the vehicle is currently at.
int getPersonNumber() const
Returns the number of persons.
MSRouteIterator myCurrEdge
Iterator to current route-edge.
bool hasDeparted() const
Returns whether this vehicle has already departed.
MSStop & getNextStop()
double getWidth() const
Returns the vehicle's width.
MSDevice_Transportable * myContainerDevice
The containers this vehicle may have.
SumoRNG * getRNG() const
SUMOTime getDeparture() const
Returns this vehicle's real departure time.
MSDevice_Transportable * myPersonDevice
The passengers this vehicle may have.
const MSRoute * myRoute
This vehicle's route.
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
bool hasStops() const
Returns whether the vehicle has to stop somewhere.
@ ROUTE_START_INVALID_LANE
Definition: MSBaseVehicle.h:74
@ ROUTE_START_INVALID_PERMISSIONS
Definition: MSBaseVehicle.h:72
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
virtual bool replaceRoute(const MSRoute *route, const std::string &info, bool onInit=false, int offset=0, bool addStops=true, bool removeStops=true, std::string *msgReturn=nullptr)
Replaces the current route by the given one.
int myArrivalLane
The destination lane where the vehicle stops.
SUMOTime myDeparture
The real departure time.
bool isStoppedTriggered() const
Returns whether the vehicle is on a triggered stop.
std::vector< SUMOVehicleParameter::Stop > myPastStops
The list of stops that the vehicle has already reached.
void onDepart()
Called when the vehicle is inserted into the network.
bool haveValidStopEdges() const
check whether all stop.edge MSRouteIterators are valid and in order
virtual bool addTraciStop(SUMOVehicleParameter::Stop stop, std::string &errorMsg)
int getRoutePosition() const
return index of edge within route
static const SUMOTime NOT_YET_DEPARTED
const SUMOVehicleParameter * myParameter
This vehicle's parameter.
int myRouteValidity
status of the current vehicle route
const MSRoute & getRoute() const
Returns the current route.
int getRNGIndex() const
bool isStopped() const
Returns whether the vehicle is at a stop.
int myNumberReroutes
The number of reroutings.
double myArrivalPos
The position on the destination lane where the vehicle stops.
virtual void saveState(OutputDevice &out)
Saves the (common) state of a vehicle.
double myOdometer
A simple odometer to keep track of the length of the route already driven.
int getContainerNumber() const
Returns the number of containers.
bool replaceRouteEdges(ConstMSEdgeVector &edges, double cost, double savings, const std::string &info, bool onInit=false, bool check=false, bool removeStops=true, std::string *msgReturn=nullptr)
Replaces the current route by the given edges.
The car-following model abstraction.
Definition: MSCFModel.h:55
double estimateSpeedAfterDistance(const double dist, const double v, const double accel) const
Definition: MSCFModel.cpp:707
virtual double maxNextSpeed(double speed, const MSVehicle *const veh) const
Returns the maximum speed given the current speed.
Definition: MSCFModel.cpp:237
double stopSpeed(const MSVehicle *const veh, const double speed, double gap) const
Computes the vehicle's safe speed for approaching a non-moving obstacle (no dawdling)
Definition: MSCFModel.h:146
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:254
double maximumSafeStopSpeed(double gap, double decel, double currentSpeed, bool onInsertion=false, double headway=-1) const
Returns the maximum next velocity for stopping within gap.
Definition: MSCFModel.cpp:716
double getEmergencyDecel() const
Get the vehicle type's maximal phisically possible deceleration [m/s^2].
Definition: MSCFModel.h:247
double getMinimalArrivalSpeed(double dist, double currentSpeed) const
Computes the minimal possible arrival speed after covering a given distance.
Definition: MSCFModel.cpp:480
virtual void setHeadwayTime(double headwayTime)
Sets a new value for desired headway [s].
Definition: MSCFModel.h:529
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:243
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:373
virtual double brakeGap(const double speed) const
Returns the distance the vehicle needs to halt including driver's reaction time tau (i....
Definition: MSCFModel.h:334
virtual double finalizeSpeed(MSVehicle *const veh, double vPos) const
Applies interaction with stops and lane changing model influences. Called at most once per simulation...
Definition: MSCFModel.cpp:163
virtual double freeSpeed(const MSVehicle *const veh, double speed, double seen, double maxSpeed, const bool onInsertion=false) const
Computes the vehicle's safe speed without a leader.
Definition: MSCFModel.cpp:266
virtual VehicleVariables * createVehicleVariables() const
Returns model specific values which are stored inside a vehicle and must be used with casting.
Definition: MSCFModel.h:222
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's follow speed (no dawdling)
virtual double maximumLaneSpeedCF(double maxSpeed, double maxSpeedLane) const
Returns the maximum velocity the CF-model wants to achieve in the next step.
Definition: MSCFModel.h:201
double getApparentDecel() const
Get the vehicle type's apparent deceleration [m/s^2] (the one regarded by its followers.
Definition: MSCFModel.h:255
double getMaxAccel() const
Get the vehicle type's maximum acceleration [m/s^2].
Definition: MSCFModel.h:231
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
Definition: MSCFModel.h:239
double getMinimalArrivalSpeedEuler(double dist, double currentSpeed) const
Computes the minimal possible arrival speed after covering a given distance for Euler update.
Definition: MSCFModel.cpp:487
virtual double getHeadwayTime() const
Get the driver's desired headway [s].
Definition: MSCFModel.h:280
The ToC Device controls transition of control between automated and manual driving.
std::shared_ptr< MSSimpleDriverState > getDriverState() const
return internal state
void update()
update internal state
A device which collects info on the vehicle trip (mainly on departure and arrival)
double consumption(SUMOVehicle &veh, double a, double newSpeed)
return energy consumption in Wh (power multiplied by TS)
double getParameterDouble(const std::string &key) const
void setConsum(const double consumption)
double acceleration(SUMOVehicle &veh, double power, double oldSpeed)
double getConsum() const
Get consum.
bool notifyMove(SUMOTrafficObject &veh, double oldPos, double newPos, double newSpeed)
Checks whether the vehicle is at a stop and transportable action is needed.
A device which collects info on the vehicle trip (mainly on departure and arrival)
void stopEnded(const SUMOVehicleParameter::Stop &stop)
void checkCollisionForInactive(MSLane *l)
trigger collision checking for inactive lane
A road/street connecting two junctions.
Definition: MSEdge.h:77
const MSEdge * getInternalFollowingEdge(const MSEdge *followerAfterInternal) const
Definition: MSEdge.cpp:761
const MSEdge * getOppositeEdge() const
Returns the opposite direction edge if on exists else a nullptr.
Definition: MSEdge.cpp:1163
bool isFringe() const
return whether this edge is at the fringe of the network
Definition: MSEdge.h:722
const std::set< MSTransportable * > & getPersons() const
Returns this edge's persons set.
Definition: MSEdge.h:198
bool isNormal() const
return whether this edge is an internal edge
Definition: MSEdge.h:257
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:408
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:168
double getSpeedLimit() const
Returns the speed limit of the edge @caution The speed limit of the first lane is retured; should pro...
Definition: MSEdge.cpp:990
const MSJunction * getFromJunction() const
Definition: MSEdge.h:397
double getMinimumTravelTime(const SUMOVehicle *const veh) const
returns the minimum travel time for the given vehicle
Definition: MSEdge.h:459
bool isRoundabout() const
Definition: MSEdge.h:685
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:262
double getWidth() const
Returns the edges's width (sum over all lanes)
Definition: MSEdge.h:612
bool isVaporizing() const
Returns whether vehicles on this edge shall be vaporized.
Definition: MSEdge.h:417
void addWaiting(SUMOVehicle *vehicle) const
Adds a vehicle to the list of waiting vehicles.
Definition: MSEdge.cpp:1230
const MSJunction * getToJunction() const
Definition: MSEdge.h:401
void removeWaiting(const SUMOVehicle *vehicle) const
Removes a vehicle from the list of waiting vehicles.
Definition: MSEdge.cpp:1239
const MSEdge * getBidiEdge() const
return opposite superposable/congruent edge, if it exist and 0 else
Definition: MSEdge.h:276
const MSEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition: MSEdge.cpp:1084
static bool gModelParkingManoeuver
whether parking simulation includes manoeuver time and any associated lane blocking
Definition: MSGlobals.h:145
static bool gUseMesoSim
Definition: MSGlobals.h:94
static double gTLSYellowMinDecel
The minimum deceleration at a yellow traffic light (only overruled by emergencyDecel)
Definition: MSGlobals.h:154
static double gLateralResolution
Definition: MSGlobals.h:88
static bool gSemiImplicitEulerUpdate
Definition: MSGlobals.h:53
static bool gLefthand
Whether lefthand-drive is being simulated.
Definition: MSGlobals.h:157
static bool gSublane
whether sublane simulation is enabled (sublane model or continuous lanechanging)
Definition: MSGlobals.h:148
static SUMOTime gLaneChangeDuration
Definition: MSGlobals.h:85
static bool gUseStopEnded
whether the simulation should replay previous stop times
Definition: MSGlobals.h:121
static double gEmergencyDecelWarningThreshold
treshold for warning about strong deceleration
Definition: MSGlobals.h:139
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:72
void add(SUMOVehicle *veh)
Adds a single vehicle for departure.
virtual const MSJunctionLogic * getLogic() const
Definition: MSJunction.h:138
virtual const MSLogicJunction::LinkBits & getResponseFor(int linkIndex) const
Returns the response for the given link.
Representation of a lane in the micro simulation.
Definition: MSLane.h:82
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.h:641
MSLane * getParallelLane(int offset, bool includeOpposite=true) const
Returns the lane with the given offset parallel to this one or 0 if it does not exist.
Definition: MSLane.cpp:2300
virtual MSVehicle * removeVehicle(MSVehicle *remVehicle, MSMoveReminder::Notification notification, bool notify=true)
Definition: MSLane.cpp:2282
int getVehicleNumber() const
Returns the number of vehicles on this lane (for which this lane is responsible)
Definition: MSLane.h:401
MSVehicle * getFirstAnyVehicle() const
returns the first vehicle that is fully or partially on this lane
Definition: MSLane.cpp:2151
const MSLink * getEntryLink() const
Returns the entry link if this is an internal lane, else nullptr.
Definition: MSLane.cpp:2237
int getVehicleNumberWithPartials() const
Returns the number of vehicles on this lane (including partial occupators)
Definition: MSLane.h:409
double getBruttoVehLenSum() const
Returns the sum of lengths of vehicles, including their minGaps, which were on the lane during the la...
Definition: MSLane.h:1031
static std::vector< MSLink * >::const_iterator succLinkSec(const SUMOVehicle &veh, int nRouteSuccs, const MSLane &succLinkSource, const std::vector< MSLane * > &conts)
Definition: MSLane.cpp:2165
std::pair< const MSPerson *, double > nextBlocking(double minPos, double minRight, double maxLeft, double stopTime=0) const
This is just a wrapper around MSPModel::nextBlocking. You should always check using hasPedestrians be...
Definition: MSLane.cpp:3978
virtual const VehCont & getVehiclesSecure() const
Returns the vehicles container; locks it for microsimulation.
Definition: MSLane.h:428
const MSLink * getLinkTo(const MSLane *const) const
returns the link to the given lane or nullptr, if it is not connected
Definition: MSLane.cpp:2214
void forceVehicleInsertion(MSVehicle *veh, double pos, MSMoveReminder::Notification notification, double posLat=0)
Inserts the given vehicle at the given position.
Definition: MSLane.cpp:1102
double getVehicleStopOffset(const MSVehicle *veh) const
Returns vehicle class specific stopOffset for the vehicle.
Definition: MSLane.cpp:3250
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition: MSLane.h:533
std::vector< MSVehicle * > VehCont
Container for vehicles.
Definition: MSLane.h:92
std::pair< MSVehicle *const, double > getFollower(const MSVehicle *ego, double egoPos, double dist, bool ignoreMinorLinks) const
Find follower vehicle for the given ego vehicle (which may be on the opposite direction lane)
Definition: MSLane.cpp:3822
std::vector< StopWatch< std::chrono::nanoseconds > > & getStopWatch()
Definition: MSLane.h:1185
const MSEdge * getNextNormal() const
Returns the lane's follower if it is an internal lane, the edge of the lane otherwise.
Definition: MSLane.cpp:1967
double getLength() const
Returns the lane's length.
Definition: MSLane.h:541
double getMaximumBrakeDist() const
compute maximum braking distance on this lane
Definition: MSLane.cpp:2357
const MSLane * getInternalFollowingLane(const MSLane *const) const
returns the internal lane leading to the given lane or nullptr, if there is none
Definition: MSLane.cpp:2226
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:1142
bool isLinkEnd(std::vector< MSLink * >::const_iterator &i) const
Definition: MSLane.h:763
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition: MSLane.h:814
virtual double setPartialOccupation(MSVehicle *v)
Sets the information about a vehicle lapping into this lane.
Definition: MSLane.cpp:277
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the lane's maximum speed, given a vehicle's speed limit adaptation.
Definition: MSLane.h:519
double getRightSideOnEdge() const
Definition: MSLane.h:1094
bool hasPedestrians() const
whether the lane has pedestrians on it
Definition: MSLane.cpp:3971
int getIndex() const
Returns the lane's index.
Definition: MSLane.h:563
const std::vector< IncomingLaneInfo > & getIncomingLanes() const
Definition: MSLane.h:837
double getOppositePos(double pos) const
return the corresponding position on the opposite lane
Definition: MSLane.cpp:3817
MSLane * getLogicalPredecessorLane() const
get the most likely precedecessor lane (sorted using by_connections_to_sorter). The result is cached ...
Definition: MSLane.cpp:2637
double getCenterOnEdge() const
Definition: MSLane.h:1102
MSLeaderDistanceInfo getFollowersOnConsecutive(const MSVehicle *ego, double backOffset, bool allSublanes, double searchDist=-1, bool ignoreMinorLinks=false) const
return the sublane followers with the largest missing rear gap among all predecessor lanes (within di...
Definition: MSLane.cpp:3275
MSVehicle * getLastAnyVehicle() const
returns the last vehicle that is fully or partially on this lane
Definition: MSLane.cpp:2137
bool isInternal() const
Definition: MSLane.cpp:2122
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:674
const PositionVector & getShape() const
Returns this lane's shape.
Definition: MSLane.h:478
MSLane * getOpposite() const
return the neighboring opposite direction lane for lane changing or nullptr
Definition: MSLane.cpp:3802
virtual void releaseVehicles() const
Allows to use the container for microsimulation again.
Definition: MSLane.h:458
bool mustCheckJunctionCollisions() const
whether this lane must check for junction collisions
Definition: MSLane.cpp:4064
double interpolateLanePosToGeometryPos(double lanePos) const
Definition: MSLane.h:499
MSLane * getBidiLane() const
retrieve bidirectional lane or nullptr
Definition: MSLane.cpp:4051
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:2433
@ COLLISION_ACTION_WARN
Definition: MSLane.h:176
MSLane * getParallelOpposite() const
return the opposite direction lane of this lanes edge or nullptr
Definition: MSLane.cpp:3811
double getSpaceTillLastStanding(const MSVehicle *ego, bool &foundStopped) const
return the empty space up to the last standing vehicle or the empty space on the whole lane if no veh...
Definition: MSLane.cpp:4070
const MSLane * getNormalPredecessorLane() const
get normal lane leading to this internal lane, for normal lanes, the lane itself is returned
Definition: MSLane.cpp:2662
const std::vector< MSMoveReminder * > & getMoveReminders() const
Return the list of this lane's move reminders.
Definition: MSLane.h:268
double getWidth() const
Returns the lane's width.
Definition: MSLane.h:556
const Position geometryPositionAtOffset(double offset, double lateralOffset=0) const
Definition: MSLane.h:505
static CollisionAction getCollisionAction()
Definition: MSLane.h:1252
saves leader/follower vehicles and their distances relative to an ego vehicle
Definition: MSLeaderInfo.h:133
virtual std::string toString() const
print a debugging representation
void fixOppositeGaps(bool isFollower)
subtract vehicle length from all gaps if the leader vehicle is driving in the opposite direction
virtual int addLeader(const MSVehicle *veh, double gap, double latOffset=0, int sublane=-1)
virtual int addLeader(const MSVehicle *veh, bool beyond, double latOffset=0)
void removeOpposite(const MSLane *lane)
remove vehicles that are driving in the opposite direction (fully or partially) on the given lane
int numSublanes() const
Definition: MSLeaderInfo.h:85
virtual std::string toString() const
print a debugging representation
virtual void clear()
discard all information
void getSubLanes(const MSVehicle *veh, double latOffset, int &rightmost, int &leftmost) const
Something on a lane to be noticed about vehicle movement.
Notification
Definition of a vehicle state.
@ NOTIFICATION_TELEPORT_ARRIVED
The vehicle was teleported out of the net.
@ NOTIFICATION_PARKING_REROUTE
The vehicle needs another parking area.
@ NOTIFICATION_DEPARTED
The vehicle has departed (was inserted into the network)
@ NOTIFICATION_LANE_CHANGE
The vehicle changes lanes (micro only)
@ NOTIFICATION_VAPORIZED_VAPORIZER
The vehicle got vaporized with a vaporizer.
@ NOTIFICATION_JUNCTION
The vehicle arrived at a junction.
@ NOTIFICATION_PARKING
The vehicle starts or ends parking.
@ NOTIFICATION_LOAD_STATE
The vehicle has been loaded from a state file.
@ NOTIFICATION_TELEPORT
The vehicle is being teleported.
Interface for objects listening to vehicle state changes.
Definition: MSNet.h:627
The simulated network and simulation perfomer.
Definition: MSNet.h:88
void removeVehicleStateListener(VehicleStateListener *listener)
Removes a vehicle states listener.
Definition: MSNet.cpp:1135
VehicleState
Definition of a vehicle state.
Definition: MSNet.h:594
@ STARTING_STOP
The vehicles starts to stop.
@ STARTING_PARKING
The vehicles starts to park.
@ STARTING_TELEPORT
The vehicle started to teleport.
@ ENDING_STOP
The vehicle ends to stop.
@ ARRIVED
The vehicle arrived at his destination (is deleted)
@ EMERGENCYSTOP
The vehicle had to brake harder than permitted.
@ MANEUVERING
Vehicle maneuvering either entering or exiting a parking space.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:174
virtual MSTransportableControl & getContainerControl()
Returns the container control.
Definition: MSNet.cpp:1068
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:376
std::string getStoppingPlaceID(const MSLane *lane, const double pos, const SumoXMLTag category) const
Returns the stop of the given category close to the given position.
Definition: MSNet.cpp:1259
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:318
static bool hasInstance()
Returns whether the network was already constructed.
Definition: MSNet.h:154
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition: MSNet.cpp:1250
void addVehicleStateListener(VehicleStateListener *listener)
Adds a vehicle states listener.
Definition: MSNet.cpp:1127
MSEdgeControl & getEdgeControl()
Returns the edge control.
Definition: MSNet.h:419
bool hasContainers() const
Returns whether containers are simulated.
Definition: MSNet.h:409
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition: MSNet.h:429
void informVehicleStateListener(const SUMOVehicle *const vehicle, VehicleState to, const std::string &info="")
Informs all added listeners about a vehicle's state change.
Definition: MSNet.cpp:1144
bool hasPersons() const
Returns whether persons are simulated.
Definition: MSNet.h:393
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition: MSNet.cpp:1059
A lane area vehicles can halt at.
Definition: MSParkingArea.h:58
int getCapacity() const
Returns the area capacity.
void enter(SUMOVehicle *veh)
Called if a vehicle enters this stop.
int getLotIndex(const SUMOVehicle *veh) const
compute lot for this vehicle
int getLastFreeLotAngle() const
Return the angle of myLastFreeLot - the next parking lot only expected to be called after we have est...
bool parkOnRoad() const
whether vehicles park on the road
int getOccupancyIncludingBlocked() const
Returns the area occupancy.
double getLastFreePosWithReservation(SUMOTime t, const SUMOVehicle &forVehicle, double brakePos)
Returns the last free position on this stop including reservatiosn from the current lane and time ste...
double getLastFreeLotGUIAngle() const
Return the GUI angle of myLastFreeLot - the angle the GUI uses to rotate into the next parking lot as...
int getManoeuverAngle(const SUMOVehicle &forVehicle) const
Return the manoeuver angle of the lot where the vehicle is parked.
int getOccupancy() const
Returns the area occupancy.
double getGUIAngle(const SUMOVehicle &forVehicle) const
Return the GUI angle of the lot where the vehicle is parked.
MSRouteIterator end() const
Returns the end of the list of edges to pass.
Definition: MSRoute.cpp:75
const MSEdge * getLastEdge() const
returns the destination edge
Definition: MSRoute.cpp:87
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:291
MSRouteIterator begin() const
Returns the begin of the list of edges to pass.
Definition: MSRoute.cpp:69
const ConstMSEdgeVector & getEdges() const
Definition: MSRoute.h:120
Definition: MSStop.h:44
const MSLane * lane
The lane to stop at (microsim only)
Definition: MSStop.h:50
bool triggered
whether an arriving person lets the vehicle continue
Definition: MSStop.h:69
bool containerTriggered
whether an arriving container lets the vehicle continue
Definition: MSStop.h:71
SUMOTime timeToLoadNextContainer
The time at which the vehicle is able to load another container.
Definition: MSStop.h:83
MSStoppingPlace * containerstop
(Optional) container stop if one is assigned to the stop
Definition: MSStop.h:56
bool joinTriggered
whether coupling another vehicle (train) the vehicle continue
Definition: MSStop.h:73
bool isOpposite
whether this an opposite-direction stop
Definition: MSStop.h:89
int numExpectedContainer
The number of still expected containers.
Definition: MSStop.h:79
bool reached
Information whether the stop has been reached.
Definition: MSStop.h:75
MSRouteIterator edge
The edge in the route to stop at.
Definition: MSStop.h:48
SUMOTime timeToBoardNextPerson
The time at which the vehicle is able to board another person.
Definition: MSStop.h:81
double getReachedThreshold() const
return startPos taking into account opposite stopping
Definition: MSStop.cpp:61
SUMOTime endBoarding
the maximum time at which persons may board this vehicle
Definition: MSStop.h:87
double getEndPos(const SUMOVehicle &veh) const
return halting position for upcoming stop;
Definition: MSStop.cpp:34
int numExpectedPerson
The number of still expected persons.
Definition: MSStop.h:77
MSParkingArea * parkingarea
(Optional) parkingArea if one is assigned to the stop
Definition: MSStop.h:58
MSStoppingPlace * chargingStation
(Optional) charging station if one is assigned to the stop
Definition: MSStop.h:60
SUMOTime duration
The stopping duration.
Definition: MSStop.h:67
const SUMOVehicleParameter::Stop pars
The stop parameter.
Definition: MSStop.h:65
MSStoppingPlace * busstop
(Optional) bus stop if one is assigned to the stop
Definition: MSStop.h:54
static MSStopOut * getInstance()
Definition: MSStopOut.h:60
static bool active()
Definition: MSStopOut.h:54
void stopStarted(const SUMOVehicle *veh, int numPersons, int numContainers, SUMOTime time)
Definition: MSStopOut.cpp:66
void stopEnded(const SUMOVehicle *veh, const SUMOVehicleParameter::Stop &stop, const std::string &laneOrEdgeID, bool simEnd=false)
Definition: MSStopOut.cpp:102
A lane area vehicles can halt at.
double getBeginLanePosition() const
Returns the begin position of this stop.
bool fits(double pos, const SUMOVehicle &veh) const
return whether the given vehicle fits at the given position
double getEndLanePosition() const
Returns the end position of this stop.
void enter(SUMOVehicle *veh, bool parking)
Called if a vehicle enters this stop.
const MSLane & getLane() const
Returns the lane this stop is located at.
bool boardAnyWaiting(const MSEdge *edge, SUMOVehicle *vehicle, SUMOTime &timeToBoardNextPerson, SUMOTime &stopDuration)
board any applicable persons Boards any people who wait on that edge for the given vehicle and remove...
bool loadAnyWaiting(const MSEdge *edge, SUMOVehicle *vehicle, SUMOTime &timeToLoadNextContainer, SUMOTime &stopDuration)
load any applicable containers Loads any container that is waiting on that edge for the given vehicle...
bool isPerson() const
Whether it is a person.
A static instance of this class in GapControlState deactivates gap control for vehicles whose referen...
Definition: MSVehicle.h:1313
void vehicleStateChanged(const SUMOVehicle *const vehicle, MSNet::VehicleState to, const std::string &info="")
Called if a vehicle changes its state.
Definition: MSVehicle.cpp:258
Changes the wished vehicle speed / lanes.
Definition: MSVehicle.h:1308
void setLaneChangeMode(int value)
Sets lane changing behavior.
Definition: MSVehicle.cpp:778
TraciLaneChangePriority myTraciLaneChangePriority
flags for determining the priority of traci lane change requests
Definition: MSVehicle.h:1614
bool getEmergencyBrakeRedLight() const
Returns whether red lights shall be a reason to brake.
Definition: MSVehicle.h:1480
SUMOTime getLaneTimeLineEnd()
Definition: MSVehicle.cpp:467
void adaptLaneTimeLine(int indexShift)
Adapts lane timeline when moving to a new lane and the lane index changes.
Definition: MSVehicle.cpp:419
void setRemoteControlled(Position xyPos, MSLane *l, double pos, double posLat, double angle, int edgeOffset, const ConstMSEdgeVector &route, SUMOTime t)
Definition: MSVehicle.cpp:789
bool isRemoteAffected(SUMOTime t) const
Definition: MSVehicle.cpp:808
int getSpeedMode() const
return the current speed mode
Definition: MSVehicle.cpp:432
void deactivateGapController()
Deactivates the gap control.
Definition: MSVehicle.cpp:406
Influencer()
Constructor.
Definition: MSVehicle.cpp:357
void setSpeedMode(int speedMode)
Sets speed-constraining behaviors.
Definition: MSVehicle.cpp:767
std::shared_ptr< GapControlState > myGapControlState
The gap control state.
Definition: MSVehicle.h:1562
bool considerSafeVelocity() const
Returns whether safe velocities shall be considered.
Definition: MSVehicle.h:1494
int getSignals() const
Definition: MSVehicle.h:1538
bool myConsiderMaxDeceleration
Whether the maximum deceleration shall be regarded.
Definition: MSVehicle.h:1580
void setLaneTimeLine(const std::vector< std::pair< SUMOTime, int > > &laneTimeLine)
Sets a new lane timeline.
Definition: MSVehicle.cpp:413
bool myRespectJunctionLeaderPriority
Whether the junction priority rules are respected (within)
Definition: MSVehicle.h:1589
void setOriginalSpeed(double speed)
Stores the originally longitudinal speed.
Definition: MSVehicle.cpp:658
double myOriginalSpeed
The velocity before influence.
Definition: MSVehicle.h:1565
double implicitDeltaPosRemote(const MSVehicle *veh)
return the change in longitudinal position that is implicit in the new remote position
Definition: MSVehicle.cpp:896
double implicitSpeedRemote(const MSVehicle *veh, double oldSpeed)
return the speed that is implicit in the new remote position
Definition: MSVehicle.cpp:869
void postProcessRemoteControl(MSVehicle *v)
Definition: MSVehicle.cpp:813
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:506
void setSublaneChange(double latDist)
Sets a new sublane-change request.
Definition: MSVehicle.cpp:427
double getOriginalSpeed() const
Returns the originally longitudinal speed to use.
Definition: MSVehicle.cpp:653
SUMOTime myLastRemoteAccess
Definition: MSVehicle.h:1598
bool getRespectJunctionLeaderPriority() const
Returns whether junction priority rules within the junction shall be respected (concerns vehicles wit...
Definition: MSVehicle.h:1488
LaneChangeMode myStrategicLC
lane changing which is necessary to follow the current route
Definition: MSVehicle.h:1603
LaneChangeMode mySpeedGainLC
lane changing to travel with higher speed
Definition: MSVehicle.h:1607
static void init()
Static initalization.
Definition: MSVehicle.cpp:382
LaneChangeMode mySublaneLC
changing to the prefered lateral alignment
Definition: MSVehicle.h:1611
bool getRespectJunctionPriority() const
Returns whether junction priority rules shall be respected (concerns approaching vehicles outside the...
Definition: MSVehicle.h:1472
static void cleanup()
Static cleanup.
Definition: MSVehicle.cpp:387
int getLaneChangeMode() const
return the current lane change mode
Definition: MSVehicle.cpp:444
SUMOTime getLaneTimeLineDuration()
Definition: MSVehicle.cpp:454
double influenceSpeed(SUMOTime currentTime, double speed, double vSafe, double vMin, double vMax)
Applies stored velocity information on the speed to use.
Definition: MSVehicle.cpp:477
double changeRequestRemainingSeconds(const SUMOTime currentTime) const
Return the remaining number of seconds of the current laneTimeLine assuming one exists.
Definition: MSVehicle.cpp:759
bool myConsiderSafeVelocity
Whether the safe velocity shall be regarded.
Definition: MSVehicle.h:1574
bool mySpeedAdaptationStarted
Whether influencing the speed has already started.
Definition: MSVehicle.h:1571
~Influencer()
Destructor.
Definition: MSVehicle.cpp:379
void setSignals(int signals)
Definition: MSVehicle.h:1534
double myLatDist
The requested lateral change.
Definition: MSVehicle.h:1568
bool myEmergencyBrakeRedLight
Whether red lights are a reason to brake.
Definition: MSVehicle.h:1586
LaneChangeMode myRightDriveLC
changing to the rightmost lane
Definition: MSVehicle.h:1609
void setSpeedTimeLine(const std::vector< std::pair< SUMOTime, double > > &speedTimeLine)
Sets a new velocity timeline.
Definition: MSVehicle.cpp:392
SUMOTime getLastAccessTimeStep() const
Definition: MSVehicle.h:1518
bool myConsiderMaxAcceleration
Whether the maximum acceleration shall be regarded.
Definition: MSVehicle.h:1577
LaneChangeMode myCooperativeLC
lane changing with the intent to help other vehicles
Definition: MSVehicle.h:1605
bool isRemoteControlled() const
Definition: MSVehicle.cpp:802
bool myRespectJunctionPriority
Whether the junction priority rules are respected (approaching)
Definition: MSVehicle.h:1583
int influenceChangeDecision(const SUMOTime currentTime, const MSEdge &currentEdge, const int currentLaneIndex, int state)
Applies stored LaneChangeMode information and laneTimeLine.
Definition: MSVehicle.cpp:664
void activateGapController(double originalTau, double newTimeHeadway, double newSpaceHeadway, double duration, double changeRate, double maxDecel, MSVehicle *refVeh=nullptr)
Activates the gap control with the given parameters,.
Definition: MSVehicle.cpp:398
Container for manouevering time associated with stopping.
Definition: MSVehicle.h:1232
SUMOTime myManoeuvreCompleteTime
Time at which this manoeuvre should complete.
Definition: MSVehicle.h:1284
MSVehicle::ManoeuvreType getManoeuvreType() const
Accessor (get) for manoeuvre type.
Definition: MSVehicle.cpp:6815
std::string myManoeuvreStop
The name of the stop associated with the Manoeuvre - for debug output.
Definition: MSVehicle.h:1278
bool manoeuvreIsComplete() const
Check if any manoeuver is ongoing and whether the completion time is beyond currentTime.
Definition: MSVehicle.cpp:6949
bool configureExitManoeuvre(MSVehicle *veh)
Setup the myManoeuvre for exiting (Sets completion time and manoeuvre type)
Definition: MSVehicle.cpp:6868
void setManoeuvreType(const MSVehicle::ManoeuvreType mType)
Accessor (set) for manoeuvre type.
Definition: MSVehicle.cpp:6831
Manoeuvre & operator=(const Manoeuvre &manoeuvre)
Assignment operator.
Definition: MSVehicle.cpp:6790
Manoeuvre()
Constructor.
Definition: MSVehicle.cpp:6779
ManoeuvreType myManoeuvreType
Manoeuvre type - currently entry, exit or none.
Definition: MSVehicle.h:1287
double getGUIIncrement() const
Accessor for GUI rotation step when parking (radians)
Definition: MSVehicle.cpp:6810
SUMOTime myManoeuvreStartTime
Time at which the Manoeuvre for this stop started.
Definition: MSVehicle.h:1281
bool operator!=(const Manoeuvre &manoeuvre)
Operator !=.
Definition: MSVehicle.cpp:6800
bool entryManoeuvreIsComplete(MSVehicle *veh)
Configure an entry manoeuvre if nothing is configured - otherwise check if complete.
Definition: MSVehicle.cpp:6910
bool manoeuvreIsComplete(const ManoeuvreType checkType) const
Check if specific manoeuver is ongoing and whether the completion time is beyond currentTime.
Definition: MSVehicle.cpp:6935
bool configureEntryManoeuvre(MSVehicle *veh)
Setup the entry manoeuvre for this vehicle (Sets completion time and manoeuvre type)
Definition: MSVehicle.cpp:6837
Container that holds the vehicles driving state (position+speed).
Definition: MSVehicle.h:85
double myPosLat
the stored lateral position
Definition: MSVehicle.h:138
double myPreviousSpeed
the speed at the begin of the previous time step
Definition: MSVehicle.h:146
double myPos
the stored position
Definition: MSVehicle.h:132
bool operator!=(const State &state)
Operator !=.
Definition: MSVehicle.cpp:155
double myLastCoveredDist
Definition: MSVehicle.h:152
double mySpeed
the stored speed (should be >=0 at any time)
Definition: MSVehicle.h:135
State & operator=(const State &state)
Assignment operator.
Definition: MSVehicle.cpp:143
double pos() const
Position of this state.
Definition: MSVehicle.h:105
State(double pos, double speed, double posLat, double backPos)
Constructor.
Definition: MSVehicle.cpp:165
double myBackPos
the stored back position
Definition: MSVehicle.h:143
void passTime(SUMOTime dt, bool waiting)
Definition: MSVehicle.cpp:199
const std::string getState() const
Definition: MSVehicle.cpp:231
SUMOTime cumulatedWaitingTime(SUMOTime memory=-1) const
Definition: MSVehicle.cpp:177
void setState(const std::string &state)
Definition: MSVehicle.cpp:242
WaitingTimeCollector(SUMOTime memory=MSGlobals::gWaitingTimeMemory)
Constructor.
Definition: MSVehicle.cpp:173
void registerEmergencyStop()
register emergency stop
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
void registerStopEnded()
register emergency stop
void removeVType(const MSVehicleType *vehType)
void registerOneWaiting()
increases the count of vehicles waiting for a transport to allow recognition of person / container re...
void unregisterOneWaiting()
decreases the count of vehicles waiting for a transport to allow recognition of person / container re...
void registerStopStarted()
register emergency stop
Abstract in-vehicle device.
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:75
void setManoeuvreType(const MSVehicle::ManoeuvreType mType)
accessor function to myManoeuvre equivalent
Definition: MSVehicle.cpp:6826
TraciLaneChangePriority
modes for prioritizing traci lane change requests
Definition: MSVehicle.h:1110
@ LCP_NOOVERLAP
Definition: MSVehicle.h:1112
@ LCP_OPPORTUNISTIC
Definition: MSVehicle.h:1114
double getRightSideOnEdge(const MSLane *lane=0) const
Get the vehicle's lateral position on the edge of the given lane (or its current edge if lane == 0)
Definition: MSVehicle.cpp:5894
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:6449
void processLinkApproaches(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:3075
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:2854
void checkRewindLinkLanes(const double lengthsInFront, DriveItemVector &lfLinks) const
runs heuristic for keeping the intersection clear in case of downstream jamming
Definition: MSVehicle.cpp:4471
bool willStop() const
Returns whether the vehicle will stop on the current edge.
Definition: MSVehicle.cpp:1472
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:2983
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:2802
bool hasDriverState() const
Whether this vehicle is equipped with a MSDriverState.
Definition: MSVehicle.h:956
static int nextLinkPriority(const std::vector< MSLane * > &conts)
get a numerical value for the priority of the upcoming link
Definition: MSVehicle.cpp:5459
double getTimeGapOnLane() const
Returns the time gap in seconds to the leader of the vehicle on the same lane.
Definition: MSVehicle.cpp:5769
void updateBestLanes(bool forceRebuild=false, const MSLane *startLane=0)
computes the best lanes to use in order to continue the route
Definition: MSVehicle.cpp:5069
bool myAmIdling
Whether the vehicle is trying to enter the network (eg after parking so engine is running)
Definition: MSVehicle.h:1863
SUMOTime myWaitingTime
The time the vehicle waits (is not faster than 0.1m/s) in seconds.
Definition: MSVehicle.h:1802
double getStopDelay() const
Returns the public transport stop delay in seconds.
Definition: MSVehicle.cpp:7052
double computeAngle() const
compute the current vehicle angle
Definition: MSVehicle.cpp:1330
double myTimeLoss
the time loss in seconds due to driving with less than maximum speed
Definition: MSVehicle.h:1806
SUMOTime myLastActionTime
Action offset (actions are taken at time myActionOffset + N*getActionStepLength()) Initialized to 0,...
Definition: MSVehicle.h:1818
bool hasArrivedInternal(bool oppositeTransformed=true) const
Returns whether this vehicle has already arived (reached the arrivalPosition on its final edge) metho...
Definition: MSVehicle.cpp:1038
bool replaceParkingArea(MSParkingArea *parkingArea, std::string &errorMsg)
replace the current parking area stop with a new stop with merge duration
Definition: MSVehicle.cpp:1411
void boardTransportables(MSStop &stop)
board persons and load transportables at the given stop
Definition: MSVehicle.cpp:1767
const std::vector< const MSLane * > getUpcomingLanesUntil(double distance) const
Returns the upcoming (best followed by default 0) sequence of lanes to continue the route starting at...
Definition: MSVehicle.cpp:5525
bool isOnRoad() const
Returns the information whether the vehicle is on a road (is simulated)
Definition: MSVehicle.h:574
void adaptLaneEntering2MoveReminder(const MSLane &enteredLane)
Adapts the vehicle's entering of a new lane.
Definition: MSVehicle.cpp:1106
void addTransportable(MSTransportable *transportable)
Adds a person or container to this vehicle.
Definition: MSVehicle.cpp:5780
MSParkingArea * getNextParkingArea()
get the upcoming parking area stop or nullptr
Definition: MSVehicle.cpp:1448
SUMOTime myJunctionConflictEntryTime
Definition: MSVehicle.h:1887
PositionVector getBoundingPoly(double offset=0) const
get bounding polygon
Definition: MSVehicle.cpp:6166
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:5878
SUMOTime getWaitingTime() const
Returns the SUMOTime waited (speed was lesser than 0.1m/s)
Definition: MSVehicle.h:631
const std::vector< MSLane * > & getFurtherLanes() const
Definition: MSVehicle.h:792
void workOnMoveReminders(double oldPos, double newPos, double newSpeed)
Processes active move reminder.
Definition: MSVehicle.cpp:1062
void setPreviousSpeed(double prevspeed)
Sets the influenced previous speed.
Definition: MSVehicle.cpp:6756
bool isStoppedOnLane() const
Definition: MSVehicle.cpp:1477
double myAcceleration
The current acceleration after dawdling in m/s.
Definition: MSVehicle.h:1845
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:2713
const MSLane * getBackLane() const
Definition: MSVehicle.cpp:4267
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:4929
std::pair< double, LinkDirection > myNextTurn
the upcoming turn for the vehicle
Definition: MSVehicle.h:1849
double getBackPositionOnLane() const
Get the vehicle's position relative to its current lane.
Definition: MSVehicle.h:403
SUMOTime getArrivalTime(SUMOTime t, double seen, double v, double arrivalSpeed) const
Definition: MSVehicle.cpp:2694
double getAccumulatedWaitingSeconds() const
Returns the number of seconds waited (speed was lesser than 0.1m/s) within the last millisecs.
Definition: MSVehicle.h:662
bool isFrontOnLane(const MSLane *lane) const
Returns the information whether the front of the vehicle is on the given lane.
Definition: MSVehicle.cpp:4465
virtual ~MSVehicle()
Destructor.
Definition: MSVehicle.cpp:954
bool myAmRegisteredAsWaitingForPerson
Whether this vehicle is registered as waiting for a person (for deadlock-recognition)
Definition: MSVehicle.h:1866
bool stopsAt(MSStoppingPlace *stop) const
Returns whether the vehicle stops at the given stopping place.
Definition: MSVehicle.cpp:1874
void processLaneAdvances(std::vector< MSLane * > &passedLanes, std::string &emergencyReason)
This method checks if the vehicle has advanced over one or several lanes along its route and triggers...
Definition: MSVehicle.cpp:3749
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:5051
void setEmergencyBlueLight(SUMOTime currentTime)
sets the blue flashing light for emergency vehicles
Definition: MSVehicle.cpp:5858
bool isActionStep(SUMOTime t) const
Returns whether the next simulation step will be an action point for the vehicle.
Definition: MSVehicle.h:604
MSAbstractLaneChangeModel * myLaneChangeModel
Definition: MSVehicle.h:1825
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:1175
bool hasValidRouteStart(std::string &msg)
checks wether the vehicle can depart on the first edge
Definition: MSVehicle.cpp:1000
std::vector< MSLane * > myFurtherLanes
The information into which lanes the vehicle laps into.
Definition: MSVehicle.h:1852
bool signalSet(int which) const
Returns whether the given signal is on.
Definition: MSVehicle.h:1146
MSLane * getMutableLane() const
Returns the lane the vehicle is on Non const version indicates that something volatile is going on.
Definition: MSVehicle.h:560
MSCFModel::VehicleVariables * myCFVariables
The per vehicle variables of the car following model.
Definition: MSVehicle.h:2054
bool addTraciStop(SUMOVehicleParameter::Stop stop, std::string &errorMsg)
Definition: MSVehicle.cpp:6291
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:2838
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
Definition: MSVehicle.cpp:6424
double getMaxSpeedOnLane() const
Returns the maximal speed for the vehicle on its current lane (including speed factor and deviation,...
Definition: MSVehicle.cpp:1241
bool isRemoteControlled() const
Returns the information whether the vehicle is fully controlled via TraCI.
Definition: MSVehicle.cpp:6443
bool myAmOnNet
Whether the vehicle is on the network (not parking, teleported, vaporized, or arrived)
Definition: MSVehicle.h:1860
void enterLaneAtMove(MSLane *enteredLane, bool onTeleporting=false)
Update when the vehicle enters a new lane in the move step.
Definition: MSVehicle.cpp:4772
void adaptBestLanesOccupation(int laneIndex, double density)
update occupation from MSLaneChanger
Definition: MSVehicle.cpp:5678
void loadPreviousApproaching(MSLink *link, bool setRequest, SUMOTime arrivalTime, double arrivalSpeed, SUMOTime arrivalTimeBraking, double arrivalSpeedBraking, double dist, double leaveSpeed)
Definition: MSVehicle.cpp:6738
void setAngle(double angle, bool straightenFurther=false)
Set a custom vehicle angle in rad, optionally updates furtherLanePosLat.
Definition: MSVehicle.cpp:1284
std::vector< LaneQ >::iterator myCurrentLaneInBestLanes
Definition: MSVehicle.h:1840
double getDeltaPos(const double accel) const
calculates the distance covered in the next integration step given an acceleration and assuming the c...
Definition: MSVehicle.cpp:3053
const MSLane * myLastBestLanesInternalLane
Definition: MSVehicle.h:1828
void updateOccupancyAndCurrentBestLane(const MSLane *startLane)
updates LaneQ::nextOccupation and myCurrentLaneInBestLanes
Definition: MSVehicle.cpp:5475
const std::vector< MSLane * > getUpstreamOppositeLanes() const
Returns the sequence of opposite lanes corresponding to past lanes.
Definition: MSVehicle.cpp:5652
WaitingTimeCollector myWaitingTimeCollector
Definition: MSVehicle.h:1803
void setRemoteState(Position xyPos)
sets position outside the road network
Definition: MSVehicle.cpp:6437
void fixPosition()
repair errors in vehicle position after changing between internal edges
Definition: MSVehicle.cpp:5686
double getAcceleration() const
Returns the vehicle's acceleration in m/s (this is computed as the last step's mean acceleration in c...
Definition: MSVehicle.h:485
double getSpeedWithoutTraciInfluence() const
Returns the uninfluenced velocity.
Definition: MSVehicle.cpp:6414
PositionVector getBoundingBox(double offset=0) const
get bounding rectangle
Definition: MSVehicle.cpp:6135
ManoeuvreType
flag identifying which, if any, manoeuvre is in progress
Definition: MSVehicle.h:1205
@ MANOEUVRE_ENTRY
Manoeuvre into stopping place.
Definition: MSVehicle.h:1207
@ MANOEUVRE_NONE
not manouevring
Definition: MSVehicle.h:1211
@ MANOEUVRE_EXIT
Manoeuvre out of stopping place.
Definition: MSVehicle.h:1209
Position getPosition(const double offset=0) const
Return current position (x/y, cartesian)
Definition: MSVehicle.cpp:1142
void setBrakingSignals(double vNext)
sets the braking lights on/off
Definition: MSVehicle.cpp:3576
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the best sequence of lanes to continue the route starting at myLane.
Definition: MSVehicle.cpp:5497
double estimateTimeToNextStop() const
Definition: MSVehicle.cpp:6958
MSParkingArea * getCurrentParkingArea()
get the current parking area stop or nullptr
Definition: MSVehicle.cpp:1462
const MSEdge * myLastBestLanesEdge
Definition: MSVehicle.h:1827
bool ignoreCollision() const
whether this vehicle is except from collision checks
Definition: MSVehicle.cpp:1509
Influencer * myInfluencer
An instance of a velocity/lane influencing instance; built in "getInfluencer".
Definition: MSVehicle.h:2057
void saveState(OutputDevice &out)
Saves the states of a vehicle.
Definition: MSVehicle.cpp:6646
bool replaceRoute(const MSRoute *route, const std::string &info, bool onInit=false, int offset=0, bool addStops=true, bool removeStops=true, std::string *msgReturn=nullptr)
Replaces the current route by the given one.
Definition: MSVehicle.cpp:1047
void onRemovalFromNet(const MSMoveReminder::Notification reason)
Called when the vehicle is removed from the network.
Definition: MSVehicle.cpp:978
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:1941
bool resumeFromStopping()
Definition: MSVehicle.cpp:6329
int getBestLaneOffset() const
Definition: MSVehicle.cpp:5668
double lateralDistanceToLane(const int offset) const
Get the minimal lateral distance required to move fully onto the lane at given offset.
Definition: MSVehicle.cpp:6012
bool stopsAtEdge(const MSEdge *edge) const
Returns whether the vehicle stops at the given edge.
Definition: MSVehicle.cpp:1890
double getBackPositionOnLane(const MSLane *lane) const
Get the vehicle's position relative to the given lane.
Definition: MSVehicle.h:396
void resetActionOffset(const SUMOTime timeUntilNextAction=0)
Resets the action offset for the vehicle.
Definition: MSVehicle.cpp:1916
std::vector< DriveProcessItem > DriveItemVector
Container for used Links/visited Lanes during planMove() and executeMove.
Definition: MSVehicle.h:1948
void setBlinkerInformation()
sets the blue flashing light for emergency vehicles
Definition: MSVehicle.cpp:5797
DriveItemVector::iterator myNextDriveItem
iterator pointing to the next item in myLFLinkLanes
Definition: MSVehicle.h:1961
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:4965
bool isIdling() const
Returns whether a sim vehicle is waiting to enter a lane (after parking has completed)
Definition: MSVehicle.h:590
std::shared_ptr< MSSimpleDriverState > getDriverState() const
Returns the vehicle driver's state.
Definition: MSVehicle.cpp:6750
void removeApproachingInformation(const DriveItemVector &lfLinks) const
unregister approach from all upcoming links
Definition: MSVehicle.cpp:6070
void replaceVehicleType(MSVehicleType *type)
Replaces the current vehicle type by the one given.
Definition: MSVehicle.cpp:4259
SUMOTime myJunctionEntryTimeNeverYield
Definition: MSVehicle.h:1886
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:5941
bool rerouteParkingArea(const std::string &parkingAreaID, std::string &errorMsg)
Definition: MSVehicle.cpp:6215
bool hasArrived() const
Returns whether this vehicle has already arived (reached the arrivalPosition on its final edge)
Definition: MSVehicle.cpp:1032
const MSEdge * getRerouteOrigin() const
Returns the starting point for reroutes (usually the current edge)
Definition: MSVehicle.cpp:1271
void switchOffSignal(int signal)
Switches the given signal off.
Definition: MSVehicle.h:1129
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:4190
double getStopArrivalDelay() const
Returns the estimated public transport stop arrival delay in seconds.
Definition: MSVehicle.cpp:7073
int mySignals
State of things of the vehicle that can be on or off.
Definition: MSVehicle.h:1857
bool setExitManoeuvre()
accessor function to myManoeuvre equivalent
Definition: MSVehicle.cpp:6771
double myStopDist
distance to the next stop or doubleMax if there is none
Definition: MSVehicle.h:1877
bool myAmRegisteredAsWaitingForContainer
Whether this vehicle is registered as waiting for a container (for deadlock-recognition)
Definition: MSVehicle.h:1869
Signalling
Some boolean values which describe the state of some vehicle parts.
Definition: MSVehicle.h:1064
@ VEH_SIGNAL_BLINKER_RIGHT
Right blinker lights are switched on.
Definition: MSVehicle.h:1068
@ VEH_SIGNAL_BRAKELIGHT
The brake lights are on.
Definition: MSVehicle.h:1074
@ VEH_SIGNAL_EMERGENCY_BLUE
A blue emergency light is on.
Definition: MSVehicle.h:1090
@ VEH_SIGNAL_BLINKER_LEFT
Left blinker lights are switched on.
Definition: MSVehicle.h:1070
bool isLeader(const MSLink *link, const MSVehicle *veh) const
whether the given vehicle must be followed at the given junction
Definition: MSVehicle.cpp:6527
SUMOTime getActionStepLength() const
Returns the vehicle's action step length in millisecs, i.e. the interval between two action points.
Definition: MSVehicle.h:496
bool myHaveToWaitOnNextLink
Definition: MSVehicle.h:1871
SUMOTime collisionStopTime() const
Returns the remaining time a vehicle needs to stop due to a collision. A negative value indicates tha...
Definition: MSVehicle.cpp:1503
const std::vector< const MSLane * > getPastLanesUntil(double distance) const
Returns the sequence of past lanes (right-most on edge) based on the route starting at the current la...
Definition: MSVehicle.cpp:5594
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:5727
bool executeMove()
Executes planned vehicle movements with regards to right-of-way.
Definition: MSVehicle.cpp:3909
std::pair< const MSVehicle *const, double > getFollower(double dist=0) const
Returns the follower of the vehicle looking for a fixed distance.
Definition: MSVehicle.cpp:5757
ChangeRequest
Requests set via TraCI.
Definition: MSVehicle.h:192
@ REQUEST_HOLD
vehicle want's to keep the current lane
Definition: MSVehicle.h:200
@ REQUEST_LEFT
vehicle want's to change to left lane
Definition: MSVehicle.h:196
@ REQUEST_NONE
vehicle doesn't want to change
Definition: MSVehicle.h:194
@ REQUEST_RIGHT
vehicle want's to change to right lane
Definition: MSVehicle.h:198
void computeFurtherLanes(MSLane *enteredLane, double pos, bool collision=false)
updates myFurtherLanes on lane insertion or after collision
Definition: MSVehicle.cpp:4876
std::pair< const MSLane *, double > getLanePosAfterDist(double distance) const
return lane and position along bestlanes at the given distance
Definition: MSVehicle.cpp:5693
SUMOTime myCollisionImmunity
amount of time for which the vehicle is immune from collisions
Definition: MSVehicle.h:1880
bool passingMinor() const
decide whether the vehicle is passing a minor link or has comitted to do so
Definition: MSVehicle.cpp:6511
void updateWaitingTime(double vNext)
Updates the vehicle's waiting time counters (accumulated and consecutive)
Definition: MSVehicle.cpp:3595
void enterLaneAtLaneChange(MSLane *enteredLane)
Update when the vehicle enters a new lane in the laneChange step.
Definition: MSVehicle.cpp:4824
BaseInfluencer & getBaseInfluencer()
Returns the velocity/lane influencer.
Definition: MSVehicle.cpp:6397
Influencer & getInfluencer()
Definition: MSVehicle.cpp:6389
double getRightSideOnLane() const
Get the vehicle's lateral position on the lane:
Definition: MSVehicle.cpp:5888
bool unsafeLinkAhead(const MSLane *lane) const
whether the vehicle may safely move to the given lane with regard to upcoming links
Definition: MSVehicle.cpp:6082
double getCurrentApparentDecel() const
get apparent deceleration based on vType parameters and current acceleration
Definition: MSVehicle.cpp:6764
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:4277
DriveItemVector myLFLinkLanesPrev
planned speeds from the previous step for un-registering from junctions after the new container is fi...
Definition: MSVehicle.h:1954
std::vector< std::vector< LaneQ > > myBestLanes
Definition: MSVehicle.h:1835
void setActionStepLength(double actionStepLength, bool resetActionOffset=true)
Sets the action steplength of the vehicle.
Definition: MSVehicle.cpp:1307
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
Definition: MSVehicle.h:411
double getSlope() const
Returns the slope of the road at vehicle's position in degrees.
Definition: MSVehicle.cpp:1128
bool myActionStep
The flag myActionStep indicates whether the current time step is an action point for the vehicle.
Definition: MSVehicle.h:1815
const Position getBackPosition() const
Definition: MSVehicle.cpp:1382
bool congested() const
Definition: MSVehicle.cpp:1324
void loadState(const SUMOSAXAttributes &attrs, const SUMOTime offset)
Loads the state of this vehicle from the given description.
Definition: MSVehicle.cpp:6690
double getSpeed() const
Returns the vehicle's current speed.
Definition: MSVehicle.h:462
void setApproachingForAllLinks(const SUMOTime t)
Register junction approaches for all link items in the current plan.
Definition: MSVehicle.cpp:4686
SUMOTime remainingStopDuration() const
Returns the remaining stop duration for a stopped vehicle or 0.
Definition: MSVehicle.cpp:1494
bool keepStopping(bool afterProcessing=false) const
Returns whether the vehicle is stopped and must continue to do so.
Definition: MSVehicle.cpp:1482
void workOnIdleReminders()
cycle through vehicle devices invoking notifyIdle
Definition: MSVehicle.cpp:1089
static std::vector< MSLane * > myEmptyLaneVector
Definition: MSVehicle.h:1842
Position myCachedPosition
Definition: MSVehicle.h:1882
MSVehicle::ManoeuvreType getManoeuvreType() const
accessor function to myManoeuvre equivalent
Definition: MSVehicle.cpp:6820
double checkReversal(bool &canReverse, double speedThreshold=SUMO_const_haltingSpeed, double seen=0) const
Definition: MSVehicle.cpp:3619
void removePassedDriveItems()
Erase passed drive items from myLFLinkLanes (and unregister approaching information for corresponding...
Definition: MSVehicle.cpp:3362
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
Definition: MSVehicle.cpp:5063
std::vector< double > myFurtherLanesPosLat
lateral positions on further lanes
Definition: MSVehicle.h:1854
bool checkActionStep(const SUMOTime t)
Returns whether the vehicle is supposed to take action in the current simulation step Updates myActio...
Definition: MSVehicle.cpp:1906
Position validatePosition(Position result, double offset=0) const
ensure that a vehicle-relative position is not invalid
Definition: MSVehicle.cpp:1250
bool keepClear(const MSLink *link) const
decide whether the given link must be kept clear
Definition: MSVehicle.cpp:6455
bool manoeuvreIsComplete() const
accessor function to myManoeuvre equivalent
Definition: MSVehicle.cpp:6953
double processNextStop(double currentVelocity)
Processes stops, returns the velocity needed to reach the stop.
Definition: MSVehicle.cpp:1515
double myAngle
the angle in radians (
Definition: MSVehicle.h:1874
bool ignoreRed(const MSLink *link, bool canBrake) const
decide whether a red (or yellow light) may be ignore
Definition: MSVehicle.cpp:6467
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition: MSVehicle.h:372
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:552
void updateTimeLoss(double vNext)
Updates the vehicle's time loss.
Definition: MSVehicle.cpp:3607
MSDevice_DriverState * myDriverState
This vehicle's driver state.
Definition: MSVehicle.h:1812
bool joinTrainPart(MSVehicle *veh)
try joining the given vehicle to the rear of this one (to resolve joinTriggered)
Definition: MSVehicle.cpp:1820
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition: MSVehicle.h:917
MSLane * myLane
The lane the vehicle is on.
Definition: MSVehicle.h:1823
bool onFurtherEdge(const MSEdge *edge) const
whether this vehicle has its back (and no its front) on the given edge
Definition: MSVehicle.cpp:6205
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:3333
Manoeuvre myManoeuvre
Definition: MSVehicle.h:1294
double getLateralOverlap() const
return the amount by which the vehicle extends laterally outside it's primary lane
Definition: MSVehicle.cpp:6064
double getAngle() const
Returns the vehicle's direction in radians.
Definition: MSVehicle.h:683
bool handleCollisionStop(MSStop &stop, const double distToStop)
Definition: MSVehicle.cpp:6302
bool hasInfluencer() const
whether the vehicle is individually influenced (via TraCI or special parameters)
Definition: MSVehicle.h:1633
double getPreviousSpeed() const
Returns the vehicle's speed before the previous time step.
Definition: MSVehicle.h:470
MSVehicle()
invalidated default constructor
bool joinTrainPartFront(MSVehicle *veh)
try joining the given vehicle to the front of this one (to resolve joinTriggered)
Definition: MSVehicle.cpp:1837
void updateActionOffset(const SUMOTime oldActionStepLength, const SUMOTime newActionStepLength)
Process an updated action step length value (only affects the vehicle's action offset,...
Definition: MSVehicle.cpp:1922
double getBrakeGap(bool delayed=false) const
get distance for coming to a stop (used for rerouting checks)
Definition: MSVehicle.cpp:1900
void executeFractionalMove(double dist)
move vehicle forward by the given distance during insertion
Definition: MSVehicle.cpp:4152
LaneChangeMode
modes for resolving conflicts between external control (traci) and vehicle control over lane changing...
Definition: MSVehicle.h:1102
@ LC_NOCONFLICT
Definition: MSVehicle.h:1104
virtual void drawOutsideNetwork(bool)
register vehicle for drawing while outside the network
Definition: MSVehicle.h:1788
void initDevices()
Definition: MSVehicle.cpp:991
State myState
This Vehicles driving state (pos and speed)
Definition: MSVehicle.h:1809
void adaptToLeaderDistance(const MSLeaderDistanceInfo &ahead, double latOffset, const double seen, DriveProcessItem *const lastLink, const MSLane *const lane, double &v, double &vLinkPass) const
Definition: MSVehicle.cpp:2770
double getCenterOnEdge(const MSLane *lane=0) const
Get the vehicle's lateral position on the edge of the given lane (or its current edge if lane == 0)
Definition: MSVehicle.cpp:5900
void activateReminders(const MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
"Activates" all current move reminder
Definition: MSVehicle.cpp:4739
double getDistanceToPosition(double destPos, const MSEdge *destEdge) const
Definition: MSVehicle.cpp:5710
void planMoveInternal(const SUMOTime t, MSLeaderInfo ahead, DriveItemVector &lfLinks, double &myStopDist, std::pair< double, LinkDirection > &myNextTurn) const
Definition: MSVehicle.cpp:2007
void switchOnSignal(int signal)
Switches the given signal on.
Definition: MSVehicle.h:1121
int getLaneIndex() const
Definition: MSVehicle.cpp:5872
void updateParkingState()
update state while parking
Definition: MSVehicle.cpp:4246
DriveItemVector myLFLinkLanes
container for the planned speeds in the current step
Definition: MSVehicle.h:1951
void updateDriveItems()
Check whether the drive items (myLFLinkLanes) are up to date, and update them if required.
Definition: MSVehicle.cpp:3416
SUMOTime myJunctionEntryTime
time at which the current junction was entered
Definition: MSVehicle.h:1885
static MSVehicleTransfer * getInstance()
Returns the instance of this object.
void remove(MSVehicle *veh)
Remove a vehicle from this transfer object.
The car-following model and parameter.
Definition: MSVehicleType.h:62
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
double getMaxSpeed() const
Get vehicle's maximum speed [m/s].
double getMinGap() const
Get the free space in front of vehicles of this class.
LaneChangeModel getLaneChangeModel() const
void setLength(const double &length)
Set a new value for this type's length.
SUMOTime getExitManoeuvreTime(const int angle) const
Accessor function for parameter equivalent returning exit time for a specific manoeuver angle.
bool isVehicleSpecific() const
Returns whether this type belongs to a single vehicle only (was modified)
const std::string & getID() const
Returns the name of the vehicle type.
Definition: MSVehicleType.h:90
void setActionStepLength(const SUMOTime actionStepLength, bool resetActionOffset)
Set a new value for this type's action step length.
double getLength() const
Get vehicle's length [m].
SUMOVehicleShape getGuiShape() const
Get this vehicle type's shape.
const MSCFModel & getCarFollowModel() const
Returns the vehicle type's car following model definition (const version)
SUMOTime getEntryManoeuvreTime(const int angle) const
Accessor function for parameter equivalent returning entry time for a specific manoeuver angle.
const SUMOVTypeParameter & getParameter() const
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:67
const std::string & getID() const
Returns the id.
Definition: Named.h:74
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:248
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
void writeParams(OutputDevice &device) const
write Params in the given outputdevice
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
static const Position INVALID
used to indicate that a position is valid
Definition: Position.h:293
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition: Position.h:252
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:262
A list of positions.
void append(const PositionVector &v, double sameThreshold=2.0)
double rotationAtOffset(double pos) const
Returns the rotation at the given length.
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
void move2side(double amount, double maxExtension=100)
move position vector to side using certain ammount
double slopeDegreeAtOffset(double pos) const
Returns the slope at the given length.
void extrapolate2D(const double val, const bool onlyFirst=false)
extrapolate position vector in two dimensions (Z is ignored)
void scaleRelative(double factor)
enlarges/shrinks the polygon by a factor based at the centroid
PositionVector reverse() const
reverse position vector
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
Definition: RandHelper.h:119
double recomputeCosts(const std::vector< const E * > &edges, const V *const v, SUMOTime msTime, double *lengthp=nullptr) const
virtual bool compute(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent=false)=0
Builds the route between the given edges using the minimum effort at the given time The definition of...
Encapsulated SAX-Attributes.
virtual double getFloat(int id) const =0
Returns the double-value of the named (by its enum-value) attribute.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
virtual std::string getString(int id) const =0
Returns the string-value of the named (by its enum-value) attribute.
virtual double getSpeed() const =0
Returns the object's current speed.
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.
Representation of a vehicle.
Definition: SUMOVehicle.h:60
Definition of vehicle stop (position and duration)
SUMOTime started
the time at which this stop was reached
std::string lane
The lane to stop at.
SUMOTime extension
The maximum time extension for boarding / loading.
double speed
the speed at which this stop counts as reached (waypoint mode)
std::string parkingarea
(Optional) parking area if one is assigned to the stop
std::string split
the id of the vehicle (train portion) that splits of upon reaching this stop
double startPos
The stopping position start.
std::string line
the new line id of the trip within a cyclical public transport route
double posLat
the lateral offset when stopping
std::string join
the id of the vehicle (train portion) to which this vehicle shall be joined
SUMOTime until
The time at which the vehicle may continue its journey.
SUMOTime ended
the time at which this stop was ended
double endPos
The stopping position end.
bool parking
whether the vehicle is removed from the net while stopping
std::string tripId
id of the trip within a cyclical public transport route
SUMOTime arrival
The (expected) time at which the vehicle reaches the stop.
SUMOTime duration
The stopping duration.
Structure representing possible vehicle parameter.
int parametersSet
Information for the router which parameter were set, TraCI may modify this (when changing color)
int departLane
(optional) The lane the vehicle shall depart from (index in edge)
ArrivalSpeedDefinition arrivalSpeedProcedure
Information how the vehicle's end speed shall be chosen.
double departSpeed
(optional) The initial speed of the vehicle
std::vector< std::string > via
List of the via-edges the vehicle must visit.
ArrivalLaneDefinition arrivalLaneProcedure
Information how the vehicle shall choose the lane to arrive on.
DepartLaneDefinition departLaneProcedure
Information how the vehicle shall choose the lane to depart from.
DepartSpeedDefinition departSpeedProcedure
Information how the vehicle's initial speed shall be chosen.
double arrivalPos
(optional) The position the vehicle shall arrive on
bool wasSet(int what) const
Returns whether the given parameter was set.
ArrivalPosDefinition arrivalPosProcedure
Information how the vehicle shall choose the arrival position.
double arrivalSpeed
(optional) The final speed of the vehicle (not used yet)
int arrivalEdge
(optional) The final edge within the route of the vehicle
static SUMOTime processActionStepLength(double given)
Checks and converts given value for the action step length from seconds to miliseconds assuring it be...
#define M_PI
Definition: odrSpiral.cpp:40
Drive process items represent bounds on the safe velocity corresponding to the upcoming links.
Definition: MSVehicle.h:1894
double getLeaveSpeed() const
Definition: MSVehicle.h:1941
void adaptLeaveSpeed(const double v)
Definition: MSVehicle.h:1934
static std::map< const MSVehicle *, GapControlState * > refVehMap
stores reference vehicles currently in use by a gapController
Definition: MSVehicle.h:1367
static GapControlVehStateListener vehStateListener
Definition: MSVehicle.h:1370
void activate(double tauOriginal, double tauTarget, double additionalGap, double duration, double changeRate, double maxDecel, const MSVehicle *refVeh)
Start gap control with given params.
Definition: MSVehicle.cpp:314
static void cleanup()
Static cleanup (removes vehicle state listener)
Definition: MSVehicle.cpp:308
void deactivate()
Stop gap control.
Definition: MSVehicle.cpp:344
static void init()
Static initalization (adds vehicle state listener)
Definition: MSVehicle.cpp:297
A structure representing the best lanes for continuing the current route starting at 'lane'.
Definition: MSVehicle.h:811
double length
The overall length which may be driven when using this lane without a lane change.
Definition: MSVehicle.h:815
bool allowsContinuation
Whether this lane allows to continue the drive.
Definition: MSVehicle.h:825
double nextOccupation
As occupation, but without the first lane.
Definition: MSVehicle.h:821
std::vector< MSLane * > bestContinuations
Definition: MSVehicle.h:831
MSLane * lane
The described lane.
Definition: MSVehicle.h:813
double currentLength
The length which may be driven on this lane.
Definition: MSVehicle.h:817
int bestLaneOffset
The (signed) number of lanes to be crossed to get to the lane which allows to continue the drive.
Definition: MSVehicle.h:823
double occupation
The overall vehicle sum on consecutive lanes which can be passed without a lane change.
Definition: MSVehicle.h:819