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