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