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