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