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