Eclipse SUMO - Simulation of Urban MObility
MSBaseVehicle.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
20 // A base class for vehicle implementations
21 /****************************************************************************/
22 #include <config.h>
23 
24 #include <iostream>
25 #include <cassert>
26 #include <utils/common/StdDefs.h>
32 #include <libsumo/TraCIConstants.h>
33 #include <mesosim/MELoop.h>
34 #include <mesosim/MEVehicle.h>
45 #include "MSGlobals.h"
46 #include "MSVehicleControl.h"
47 #include "MSVehicleType.h"
48 #include "MSEdge.h"
49 #include "MSLane.h"
50 #include "MSMoveReminder.h"
51 #include "MSEdgeWeightsStorage.h"
52 #include "MSNet.h"
53 #include "MSStop.h"
54 #include "MSParkingArea.h"
55 #include "MSInsertionControl.h"
56 #include "MSBaseVehicle.h"
57 
58 //#define DEBUG_REROUTE
59 //#define DEBUG_ADD_STOP
60 //#define DEBUG_COND (getID() == "")
61 //#define DEBUG_COND (true)
62 //#define DEBUG_REPLACE_ROUTE
63 #define DEBUG_COND (isSelected())
64 
65 // ===========================================================================
66 // static members
67 // ===========================================================================
69 std::vector<MSTransportable*> MSBaseVehicle::myEmptyTransportableVector;
70 #ifdef _DEBUG
71 std::set<std::string> MSBaseVehicle::myShallTraceMoveReminders;
72 #endif
74 
75 // ===========================================================================
76 // Influencer method definitions
77 // ===========================================================================
78 
80 {}
81 
82 // ===========================================================================
83 // method definitions
84 // ===========================================================================
85 
86 double
88  throw ProcessError("getPreviousSpeed() is not available for non-MSVehicles.");
89 }
90 
91 
93  MSVehicleType* type, const double speedFactor) :
94  SUMOVehicle(pars->id),
95  myParameter(pars),
96  myRoute(route),
97  myType(type),
98  myCurrEdge(route->begin()),
99  myChosenSpeedFactor(pars->speedFactor < 0 ? speedFactor : pars->speedFactor),
100  myMoveReminders(0),
101  myPersonDevice(nullptr),
102  myContainerDevice(nullptr),
103  myEnergyParams(nullptr),
105  myDepartPos(-1),
106  myArrivalPos(-1),
107  myArrivalLane(-1),
108  myNumberReroutes(0),
110  myOdometer(0.),
114  myEdgeWeights(nullptr)
115 #ifdef _DEBUG
116  , myTraceMoveReminders(myShallTraceMoveReminders.count(pars->id) > 0)
117 #endif
118 {
119  if ((*myRoute->begin())->isTazConnector() || myRoute->getLastEdge()->isTazConnector()) {
121  }
122  if ((pars->parametersSet & VEHPARS_FORCE_REROUTE) == 0) {
124  }
125  if (!pars->wasSet(VEHPARS_FORCE_REROUTE)) {
127  }
129 }
130 
131 
133  delete myEdgeWeights;
134  if (myParameter->repetitionNumber == -1) {
135  // this is not a flow (flows call checkDist in MSInsertionControl::determineCandidates)
137  }
138  for (MSVehicleDevice* dev : myDevices) {
139  delete dev;
140  }
141  delete myEnergyParams;
142  delete myParkingMemory;
144  delete myParameter;
145 }
146 
147 
148 void
150  // the check for an instance is needed for the unit tests which do not construct a network
151  // TODO Optimize for speed and there should be a better way to check whether a vehicle is part of a flow
152  if (MSNet::hasInstance() && !MSNet::getInstance()->hasFlow(getFlowID())) {
153  myRoute->checkRemoval();
154  }
155 }
156 
157 
158 std::string
160  return getID().substr(0, getID().rfind('.'));
161 }
162 
163 
164 void
167  for (MSVehicleDevice* dev : myDevices) {
168  myMoveReminders.push_back(std::make_pair(dev, 0.));
169  }
171  // ensure we have the emission parameters even if we don't have the device
173  }
174 }
175 
176 
177 void
178 MSBaseVehicle::setID(const std::string& /*newID*/) {
179  throw ProcessError(TL("Changing a vehicle ID is not permitted"));
180 }
181 
184  return *myParameter;
185 }
186 
187 
188 void
190  delete myParameter;
191  myParameter = newParameter;
192 }
193 
194 
195 bool
198 }
199 
200 double
203 }
204 
205 
206 const MSEdge*
207 MSBaseVehicle::succEdge(int nSuccs) const {
208  if (myCurrEdge + nSuccs < myRoute->end() && std::distance(myCurrEdge, myRoute->begin()) <= nSuccs) {
209  return *(myCurrEdge + nSuccs);
210  } else {
211  return nullptr;
212  }
213 }
214 
215 
216 const MSEdge*
218  return *myCurrEdge;
219 }
220 
221 
222 const std::set<SUMOTrafficObject::NumericalID>
224  std::set<SUMOTrafficObject::NumericalID> result;
225  for (auto e = myCurrEdge; e != myRoute->end(); ++e) {
226  result.insert((*e)->getNumericalID());
227  }
228  return result;
229 }
230 
231 
232 bool
234  if (stop == nullptr) {
235  return false;
236  }
237  for (const MSStop& s : myStops) {
238  if (s.busstop == stop
239  || s.containerstop == stop
240  || s.parkingarea == stop
241  || s.chargingStation == stop) {
242  return true;
243  }
244  }
245  return false;
246 }
247 
248 bool
249 MSBaseVehicle::stopsAtEdge(const MSEdge* edge) const {
250  for (const MSStop& s : myStops) {
251  if (&s.lane->getEdge() == edge) {
252  return true;
253  }
254  }
255  return myRoute->getLastEdge() == edge;
256 }
257 
258 
259 bool
260 MSBaseVehicle::reroute(SUMOTime t, const std::string& info, SUMOAbstractRouter<MSEdge, SUMOVehicle>& router, const bool onInit, const bool withTaz, const bool silent, const MSEdge* sink) {
261  // check whether to reroute
262  const MSEdge* source = withTaz && onInit ? MSEdge::dictionary(myParameter->fromTaz + "-source") : *getRerouteOrigin();
263  if (source == nullptr) {
264  source = *getRerouteOrigin();
265  }
266  if (sink == nullptr) {
267  sink = withTaz ? MSEdge::dictionary(myParameter->toTaz + "-sink") : myRoute->getLastEdge();
268  if (sink == nullptr) {
269  sink = myRoute->getLastEdge();
270  }
271  }
272  ConstMSEdgeVector oldEdgesRemaining(source == *myCurrEdge ? myCurrEdge : myCurrEdge + 1, myRoute->end());
273  ConstMSEdgeVector edges;
274  ConstMSEdgeVector stops;
275  std::set<int> jumps;
276  if (myParameter->via.size() == 0) {
277  double firstPos = -1;
278  double lastPos = -1;
279  stops = getStopEdges(firstPos, lastPos, jumps);
280  if (stops.size() > 0) {
281  const double sourcePos = onInit ? 0 : getPositionOnLane();
282  // avoid superfluous waypoints for first and last edge
283  const bool skipFirst = stops.front() == source && (source != getEdge() || sourcePos + getBrakeGap() <= firstPos + NUMERICAL_EPS);
284  const bool skipLast = stops.back() == sink && myArrivalPos >= lastPos && (
285  stops.size() < 2 || stops.back() != stops[stops.size() - 2]);
286 #ifdef DEBUG_REROUTE
287  if (DEBUG_COND) {
288  std::cout << SIMTIME << " reroute " << info << " veh=" << getID() << " lane=" << Named::getIDSecure(getLane())
289  << " source=" << source->getID() << " sourcePos=" << sourcePos << " firstPos=" << firstPos << " arrivalPos=" << myArrivalPos << " lastPos=" << lastPos
290  << " route=" << toString(myRoute->getEdges()) << " stopEdges=" << toString(stops) << " skipFirst=" << skipFirst << " skipLast=" << skipLast << "\n";
291  }
292 #endif
293  if (stops.size() == 1 && (skipFirst || skipLast)) {
294  stops.clear();
295  } else {
296  if (skipFirst) {
297  stops.erase(stops.begin());
298  }
299  if (skipLast) {
300  stops.erase(stops.end() - 1);
301  }
302  }
303  }
304  } else {
305  std::set<const MSEdge*> jumpEdges;
306  for (const MSStop& stop : myStops) {
307  if (stop.pars.jump >= 0) {
308  jumpEdges.insert(*stop.edge);
309  }
310  }
311  // via takes precedence over stop edges
312  // there is a consistency check in MSRouteHandler::addStop that warns when a stop edge is not part of the via edges
313  for (std::vector<std::string>::const_iterator it = myParameter->via.begin(); it != myParameter->via.end(); ++it) {
314  MSEdge* viaEdge = MSEdge::dictionary(*it);
315  if ((viaEdge == source && it == myParameter->via.begin()) || (viaEdge == sink && myParameter->via.end() - it == 1)) {
316  continue;
317  }
318  assert(viaEdge != 0);
319  if (!viaEdge->isTazConnector() && viaEdge->allowedLanes(getVClass()) == nullptr) {
320  throw ProcessError(TLF("Vehicle '%' is not allowed on any lane of via edge '%'.", getID(), viaEdge->getID()));
321  }
322  stops.push_back(viaEdge);
323  if (jumpEdges.count(viaEdge) != 0) {
324  jumps.insert((int)stops.size());
325  }
326  }
327  }
328 
329  int stopIndex = -1;
330  for (const MSEdge* const stopEdge : stops) {
331  stopIndex++;
332  // !!! need to adapt t here
333  ConstMSEdgeVector into;
334  if (jumps.count(stopIndex) != 0) {
335  edges.push_back(source);
336  source = stopEdge;
337  continue;
338  }
339  router.computeLooped(source, stopEdge, this, t, into, silent);
340  //std::cout << SIMTIME << " reroute veh=" << getID() << " source=" << source->getID() << " target=" << (*s)->getID() << " edges=" << toString(into) << "\n";
341  if (into.size() > 0) {
342  into.pop_back();
343  edges.insert(edges.end(), into.begin(), into.end());
344  if (stopEdge->isTazConnector()) {
345  source = into.back();
346  edges.pop_back();
347  } else {
348  source = stopEdge;
349  }
350  } else {
351  std::string error = TLF("Vehicle '%' has no valid route from edge '%' to stop edge '%'.", getID(), source->getID(), stopEdge->getID());
352  if (MSGlobals::gCheckRoutes || silent) {
353  throw ProcessError(error);
354  } else {
355  WRITE_WARNING(error);
356  edges.push_back(source);
357  }
358  source = stopEdge;
359  }
360  }
361  if (stops.empty() && source == sink && onInit
365  router.computeLooped(source, sink, this, t, edges, silent);
366  } else {
367  if (!router.compute(source, sink, this, t, edges, silent)) {
368  edges.clear();
369  }
370  }
371 
372  // router.setHint(myCurrEdge, myRoute->end(), this, t);
373  if (edges.empty() && silent) {
374  return false;
375  }
376  if (!edges.empty() && edges.front()->isTazConnector()) {
377  edges.erase(edges.begin());
378  }
379  if (!edges.empty() && edges.back()->isTazConnector()) {
380  edges.pop_back();
381  }
382  const double routeCost = router.recomputeCosts(edges, this, t);
383  const double previousCost = onInit ? routeCost : router.recomputeCosts(oldEdgesRemaining, this, t);
384  const double savings = previousCost - routeCost;
385  //if (getID() == "43") std::cout << SIMTIME << " pCost=" << previousCost << " cost=" << routeCost
386  // << " onInit=" << onInit
387  // << " prevEdges=" << toString(oldEdgesRemaining)
388  // << " newEdges=" << toString(edges)
389  // << "\n";
390  replaceRouteEdges(edges, routeCost, savings, info, onInit);
391  // this must be called even if the route could not be replaced
392  if (onInit) {
393  if (edges.empty()) {
395  throw ProcessError(TLF("Vehicle '%' has no valid route.", getID()));
396  } else if (source->isTazConnector()) {
397  WRITE_WARNINGF(TL("Removing vehicle '%' which has no valid route."), getID());
399  return false;
400  }
401  }
403  calculateArrivalParams(onInit);
404  }
405  return !edges.empty();
406 }
407 
408 
409 bool
410 MSBaseVehicle::replaceRouteEdges(ConstMSEdgeVector& edges, double cost, double savings, const std::string& info, bool onInit, bool check, bool removeStops, std::string* msgReturn) {
411  if (edges.empty()) {
412  WRITE_WARNINGF(TL("No route for vehicle '%' found."), getID());
413  if (msgReturn != nullptr) {
414  *msgReturn = "No route found";
415  }
416  return false;
417  }
418  // build a new id, first
419  std::string id = getID();
420  if (id[0] != '!') {
421  id = "!" + id;
422  }
423  const std::string idSuffix = id + "!var#";
424  int varIndex = 1;
425  id = idSuffix + toString(varIndex);
426  while (MSRoute::hasRoute(id)) {
427  id = idSuffix + toString(++varIndex);
428  }
429  int oldSize = (int)edges.size();
430  if (!onInit) {
431  const MSEdge* const origin = *getRerouteOrigin();
432  if (origin != *myCurrEdge && edges.front() == origin) {
433  edges.insert(edges.begin(), *myCurrEdge);
434  oldSize = (int)edges.size();
435  }
436  edges.insert(edges.begin(), myRoute->begin(), myCurrEdge);
437  }
438  if (edges == myRoute->getEdges() && haveValidStopEdges(true)) {
439  // re-assign stop iterators when rerouting to a new parkingArea / insertStop
440  return true;
441  }
442  const RGBColor& c = myRoute->getColor();
443  MSRoute* newRoute = new MSRoute(id, edges, false, &c == &RGBColor::DEFAULT_COLOR ? nullptr : new RGBColor(c), std::vector<SUMOVehicleParameter::Stop>());
444  newRoute->setCosts(cost);
445  newRoute->setSavings(savings);
446  ConstMSRoutePtr constRoute = std::shared_ptr<MSRoute>(newRoute);
447  if (!MSRoute::dictionary(id, constRoute)) {
448  delete newRoute;
449  if (msgReturn != nullptr) {
450  *msgReturn = "duplicate routeID '" + id + "'";
451  }
452  return false;
453  }
454 
455  std::string msg;
456  if (check && !hasValidRoute(msg, constRoute)) {
457  WRITE_WARNINGF(TL("Invalid route replacement for vehicle '%'. %"), getID(), msg);
459  if (msgReturn != nullptr) {
460  *msgReturn = msg;
461  }
462  return false;
463  }
464  }
465  if (!replaceRoute(constRoute, info, onInit, (int)edges.size() - oldSize, false, removeStops, msgReturn)) {
466  return false;
467  }
468  return true;
469 }
470 
471 
472 bool
473 MSBaseVehicle::replaceRoute(ConstMSRoutePtr newRoute, const std::string& info, bool onInit, int offset, bool addRouteStops, bool removeStops, std::string* msgReturn) {
474  const ConstMSEdgeVector& edges = newRoute->getEdges();
475  // rebuild in-vehicle route information
476  if (onInit) {
477  myCurrEdge = newRoute->begin();
478  } else {
479  MSRouteIterator newCurrEdge = std::find(edges.begin() + offset, edges.end(), *myCurrEdge);
480  if (newCurrEdge == edges.end()) {
481  if (msgReturn != nullptr) {
482  *msgReturn = TLF("current edge '%' not found in new route", (*myCurrEdge)->getID());
483  }
484 #ifdef DEBUG_REPLACE_ROUTE
485  if (DEBUG_COND) {
486  std::cout << " newCurrEdge not found\n";
487  }
488 #endif
489  return false;
490  }
491  if (getLane() != nullptr) {
492  if (getLane()->getEdge().isInternal() && (
493  (newCurrEdge + 1) == edges.end() || (*(newCurrEdge + 1)) != &(getLane()->getOutgoingViaLanes().front().first->getEdge()))) {
494  if (msgReturn != nullptr) {
495  *msgReturn = TL("Vehicle is on junction-internal edge leading elsewhere");
496  }
497 #ifdef DEBUG_REPLACE_ROUTE
498  if (DEBUG_COND) {
499  std::cout << " Vehicle is on junction-internal edge leading elsewhere\n";
500  }
501 #endif
502  return false;
503  } else if (getPositionOnLane() > getLane()->getLength()
504  && (myCurrEdge + 1) != myRoute->end()
505  && (newCurrEdge + 1) != edges.end()
506  && *(myCurrEdge + 1) != *(newCurrEdge + 1)) {
507  if (msgReturn != nullptr) {
508  *msgReturn = TL("Vehicle is moving past junction and committed to move to another successor edge");
509  }
510 #ifdef DEBUG_REPLACE_ROUTE
511  if (DEBUG_COND) {
512  std::cout << " Vehicle is moving past junction and committed to move to another successor edge\n";
513  }
514 #endif
515  return false;
516  }
517  }
518  myCurrEdge = newCurrEdge;
519  }
520  const bool stopsFromScratch = onInit && myRoute->getStops().empty();
521  // assign new route
523  myRoute = newRoute;
524  // update arrival definition
525  calculateArrivalParams(onInit);
526  // save information that the vehicle was rerouted
528  myStopUntilOffset += myRoute->getPeriod();
530 #ifdef DEBUG_REPLACE_ROUTE
531  if (DEBUG_COND) {
532  std::cout << SIMTIME << " replaceRoute info=" << info << " on " << (*myCurrEdge)->getID()
533  << " lane=" << Named::getIDSecure(getLane())
534  << " stopsFromScratch=" << stopsFromScratch
535  << " newSize=" << newRoute->getEdges().size()
536  << " newIndex=" << (myCurrEdge - newRoute->begin())
537  << " edges=" << toString(newRoute->getEdges())
538  << "\n";
539  }
540 #endif
541  // if we did not drive yet it may be best to simply reassign the stops from scratch
542  if (stopsFromScratch) {
543  myStops.clear();
545  } else {
546  // recheck old stops
547  MSRouteIterator searchStart = myCurrEdge;
548  double lastPos = getPositionOnLane() + getBrakeGap();
549  if (getLane() != nullptr && getLane()->isInternal()
550  && myStops.size() > 0 && !myStops.front().lane->isInternal()) {
551  // searchStart is still incoming to the intersection so lastPos
552  // relative to that edge must be adapted
553  lastPos += (*myCurrEdge)->getLength();
554  }
555  for (std::list<MSStop>::iterator iter = myStops.begin(); iter != myStops.end();) {
556  double endPos = iter->getEndPos(*this);
557 #ifdef DEBUG_REPLACE_ROUTE
558  if (DEBUG_COND) {
559  std::cout << " stopEdge=" << iter->lane->getEdge().getID() << " start=" << (searchStart - myCurrEdge) << " endPos=" << endPos << " lastPos=" << lastPos << "\n";
560  }
561 #endif
562  if (*searchStart != &iter->lane->getEdge()
563  || endPos + NUMERICAL_EPS < lastPos) {
564  if (searchStart != edges.end() && !iter->reached) {
565  searchStart++;
566  }
567  }
568  lastPos = endPos;
569 
570  iter->edge = std::find(searchStart, edges.end(), &iter->lane->getEdge());
571 #ifdef DEBUG_REPLACE_ROUTE
572  if (DEBUG_COND) {
573  std::cout << " foundIndex=" << (iter->edge - myCurrEdge) << " end=" << (edges.end() - myCurrEdge) << "\n";
574  }
575 #endif
576  if (iter->edge == edges.end()) {
577  if (!removeStops) {
578  WRITE_ERRORF(TL("Vehicle '%' could not assign stop '%' after rerouting (%) at time=%."), getID(), iter->getDescription(), info, time2string(SIMSTEP));
579  }
580  iter = myStops.erase(iter);
581  continue;
582  } else {
583  searchStart = iter->edge;
584  }
585  ++iter;
586  }
587  // add new stops
588  if (addRouteStops) {
589  for (std::vector<SUMOVehicleParameter::Stop>::const_iterator i = newRoute->getStops().begin(); i != newRoute->getStops().end(); ++i) {
590  std::string error;
592  if (error != "") {
593  WRITE_WARNING(error);
594  }
595  }
596  }
597  }
598  return true;
599 }
600 
601 
602 double
604  return 0;
605 }
606 
607 
608 void
613 }
614 
615 
616 SUMOTime
618  const SUMOTime dep = getParameter().depart;
619  if (dep < 0) {
620  return 0;
621  }
622  return hasDeparted() ? getDeparture() - dep : SIMSTEP - dep;
623 }
624 
625 
626 bool
628  return succEdge(1) == nullptr;
629 }
630 
631 
632 int
634  return (int) std::distance(myRoute->begin(), myCurrEdge);
635 }
636 
637 
638 void
640  myCurrEdge = myRoute->begin() + index;
641  const_cast<SUMOVehicleParameter*>(myParameter)->departLaneProcedure = departLaneProcedure;
642  // !!! hack
643  myArrivalPos = (*(myRoute->end() - 1))->getLanes()[0]->getLength();
644 }
645 
646 double
649 }
650 
651 bool
653  if (t->isPerson() && getPersonNumber() >= getVehicleType().getPersonCapacity()) {
654  return false;
655  } else if (!t->isPerson() && getContainerNumber() >= getVehicleType().getContainerCapacity()) {
656  return false;
657  }
658  if (isStopped() && myStops.begin()->pars.permitted.size() > 0
659  && myStops.begin()->pars.permitted.count(t->getID()) == 0) {
660  return false;
661  }
662  MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(getDevice(typeid(MSDevice_Taxi)));
663  if (taxiDevice != nullptr) {
664  return taxiDevice->allowsBoarding(t);
665  }
666  return true;
667 }
668 
669 
670 void
672  if (transportable->isPerson()) {
673  if (myPersonDevice == nullptr) {
675  myMoveReminders.push_back(std::make_pair(myPersonDevice, 0.));
678  }
679  }
680  myPersonDevice->addTransportable(transportable);
681  } else {
682  if (myContainerDevice == nullptr) {
684  myMoveReminders.push_back(std::make_pair(myContainerDevice, 0.));
687  }
688  }
689  myContainerDevice->addTransportable(transportable);
690  }
691 }
692 
693 
694 bool
696  for (const MSStop& stop : myStops) {
697  if (stop.edge == it) {
698  return stop.pars.jump >= 0;
699  }
700  }
701  return false;
702 }
703 
704 
705 bool
706 MSBaseVehicle::hasValidRoute(std::string& msg, ConstMSRoutePtr route) const {
707  MSRouteIterator start = myCurrEdge;
708  if (route == nullptr) {
709  route = myRoute;
710  } else {
711  start = route->begin();
712  }
713  const bool checkJumps = route == myRoute; // the edge iterators in the stops are invalid otherwise
714  MSRouteIterator last = route->end() - 1;
715  // check connectivity, first
716  for (MSRouteIterator e = start; e != last; ++e) {
717  const MSEdge& next = **(e + 1);
718  if ((*e)->allowedLanes(next, myType->getVehicleClass()) == nullptr) {
719  if (!checkJumps || !hasJump(e)) {
721  || (!next.hasTransientPermissions() && !(*e)->hasTransientPermissions())) {
722  msg = TLF("No connection between edge '%' and edge '%'.", (*e)->getID(), (*(e + 1))->getID());
723  return false;
724  }
725  }
726  }
727  }
728  last = route->end();
729  // check usable lanes, then
730  for (MSRouteIterator e = start; e != last; ++e) {
731  if ((*e)->prohibits(this)) {
732  msg = TLF("Edge '%' prohibits.", (*e)->getID());
733  return false;
734  }
735  }
736  return true;
737 }
738 
739 
740 bool
742  if (!(*myCurrEdge)->isTazConnector()) {
744  msg = TLF("Departure speed for vehicle '%' is too high for the vehicle type '%'.", getID(), myType->getID());
746  return false;
747  }
748  }
749  if (myRoute->getEdges().size() > 0 && !(*myCurrEdge)->prohibits(this)) {
751  return true;
752  } else {
753  msg = TLF("Vehicle '%' is not allowed to depart on any lane of edge '%'.", getID(), (*myCurrEdge)->getID());
755  return false;
756  }
757 }
758 
759 
760 int
761 MSBaseVehicle::getRouteValidity(bool update, bool silent, std::string* msgReturn) {
762  if (!update) {
763  return myRouteValidity;
764  }
765  // insertion check must be done in any case
766  std::string msg;
767  if (!hasValidRouteStart(msg)) {
769  throw ProcessError(msg);
770  } else if (!silent) {
771  // vehicle will be discarded
772  WRITE_WARNING(msg);
773  } else if (msgReturn != nullptr) {
774  *msgReturn = msg;
775  }
776  }
778  && (myRouteValidity & ROUTE_UNCHECKED) != 0
779  // we could check after the first rerouting
781  if (!hasValidRoute(msg, myRoute)) {
783  throw ProcessError(TLF("Vehicle '%' has no valid route. %", getID(), msg));
784  }
785  }
787  return myRouteValidity;
788 }
789 
790 void
792 #ifdef _DEBUG
793  if (myTraceMoveReminders) {
794  traceMoveReminder("add", rem, 0, true);
795  }
796 #endif
797  myMoveReminders.push_back(std::make_pair(rem, 0.));
798 }
799 
800 
801 void
803  for (MoveReminderCont::iterator r = myMoveReminders.begin(); r != myMoveReminders.end(); ++r) {
804  if (r->first == rem) {
805 #ifdef _DEBUG
806  if (myTraceMoveReminders) {
807  traceMoveReminder("remove", rem, 0, false);
808  }
809 #endif
810  myMoveReminders.erase(r);
811  return;
812  }
813  }
814 }
815 
816 
817 void
819  for (MoveReminderCont::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end();) {
820  if (rem->first->notifyEnter(*this, reason, enteredLane)) {
821 #ifdef _DEBUG
822  if (myTraceMoveReminders) {
823  traceMoveReminder("notifyEnter", rem->first, rem->second, true);
824  }
825 #endif
826  ++rem;
827  } else {
828 #ifdef _DEBUG
829  if (myTraceMoveReminders) {
830  traceMoveReminder("notifyEnter", rem->first, rem->second, false);
831  }
832 #endif
833  rem = myMoveReminders.erase(rem);
834  }
835  }
836 }
837 
838 
839 void
841  if (myRoute->getLastEdge()->isTazConnector()) {
842  return;
843  }
844  const int arrivalEdgeIndex = MIN2(myParameter->arrivalEdge, (int)myRoute->getEdges().size() - 1);
845  if (arrivalEdgeIndex != myParameter->arrivalEdge) {
846  WRITE_WARNINGF(TL("Vehicle '%' ignores attribute arrivalEdge=% after rerouting at time=% (routeLength=%)"),
847  getID(), myParameter->arrivalEdge, time2string(SIMSTEP), myRoute->getEdges().size() - 1);
848  }
849  const MSEdge* arrivalEdge = myParameter->arrivalEdge >= 0 ? myRoute->getEdges()[arrivalEdgeIndex] : myRoute->getLastEdge();
850  if (!onInit) {
851  arrivalEdge = myRoute->getLastEdge();
852  // ignore arrivalEdge parameter after rerouting
853  const_cast<SUMOVehicleParameter*>(myParameter)->arrivalEdge = -1;
854  }
855  const std::vector<MSLane*>& lanes = arrivalEdge->getLanes();
856  const double lastLaneLength = lanes[0]->getLength();
857  switch (myParameter->arrivalPosProcedure) {
859  if (fabs(myParameter->arrivalPos) > lastLaneLength) {
860  WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive at the given position!"), getID());
861  }
862  // Maybe we should warn the user about invalid inputs!
863  myArrivalPos = MIN2(myParameter->arrivalPos, lastLaneLength);
864  if (myArrivalPos < 0) {
865  myArrivalPos = MAX2(myArrivalPos + lastLaneLength, 0.);
866  }
867  break;
869  myArrivalPos = RandHelper::rand(lastLaneLength);
870  break;
872  myArrivalPos = lastLaneLength / 2.;
873  break;
874  default:
875  myArrivalPos = lastLaneLength;
876  break;
877  }
879  if (myParameter->arrivalLane >= (int)lanes.size() || !lanes[myParameter->arrivalLane]->allowsVehicleClass(myType->getVehicleClass())) {
880  WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive at the given lane '%_%'!"), getID(), arrivalEdge->getID(), toString(myParameter->arrivalLane));
881  }
882  myArrivalLane = MIN2(myParameter->arrivalLane, (int)(lanes.size() - 1));
884  myArrivalLane = -1;
885  for (MSLane* lane : lanes) {
886  if (lane->allowsVehicleClass(myType->getVehicleClass())) {
887  myArrivalLane = lane->getIndex();
888  break;
889  }
890  }
891  if (myArrivalLane == -1) {
892  WRITE_WARNINGF(TL("Vehicle '%' has no usable arrivalLane on edge '%'."), getID(), arrivalEdge->getID());
893  myArrivalLane = 0;
894  }
896  // pick random lane among all usable lanes
897  std::vector<MSLane*> usable;
898  for (MSLane* lane : lanes) {
899  if (lane->allowsVehicleClass(myType->getVehicleClass())) {
900  usable.push_back(lane);
901  }
902  }
903  if (usable.empty()) {
904  WRITE_WARNINGF(TL("Vehicle '%' has no usable arrivalLane on edge '%'."), getID(), arrivalEdge->getID());
905  myArrivalLane = 0;
906  } else {
907  myArrivalLane = usable[RandHelper::rand(0, (int)usable.size())]->getIndex();
908  }
909  }
911  for (std::vector<MSLane*>::const_iterator l = lanes.begin(); l != lanes.end(); ++l) {
912  if (myParameter->arrivalSpeed <= (*l)->getVehicleMaxSpeed(this)) {
913  return;
914  }
915  }
916  WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive with the given speed!"), getID());
917  }
918 }
919 
920 void
924  const int routeEdges = (int)myRoute->getEdges().size();
926  // write specific edge in vehroute output for reproducibility
927  pars->departEdge = RandHelper::rand(0, routeEdges);
929  }
930  assert(pars->departEdge >= 0);
931  if (pars->departEdge >= routeEdges) {
932  WRITE_WARNINGF(TL("Ignoring departEdge % for vehicle '%' with % route edges"), toString(pars->departEdge), getID(), toString(routeEdges));
933  } else {
934  myCurrEdge += pars->departEdge;
935  }
936  }
938  const int routeEdges = (int)myRoute->getEdges().size();
939  const int begin = (int)(myCurrEdge - myRoute->begin());
940  // write specific edge in vehroute output for reproducibility
941  pars->arrivalEdge = RandHelper::rand(begin, routeEdges);
943  assert(pars->arrivalEdge >= begin);
944  assert(pars->arrivalEdge < routeEdges);
945  }
946 }
947 
948 
949 double
951  return MAX2(0., MIN2(1., getVehicleType().getImpatience()
952  + (hasInfluencer() ? getBaseInfluencer()->getExtraImpatience() : 0)
953  + (MSGlobals::gTimeToImpatience > 0 ? (double)getWaitingTime() / (double)MSGlobals::gTimeToImpatience : 0.)));
954 }
955 
956 
957 MSDevice*
958 MSBaseVehicle::getDevice(const std::type_info& type) const {
959  for (MSVehicleDevice* const dev : myDevices) {
960  if (typeid(*dev) == type) {
961  return dev;
962  }
963  }
964  return nullptr;
965 }
966 
967 
968 void
970  // the parameters may hold the name of a vTypeDistribution but we are interested in the actual type
973  // params and stops must be written in child classes since they may wish to add additional attributes first
974  out.writeAttr(SUMO_ATTR_ROUTE, myRoute->getID());
975  std::ostringstream os;
976  os << myOdometer << " " << myNumberReroutes;
977  out.writeAttr(SUMO_ATTR_DISTANCE, os.str());
979  const int precision = out.precision();
980  out.setPrecision(MAX2(gPrecisionRandom, precision));
982  out.setPrecision(precision);
983  }
985  out.writeAttr(SUMO_ATTR_REROUTE, true);
986  }
988  // could be set from stop
990  }
991  // here starts the vehicle internal part (see loading)
992  // @note: remember to close the vehicle tag when calling this in a subclass!
993 }
994 
995 
996 bool
997 MSBaseVehicle::handleCollisionStop(MSStop& stop, const double distToStop) {
998  UNUSED_PARAMETER(stop);
999  UNUSED_PARAMETER(distToStop);
1000  return true;
1001 }
1002 
1003 
1004 bool
1006  return !myStops.empty() && myStops.begin()->reached /*&& myState.mySpeed < SUMO_const_haltingSpeed @todo #1864#*/;
1007 }
1008 
1009 
1010 bool
1012  return (isStopped() && (myStops.begin()->pars.parking == ParkingType::OFFROAD)
1013  && (myStops.begin()->parkingarea == nullptr || !myStops.begin()->parkingarea->parkOnRoad())
1014  && (myStops.begin()->getSpeed() == 0 || getSpeed() < SUMO_const_haltingSpeed));
1015 }
1016 
1017 
1018 bool
1020  return myPastStops.size() > 0 && myPastStops.back().jump >= 0 && getEdge()->getID() == myPastStops.back().edge;
1021 }
1022 
1023 
1024 bool
1026  return isStopped() && (myStops.begin()->triggered || myStops.begin()->containerTriggered || myStops.begin()->joinTriggered);
1027 }
1028 
1029 
1030 bool
1032  return isStopped() && (myStops.begin()->pars.parking == ParkingType::OFFROAD);
1033 }
1034 
1035 
1036 bool
1037 MSBaseVehicle::isStoppedInRange(const double pos, const double tolerance, bool checkFuture) const {
1038  if (isStopped() || (checkFuture && hasStops())) {
1039  const MSStop& stop = myStops.front();
1040  return stop.pars.startPos - tolerance <= pos && stop.pars.endPos + tolerance >= pos;
1041  }
1042  return false;
1043 }
1044 
1045 bool
1046 MSBaseVehicle::replaceParkingArea(MSParkingArea* parkingArea, std::string& errorMsg) {
1047  // Check if there is a parking area to be replaced
1048  if (parkingArea == 0) {
1049  errorMsg = "new parkingArea is NULL";
1050  return false;
1051  }
1052  if (myStops.size() == 0) {
1053  errorMsg = "vehicle has no stops";
1054  return false;
1055  }
1056  if (myStops.front().parkingarea == 0) {
1057  errorMsg = "first stop is not at parkingArea";
1058  return false;
1059  }
1060  MSStop& first = myStops.front();
1061  SUMOVehicleParameter::Stop& stopPar = const_cast<SUMOVehicleParameter::Stop&>(first.pars);
1062  // merge subsequent duplicate stops equals to parking area
1063  for (std::list<MSStop>::iterator iter = ++myStops.begin(); iter != myStops.end();) {
1064  if (iter->parkingarea == parkingArea) {
1065  stopPar.duration += iter->duration;
1066  myStops.erase(iter++);
1067  } else {
1068  break;
1069  }
1070  }
1071  stopPar.lane = parkingArea->getLane().getID();
1072  stopPar.parkingarea = parkingArea->getID();
1073  stopPar.startPos = parkingArea->getBeginLanePosition();
1074  stopPar.endPos = parkingArea->getEndLanePosition();
1075  first.edge = myRoute->end(); // will be patched in replaceRoute
1076  first.lane = &parkingArea->getLane();
1077  first.parkingarea = parkingArea;
1078  return true;
1079 }
1080 
1081 
1084  MSParkingArea* nextParkingArea = nullptr;
1085  if (!myStops.empty()) {
1087  MSStop stop = myStops.front();
1088  if (!stop.reached && stop.parkingarea != nullptr) {
1089  nextParkingArea = stop.parkingarea;
1090  }
1091  }
1092  return nextParkingArea;
1093 }
1094 
1095 
1098  MSParkingArea* currentParkingArea = nullptr;
1099  if (isParking()) {
1100  currentParkingArea = myStops.begin()->parkingarea;
1101  }
1102  return currentParkingArea;
1103 }
1104 
1105 
1106 const std::vector<std::string>&
1109  return myParameter->parkingBadges;
1110  } else {
1111  return getVehicleType().getParkingBadges();
1112  }
1113 }
1114 
1115 
1116 double
1117 MSBaseVehicle::basePos(const MSEdge* edge) const {
1118  double result = MIN2(getVehicleType().getLength() + POSITION_EPS, edge->getLength());
1119  if (hasStops()
1120  && myStops.front().edge == myRoute->begin()
1121  && (&myStops.front().lane->getEdge()) == *myStops.front().edge) {
1122  result = MIN2(result, MAX2(0.0, myStops.front().getEndPos(*this)));
1123  }
1124  return result;
1125 }
1126 
1127 MSLane*
1129  const std::string edgeID = SUMOXMLDefinitions::getEdgeIDFromLane(stop.lane);
1130  const int laneIndex = SUMOXMLDefinitions::getIndexFromLane(stop.lane);
1131  const MSEdge* edge = MSEdge::dictionary(edgeID);
1132  if (edge != nullptr && edge->getOppositeEdge() != nullptr
1133  && laneIndex < (edge->getNumLanes() + edge->getOppositeEdge()->getNumLanes())) {
1134  const int oppositeIndex = edge->getOppositeEdge()->getNumLanes() + edge->getNumLanes() - 1 - laneIndex;
1135  stop.edge = edgeID;
1136  return edge->getOppositeEdge()->getLanes()[oppositeIndex];
1137  } else {
1138  return nullptr;
1139  }
1140 }
1141 
1142 bool
1143 MSBaseVehicle::addStop(const SUMOVehicleParameter::Stop& stopPar, std::string& errorMsg, SUMOTime untilOffset,
1144  MSRouteIterator* searchStart) {
1145  MSStop stop(stopPar);
1146  if (stopPar.lane == "") {
1147  // use rightmost allowed lane
1148  MSEdge* e = MSEdge::dictionary(stopPar.edge);
1149  for (MSLane* cand : e->getLanes()) {
1150  if (cand->allowsVehicleClass(getVClass())) {
1151  stop.lane = cand;
1152  break;
1153  }
1154  }
1155  if (stop.lane == nullptr) {
1156  errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on any lane of edge '" + stopPar.edge + "'.";
1157  return false;
1158  }
1159  } else {
1160  stop.lane = MSLane::dictionary(stopPar.lane);
1161  if (stop.lane == nullptr) {
1162  // must be an opposite stop
1163  SUMOVehicleParameter::Stop tmp = stopPar;
1164  stop.lane = interpretOppositeStop(tmp);
1165  assert(stop.lane != nullptr);
1166  }
1167  if (!stop.lane->allowsVehicleClass(myType->getVehicleClass())) {
1168  errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on lane '" + stopPar.lane + "'.";
1169  return false;
1170  }
1171  }
1172  if (MSGlobals::gUseMesoSim) {
1173  stop.segment = MSGlobals::gMesoNet->getSegmentForEdge(stop.lane->getEdge(), stop.getEndPos(*this));
1174  if (stop.lane->isInternal()) {
1175  errorMsg = "Mesoscopic simulation does not allow stopping on internal edge '" + stopPar.edge + "' for vehicle '" + myParameter->id + "'.";
1176  return false;
1177  }
1178  }
1179  stop.initPars(stopPar);
1180  if (stopPar.until != -1) {
1181  // !!! it would be much cleaner to invent a constructor for stops which takes "until" as an argument
1182  const_cast<SUMOVehicleParameter::Stop&>(stop.pars).until += untilOffset;
1183  }
1184  if (stopPar.arrival != -1) {
1185  const_cast<SUMOVehicleParameter::Stop&>(stop.pars).arrival += untilOffset;
1186  }
1187  std::string stopType = "stop";
1188  std::string stopID = "";
1189  if (stop.busstop != nullptr) {
1190  stopType = "busStop";
1191  stopID = stop.busstop->getID();
1192  } else if (stop.containerstop != nullptr) {
1193  stopType = "containerStop";
1194  stopID = stop.containerstop->getID();
1195  } else if (stop.chargingStation != nullptr) {
1196  stopType = "chargingStation";
1197  stopID = stop.chargingStation->getID();
1198  } else if (stop.overheadWireSegment != nullptr) {
1199  stopType = "overheadWireSegment";
1200  stopID = stop.overheadWireSegment->getID();
1201  } else if (stop.parkingarea != nullptr) {
1202  stopType = "parkingArea";
1203  stopID = stop.parkingarea->getID();
1204  }
1205  const std::string errorMsgStart = stopID == "" ? stopType : stopType + " '" + stopID + "'";
1206 
1207  if (stop.pars.startPos < 0 || stop.pars.endPos > stop.lane->getLength()) {
1208  errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' has an invalid position.";
1209  return false;
1210  }
1211  if (stopType != "stop" && stopType != "parkingArea" && myType->getLength() / 2. > stop.pars.endPos - stop.pars.startPos
1212  && MSNet::getInstance()->warnOnce(stopType + ":" + stopID)) {
1213  errorMsg = errorMsgStart + " on lane '" + stop.lane->getID() + "' is too short for vehicle '" + myParameter->id + "'.";
1214  }
1215  if (stopType == "parkingArea" && !stop.parkingarea->accepts(this)) {
1216  // forbid access in case the parking requests other badges
1217  errorMsg = errorMsgStart + "on lane '" + stop.lane->getID() + "' forbids access because vehicle '" + myParameter->id + "' does not provide any valid badge.";
1218  return false;
1219  }
1220  const MSEdge* stopLaneEdge = &stop.lane->getEdge();
1221  const MSEdge* stopEdge;
1222  if (stopLaneEdge->getOppositeEdge() != nullptr && stopLaneEdge->getOppositeEdge()->getID() == stopPar.edge) {
1223  // stop lane is on the opposite side
1224  stopEdge = stopLaneEdge->getOppositeEdge();
1225  stop.isOpposite = true;
1226  } else {
1227  // if stop is on an internal edge the normal edge before the intersection is used
1228  stopEdge = stopLaneEdge->getNormalBefore();
1229  }
1230  MSRouteIterator succ = myCurrEdge + 1; // we're using the address but only within the scope of this function (and recursive calls)
1231  if (searchStart == nullptr) {
1232  searchStart = &myCurrEdge;
1233  if (stopLaneEdge->isNormal() && getLane() != nullptr && getLane()->isInternal()) {
1234  // already on the intersection but myCurrEdge is before it
1235  searchStart = &succ;
1236  }
1237  }
1238 #ifdef DEBUG_ADD_STOP
1239  if (DEBUG_COND) {
1240  std::cout << "addStop desc=" << stop.getDescription() << " stopEdge=" << stopEdge->getID()
1241  << " searchStart=" << ((*searchStart) == myRoute->end() ? "END" : (**searchStart)->getID())
1242  << " index=" << (int)((*searchStart) - myRoute->begin()) << " route=" << toString(myRoute->getEdges())
1243  << "\n";
1244  }
1245 #endif
1246  stop.edge = std::find(*searchStart, myRoute->end(), stopEdge);
1247  MSRouteIterator prevStopEdge = myCurrEdge;
1248  const MSEdge* prevEdge = (getLane() == nullptr ? getEdge() : &getLane()->getEdge());
1249  double prevStopPos = getPositionOnLane();
1250  // where to insert the stop
1251  std::list<MSStop>::iterator iter = myStops.begin();
1252  if (stopPar.index == STOP_INDEX_END || stopPar.index >= static_cast<int>(myStops.size())) {
1253  iter = myStops.end();
1254  if (myStops.size() > 0 && myStops.back().edge >= *searchStart) {
1255  prevStopEdge = myStops.back().edge;
1256  prevEdge = &myStops.back().lane->getEdge();
1257  prevStopPos = myStops.back().pars.endPos;
1258  stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1259  if (prevStopEdge == stop.edge // laneEdge check is insufficient for looped routes
1260  && prevEdge == &stop.lane->getEdge() // route iterator check insufficient for internal lane stops
1261  && prevStopPos > stop.pars.endPos) {
1262  stop.edge = std::find(prevStopEdge + 1, myRoute->end(), stopEdge);
1263  }
1264 #ifdef DEBUG_ADD_STOP
1265  if (DEBUG_COND) {
1266  std::cout << " (@end) prevStopEdge=" << (*prevStopEdge)->getID() << " index=" << (int)(prevStopEdge - myRoute->begin())
1267  << " foundIndex=" << (stop.edge == myRoute->end() ? -1 : (int)(stop.edge - myRoute->begin())) << "\n";
1268  }
1269 #endif
1270  }
1271  } else {
1272  if (stopPar.index == STOP_INDEX_FIT) {
1273  while (iter != myStops.end() && (iter->edge < stop.edge ||
1274  (iter->pars.endPos < stop.pars.endPos && iter->edge == stop.edge) ||
1275  (stop.lane->getEdge().isInternal() && iter->edge == stop.edge))) {
1276  prevStopEdge = iter->edge;
1277  prevStopPos = iter->pars.endPos;
1278  ++iter;
1279  }
1280  } else {
1281  int index = stopPar.index;
1282  while (index > 0) {
1283  prevStopEdge = iter->edge;
1284  prevStopPos = iter->pars.endPos;
1285  ++iter;
1286  --index;
1287  }
1288 #ifdef DEBUG_ADD_STOP
1289  if (DEBUG_COND) {
1290  std::cout << " (@fit) prevStopEdge=" << (*prevStopEdge)->getID() << " index=" << (int)(prevStopEdge - myRoute->begin()) << "\n";
1291  }
1292 #endif
1293  stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1294  }
1295  }
1296  const bool wasTooClose = errorMsg != "" && errorMsg.find("too close") != std::string::npos;
1297  if (stop.edge == myRoute->end()) {
1298  if (!wasTooClose) {
1299  errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is not downstream the current route.";
1300  }
1301  return false;
1302  }
1303 
1304  const bool tooClose = (prevStopEdge == stop.edge && prevEdge == &stop.lane->getEdge() &&
1305  prevStopPos + (iter == myStops.begin() ? getBrakeGap() : 0) > stop.pars.endPos + POSITION_EPS);
1306 
1307  if (prevStopEdge > stop.edge ||
1308  // a collision-stop happens after vehicle movement and may move the
1309  // vehicle backwards on its lane (prevStopPos is the vehicle position)
1310  (tooClose && !stop.pars.collision)
1311  || (stop.lane->getEdge().isInternal() && stop.lane->getNextNormal() != *(stop.edge + 1))) {
1312  // check if the edge occurs again later in the route
1313  //std::cout << " could not add stop " << errorMsgStart << " prevStops=" << myStops.size() << " searchStart=" << (*searchStart - myRoute->begin()) << " route=" << toString(myRoute->getEdges()) << "\n";
1314  if (tooClose && prevStopPos <= stop.pars.endPos + POSITION_EPS) {
1315  errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.pars.lane + "' is too close to brake.";
1316  }
1317  MSRouteIterator next = stop.edge + 1;
1318  return addStop(stopPar, errorMsg, untilOffset, &next);
1319  }
1320  if (wasTooClose) {
1321  errorMsg = "";
1322  }
1323  // David.C:
1324  //if (!stop.parking && (myCurrEdge == stop.edge && myState.myPos > stop.endPos - getCarFollowModel().brakeGap(myState.mySpeed))) {
1325  const double endPosOffset = stop.lane->getEdge().isInternal() ? (*stop.edge)->getLength() : 0;
1326  const double distToStop = stop.pars.endPos + endPosOffset - getPositionOnLane();
1327  if (stop.pars.collision && !handleCollisionStop(stop, distToStop)) {
1328  return false;
1329  }
1330  if (!hasDeparted() && myCurrEdge == stop.edge) {
1331  double pos = -1;
1333  pos = myParameter->departPos;
1334  if (pos < 0.) {
1335  pos += (*myCurrEdge)->getLength();
1336  }
1337  }
1339  pos = MIN2(stop.pars.endPos + endPosOffset, basePos(*myCurrEdge));
1340  }
1341  if (pos > stop.pars.endPos + endPosOffset) {
1342  if (stop.edge != myRoute->end()) {
1343  // check if the edge occurs again later in the route
1344  MSRouteIterator next = stop.edge + 1;
1345  return addStop(stopPar, errorMsg, untilOffset, &next);
1346  }
1347  errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is before departPos.";
1348  return false;
1349  }
1350  }
1351  if (iter != myStops.begin()) {
1352  std::list<MSStop>::iterator iter2 = iter;
1353  iter2--;
1354  if (stop.getUntil() >= 0 && iter2->getUntil() > stop.getUntil()
1355  && (!MSGlobals::gUseStopEnded || iter2->pars.ended < 0 || stop.pars.ended >= 0)) {
1356  errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1357  + "' set to end at " + time2string(stop.getUntil())
1358  + " earlier than previous stop at " + time2string(iter2->getUntil()) + ".";
1359  }
1360  if (stop.pars.arrival >= 0 && iter2->pars.arrival > stop.pars.arrival) {
1361  errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1362  + "' set to start at " + time2string(stop.pars.arrival)
1363  + " earlier than previous stop end at " + time2string(iter2->getUntil()) + ".";
1364  }
1365  if (stop.pars.arrival >= 0 && iter2->pars.arrival > stop.pars.arrival) {
1366  errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1367  + "' set to start at " + time2string(stop.pars.arrival)
1368  + " earlier than previous stop arrival at " + time2string(iter2->pars.arrival) + ".";
1369  }
1370  } else {
1371  if (stop.getUntil() >= 0 && getParameter().depart > stop.getUntil()) {
1372  errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1373  + "' set to end at " + time2string(stop.getUntil())
1374  + " earlier than departure at " + time2string(getParameter().depart) + ".";
1375  }
1376  }
1377  if (stop.getUntil() >= 0 && stop.pars.arrival > stop.getUntil() && errorMsg == "") {
1378  errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1379  + "' set to end at " + time2string(stop.getUntil())
1380  + " earlier than arrival at " + time2string(stop.pars.arrival) + ".";
1381  }
1382  myStops.insert(iter, stop);
1383  //std::cout << " added stop " << errorMsgStart << " totalStops=" << myStops.size() << " searchStart=" << (*searchStart - myRoute->begin())
1384  // << " routeIndex=" << (stop.edge - myRoute->begin())
1385  // << " stopIndex=" << std::distance(myStops.begin(), iter)
1386  // << " route=" << toString(myRoute->getEdges()) << "\n";
1387  return true;
1388 }
1389 
1390 
1391 void
1392 MSBaseVehicle::addStops(const bool ignoreStopErrors, MSRouteIterator* searchStart, bool addRouteStops) {
1393  if (addRouteStops) {
1394  for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
1395  std::string errorMsg;
1396  if (!addStop(stop, errorMsg, myParameter->depart, searchStart) && !ignoreStopErrors) {
1397  throw ProcessError(errorMsg);
1398  }
1399  if (errorMsg != "") {
1400  WRITE_WARNING(errorMsg);
1401  }
1402  }
1403  }
1405  for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
1406  std::string errorMsg;
1407  if (!addStop(stop, errorMsg, untilOffset, searchStart) && !ignoreStopErrors) {
1408  throw ProcessError(errorMsg);
1409  }
1410  if (errorMsg != "") {
1411  WRITE_WARNING(errorMsg);
1412  }
1413  }
1414 }
1415 
1416 
1417 bool
1419  MSRouteIterator start = myCurrEdge;
1420  const std::string err = "for vehicle '" + getID() + "' at time=" + time2string(SIMSTEP);
1421  int i = 0;
1422  bool ok = true;
1423  double lastPos = getPositionOnLane();
1424  if (getLane() != nullptr && getLane()->isInternal()
1425  && myStops.size() > 0 && !myStops.front().lane->isInternal()) {
1426  // start edge is still incoming to the intersection so lastPos
1427  // relative to that edge must be adapted
1428  lastPos += (*myCurrEdge)->getLength();
1429  }
1430  for (const MSStop& stop : myStops) {
1431  const double endPos = stop.getEndPos(*this);
1432  MSRouteIterator it;
1433  const std::string prefix = "Stop " + toString(i) + " on edge '" + stop.lane->getEdge().getID() + "' ";
1434  if (stop.lane->isInternal()) {
1435  // find the normal predecessor and ensure that the next route edge
1436  // matches the successor of the internal edge successor
1437  it = std::find(start, myRoute->end(), stop.lane->getEdge().getNormalBefore());
1438  if (it != myRoute->end() && (
1439  it + 1 == myRoute->end() || *(it + 1) != stop.lane->getEdge().getNormalSuccessor())) {
1440  it = myRoute->end(); // signal failure
1441  }
1442  } else {
1443  const MSEdge* const stopEdge = &stop.lane->getEdge();
1444  it = std::find(start, myRoute->end(), stopEdge);
1445  }
1446  if (it == myRoute->end()) {
1447  if (!silent) {
1448  WRITE_ERROR(prefix + "is not found after edge '" + (*start)->getID() + "' (" + toString(start - myCurrEdge) + " after current " + err);
1449  }
1450  ok = false;
1451  } else {
1452  MSRouteIterator it2;
1453  for (it2 = myRoute->begin(); it2 != myRoute->end(); it2++) {
1454  if (it2 == stop.edge) {
1455  break;
1456  }
1457  }
1458  if (it2 == myRoute->end()) {
1459  if (!silent) {
1460  WRITE_ERROR(prefix + "used invalid route index " + err);
1461  }
1462  ok = false;
1463  } else if (it2 < start) {
1464  if (!silent) {
1465  WRITE_ERROR(prefix + "used invalid (relative) route index " + toString(it2 - myCurrEdge) + " expected after " + toString(start - myCurrEdge) + " " + err);
1466  }
1467  ok = false;
1468  } else {
1469  if (it != stop.edge) {
1470  double brakeGap = i == 0 ? getBrakeGap() : 0;
1471  if (endPos >= lastPos + brakeGap) {
1472  if (!silent) {
1473  WRITE_WARNING(prefix + "is used in " + toString(stop.edge - myCurrEdge) + " edges but first encounter is in "
1474  + toString(it - myCurrEdge) + " edges " + err);
1475  }
1476  }
1477  }
1478  start = stop.edge;
1479  }
1480  }
1481  lastPos = endPos;
1482  i++;
1483  }
1484  return ok;
1485 }
1486 
1487 
1488 const ConstMSEdgeVector
1489 MSBaseVehicle::getStopEdges(double& firstPos, double& lastPos, std::set<int>& jumps) const {
1490  assert(haveValidStopEdges());
1491  ConstMSEdgeVector result;
1492  const MSStop* prev = nullptr;
1493  const MSEdge* internalSuccessor = nullptr;
1494  for (const MSStop& stop : myStops) {
1495  if (stop.reached) {
1496  if (stop.pars.jump >= 0) {
1497  jumps.insert((int)result.size());
1498  }
1499  continue;
1500  }
1501  const double stopPos = stop.getEndPos(*this);
1502  if ((prev == nullptr
1503  || prev->edge != stop.edge
1504  || (prev->lane == stop.lane && prev->getEndPos(*this) > stopPos))
1505  && *stop.edge != internalSuccessor) {
1506  result.push_back(*stop.edge);
1507  if (stop.lane->isInternal()) {
1508  internalSuccessor = stop.lane->getNextNormal();
1509  result.push_back(internalSuccessor);
1510  } else {
1511  internalSuccessor = nullptr;
1512  }
1513  }
1514  prev = &stop;
1515  if (firstPos < 0) {
1516  firstPos = stopPos;
1517  }
1518  lastPos = stopPos;
1519  if (stop.pars.jump >= 0) {
1520  jumps.insert((int)result.size() - 1);
1521  }
1522  }
1523  //std::cout << "getStopEdges veh=" << getID() << " result=" << toString(result) << "\n";
1524  return result;
1525 }
1526 
1527 
1528 std::vector<std::pair<int, double> >
1530  std::vector<std::pair<int, double> > result;
1531  for (std::list<MSStop>::const_iterator iter = myStops.begin(); iter != myStops.end(); ++iter) {
1532  result.push_back(std::make_pair(
1533  (int)(iter->edge - myRoute->begin()),
1534  iter->getEndPos(*this)));
1535  }
1536  return result;
1537 }
1538 
1539 
1540 MSStop&
1542  assert(myStops.size() > 0);
1543  return myStops.front();
1544 }
1545 
1546 SUMOTime
1548  if (isStopped()) {
1549  return myStops.front().duration;
1550  } else {
1551  return 0;
1552  }
1553 }
1554 
1555 
1556 MSStop&
1557 MSBaseVehicle::getStop(int nextStopIndex) {
1558  if (nextStopIndex < 0 || (int)myStops.size() <= nextStopIndex) {
1559  throw InvalidArgument("Invalid stop index " + toString(nextStopIndex) + " (has " + toString(myStops.size()) + " stops)");
1560  }
1561  auto stopIt = myStops.begin();
1562  std::advance(stopIt, nextStopIndex);
1563  return *stopIt;
1564 }
1565 
1566 
1569  if (hasStops()) {
1570  return &myStops.front().pars;
1571  }
1572  return nullptr;
1573 }
1574 
1575 
1576 bool
1578  //if the stop exists update the duration
1579  for (std::list<MSStop>::iterator iter = myStops.begin(); iter != myStops.end(); iter++) {
1580  if (iter->lane->getID() == stop.lane && fabs(iter->pars.endPos - stop.endPos) < POSITION_EPS) {
1581  // update existing stop
1582  if (stop.duration == 0 && stop.until < 0 && !iter->reached) {
1583  myStops.erase(iter);
1584  } else {
1585  iter->duration = stop.duration;
1586  iter->triggered = stop.triggered;
1587  iter->containerTriggered = stop.containerTriggered;
1588  const_cast<SUMOVehicleParameter::Stop&>(iter->pars).until = stop.until;
1589  const_cast<SUMOVehicleParameter::Stop&>(iter->pars).parking = stop.parking;
1590  }
1591  return true;
1592  }
1593  }
1594  const bool result = addStop(stop, errorMsg);
1595  if (result) {
1597  myParameter->stops.push_back(stop);
1598  }
1599  return result;
1600 }
1601 
1602 
1603 bool
1604 MSBaseVehicle::abortNextStop(int nextStopIndex) {
1605  if (hasStops() && nextStopIndex < (int)myStops.size()) {
1606  if (nextStopIndex == 0 && isStopped()) {
1608  } else {
1609  auto stopIt = myStops.begin();
1610  std::advance(stopIt, nextStopIndex);
1611  myStops.erase(stopIt);
1612  }
1613  if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
1614  // stops will be rebuilt from scratch on rerouting so we must patch the stops in myParameter
1615  auto stopIt2 = myParameter->stops.begin();
1616  std::advance(stopIt2, nextStopIndex);
1617  const_cast<SUMOVehicleParameter*>(myParameter)->stops.erase(stopIt2);
1618  }
1619  return true;
1620  } else {
1621  return false;
1622  }
1623 }
1624 
1625 
1626 bool
1627 MSBaseVehicle::replaceStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string& info, bool teleport, std::string& errorMsg) {
1628  const int n = (int)myStops.size();
1629  if (nextStopIndex < 0 || nextStopIndex >= n) {
1630  errorMsg = ("Invalid nextStopIndex '" + toString(nextStopIndex) + "' for " + toString(n) + " remaining stops");
1631  return false;
1632  }
1633  if (nextStopIndex == 0 && isStopped()) {
1634  errorMsg = "Cannot replace reached stop";
1635  return false;
1636  }
1638  MSLane* stopLane = MSLane::dictionary(stop.lane);
1639  MSEdge* stopEdge = &stopLane->getEdge();
1640 
1641  auto itStop = myStops.begin();
1642  std::advance(itStop, nextStopIndex);
1643  MSStop& replacedStop = *itStop;
1644 
1645  // check parking access rights
1646  if (stop.parkingarea != "") {
1648  if (pa != nullptr && !pa->accepts(this)) {
1649  errorMsg = "Vehicle '" + getID() + "' does not have the right badge to access parkingArea '" + stop.parkingarea + "'.";
1650  return false;
1651  }
1652  }
1653 
1654  if (replacedStop.lane == stopLane && replacedStop.pars.endPos == stop.endPos && !teleport) {
1655  // only replace stop attributes
1656  const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
1657  replacedStop.initPars(stop);
1658  return true;
1659  }
1660 
1661  if (!stopLane->allowsVehicleClass(getVClass(), myRoutingMode)) {
1662  errorMsg = ("Disallowed stop lane '" + stopLane->getID() + "'");
1663  return false;
1664  }
1665 
1666  const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
1667  std::vector<MSStop> stops(myStops.begin(), myStops.end());
1668  const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
1669  MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
1670  double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
1671  MSRouteIterator itEnd = nextStopIndex == n - 1 ? oldEdges.end() - 1 : stops[nextStopIndex + 1].edge;
1672  auto endPos = nextStopIndex == n - 1 ? getArrivalPos() : stops[nextStopIndex + 1].pars.endPos;
1674 
1675  bool newDestination = nextStopIndex == n - 1 && stops[nextStopIndex].edge == oldEdges.end() - 1;
1676 
1677  ConstMSEdgeVector toNewStop;
1678  if (!teleport) {
1679  router.compute(*itStart, startPos, stopEdge, stop.endPos, this, t, toNewStop, true);
1680  if (toNewStop.size() == 0) {
1681  errorMsg = "No route found from edge '" + (*itStart)->getID() + "' to stop edge '" + stopEdge->getID() + "'";
1682  return false;
1683  }
1684  }
1685 
1686  ConstMSEdgeVector fromNewStop;
1687  if (!newDestination) {
1688  router.compute(stopEdge, stop.endPos, *itEnd, endPos, this, t, fromNewStop, true);
1689  if (fromNewStop.size() == 0) {
1690  errorMsg = "No route found from stop edge '" + stopEdge->getID() + "' to edge '" + (*itEnd)->getID() + "'";
1691  return false;
1692  }
1693  }
1694 
1695  const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
1696  replacedStop.initPars(stop);
1697  replacedStop.edge = myRoute->end(); // will be patched in replaceRoute
1698  replacedStop.lane = stopLane;
1699  if (MSGlobals::gUseMesoSim) {
1700  replacedStop.segment = MSGlobals::gMesoNet->getSegmentForEdge(replacedStop.lane->getEdge(), replacedStop.getEndPos(*this));
1701  if (replacedStop.lane->isInternal()) {
1702  errorMsg = "Mesoscopic simulation does not allow stopping on internal edge '" + stop.edge + "' for vehicle '" + getID() + "'.";
1703  return false;
1704  }
1705  }
1706 
1707  ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
1708  ConstMSEdgeVector newEdges; // only remaining
1709  newEdges.insert(newEdges.end(), myCurrEdge, itStart);
1710  if (!teleport) {
1711  newEdges.insert(newEdges.end(), toNewStop.begin(), toNewStop.end() - 1);
1712  } else {
1713  newEdges.push_back(*itStart);
1714  }
1715  if (!newDestination) {
1716  newEdges.insert(newEdges.end(), fromNewStop.begin(), fromNewStop.end() - 1);
1717  newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
1718  } else {
1719  newEdges.push_back(stopEdge);
1720  }
1721  //std::cout << SIMTIME << " replaceStop veh=" << getID()
1722  // << " teleport=" << teleport
1723  // << " busStop=" << stop.busstop
1724  // << " oldEdges=" << oldRemainingEdges.size()
1725  // << " newEdges=" << newEdges.size()
1726  // << " toNewStop=" << toNewStop.size()
1727  // << " fromNewStop=" << fromNewStop.size()
1728  // << "\n";
1729 
1730  const double routeCost = router.recomputeCosts(newEdges, this, t);
1731  const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
1732  const double savings = previousCost - routeCost;
1733  if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
1734  // stops will be rebuilt from scratch so we must patch the stops in myParameter
1735  const_cast<SUMOVehicleParameter*>(myParameter)->stops[nextStopIndex] = stop;
1736  }
1737  if (teleport) {
1738  // let the vehicle jump rather than teleport
1739  // we add a jump-stop at the end of the edge (unless the vehicle is
1740  // already configure to jump before the replaced stop)
1741  if (!insertJump(nextStopIndex, itStart, errorMsg)) {
1742  return false;
1743  };
1744  }
1745  return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
1746 }
1747 
1748 
1749 bool
1750 MSBaseVehicle::rerouteBetweenStops(int nextStopIndex, const std::string& info, bool teleport, std::string& errorMsg) {
1751  const int n = (int)myStops.size();
1752  if (nextStopIndex < 0 || nextStopIndex > n) {
1753  errorMsg = ("Invalid nextStopIndex '" + toString(nextStopIndex) + "' for " + toString(n) + " remaining stops");
1754  return false;
1755  }
1756  if (nextStopIndex == 0 && isStopped()) {
1757  errorMsg = "Cannot reroute towards reached stop";
1758  return false;
1759  }
1761 
1762  const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
1763  std::vector<MSStop> stops(myStops.begin(), myStops.end());
1764  const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
1765  MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
1766  double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
1767  MSRouteIterator itEnd = nextStopIndex == n ? oldEdges.end() - 1 : stops[nextStopIndex].edge;
1768  auto endPos = nextStopIndex == n ? getArrivalPos() : stops[nextStopIndex].pars.endPos;
1770 
1771  ConstMSEdgeVector newBetween;
1772  if (!teleport) {
1773  router.compute(*itStart, startPos, *itEnd, endPos, this, t, newBetween, true);
1774  if (newBetween.size() == 0) {
1775  errorMsg = "No route found from edge '" + (*itStart)->getID() + "' to stop edge '" + (*itEnd)->getID() + "'";
1776  return false;
1777  }
1778  }
1779 
1780  ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
1781  ConstMSEdgeVector newEdges; // only remaining
1782  newEdges.insert(newEdges.end(), myCurrEdge, itStart);
1783  if (!teleport) {
1784  newEdges.insert(newEdges.end(), newBetween.begin(), newBetween.end() - 1);
1785  } else {
1786  newEdges.push_back(*itStart);
1787  }
1788  newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
1789  //std::cout << SIMTIME << " rerouteBetweenStops veh=" << getID()
1790  // << " oldEdges=" << oldRemainingEdges.size()
1791  // << " newEdges=" << newEdges.size()
1792  // << " toNewStop=" << toNewStop.size()
1793  // << " fromNewStop=" << fromNewStop.size()
1794  // << "\n";
1795 
1796  const double routeCost = router.recomputeCosts(newEdges, this, t);
1797  const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
1798  const double savings = previousCost - routeCost;
1799 
1800  if (teleport) {
1801  // let the vehicle jump rather than teleport
1802  // we add a jump-stop at the end of the edge (unless the vehicle is
1803  // already configure to jump before the replaced stop)
1804  if (!insertJump(nextStopIndex, itStart, errorMsg)) {
1805  return false;
1806  };
1807  }
1808  return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
1809 }
1810 
1811 
1812 bool
1813 MSBaseVehicle::insertJump(int nextStopIndex, MSRouteIterator itStart, std::string& errorMsg) {
1814  bool needJump = true;
1815  if (nextStopIndex > 0) {
1816  auto itPriorStop = myStops.begin();
1817  std::advance(itPriorStop, nextStopIndex - 1);
1818  const MSStop& priorStop = *itPriorStop;
1819  if (priorStop.pars.jump >= 0) {
1820  needJump = false;
1821  }
1822  }
1823  if (needJump) {
1824  SUMOVehicleParameter::Stop jumpStopPars;
1825  jumpStopPars.endPos = (*itStart)->getLength();
1826  jumpStopPars.speed = 1000;
1827  jumpStopPars.jump = 0;
1828  jumpStopPars.edge = (*itStart)->getID();
1829  jumpStopPars.parametersSet = STOP_SPEED_SET | STOP_JUMP_SET;
1830  MSLane* jumpStopLane = nullptr;
1831  for (MSLane* cand : (*itStart)->getLanes()) {
1832  if (cand->allowsVehicleClass(getVClass())) {
1833  jumpStopLane = cand;
1834  break;
1835  }
1836  }
1837  if (jumpStopLane == nullptr) {
1838  errorMsg = "Unable to replace stop with teleporting\n";
1839  return false;
1840  }
1841  auto itStop = myStops.begin();
1842  std::advance(itStop, nextStopIndex);
1843  MSStop jumpStop(jumpStopPars);
1844  jumpStop.initPars(jumpStopPars);
1845  jumpStop.lane = jumpStopLane;
1846  jumpStop.edge = myRoute->end(); // will be patched in replaceRoute
1847  myStops.insert(itStop, jumpStop);
1848  if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
1849  // stops will be rebuilt from scratch so we must patch the stops in myParameter
1850  auto it = myParameter->stops.begin() + nextStopIndex;
1851  const_cast<SUMOVehicleParameter*>(myParameter)->stops.insert(it, jumpStopPars);
1852  }
1853  }
1854  return true;
1855 }
1856 
1857 
1858 bool
1859 MSBaseVehicle::insertStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string& info, bool teleport, std::string& errorMsg) {
1860  const int n = (int)myStops.size();
1861  if (nextStopIndex < 0 || nextStopIndex > n) {
1862  errorMsg = ("Invalid nextStopIndex '" + toString(nextStopIndex) + "' for " + toString(n) + " remaining stops");
1863  return false;
1864  }
1865  if (nextStopIndex == 0 && isStopped()) {
1866  errorMsg = "Cannot insert stop before the currently reached stop";
1867  return false;
1868  }
1870  MSLane* stopLane = MSLane::dictionary(stop.lane);
1871  MSEdge* stopEdge = &stopLane->getEdge();
1872 
1873  if (!stopLane->allowsVehicleClass(getVClass(), myRoutingMode)) {
1874  errorMsg = ("Disallowed stop lane '" + stopLane->getID() + "'");
1875  return false;
1876  }
1877 
1878  // check parking access rights
1879  if (stop.parkingarea != "") {
1881  if (pa != nullptr && !pa->accepts(this)) {
1882  errorMsg = "Vehicle '" + getID() + "' does not have the right badge to access parkingArea '" + stop.parkingarea + "'.";
1883  return false;
1884  }
1885  }
1886 
1887  const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
1888  std::vector<MSStop> stops(myStops.begin(), myStops.end());
1889  const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
1890  MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
1891  double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
1892  MSRouteIterator itEnd = nextStopIndex == n ? oldEdges.end() - 1 : stops[nextStopIndex].edge;
1893  auto endPos = nextStopIndex == n ? getArrivalPos() : stops[nextStopIndex].pars.endPos;
1895 
1896  bool newDestination = nextStopIndex == n && stopEdge == oldEdges.back();
1897 
1898  ConstMSEdgeVector toNewStop;
1899  if (!teleport) {
1900  router.compute(*itStart, startPos, stopEdge, stop.endPos, this, t, toNewStop, true);
1901  if (toNewStop.size() == 0) {
1902  errorMsg = "No route found from edge '" + (*itStart)->getID() + "' to stop edge '" + stopEdge->getID() + "'";
1903  return false;
1904  }
1905  }
1906 
1907  ConstMSEdgeVector fromNewStop;
1908  if (!newDestination) {
1909  router.compute(stopEdge, stop.endPos, *itEnd, endPos, this, t, fromNewStop, true);
1910  if (fromNewStop.size() == 0) {
1911  errorMsg = "No route found from stop edge '" + stopEdge->getID() + "' to edge '" + (*itEnd)->getID() + "'";
1912  return false;
1913  }
1914  }
1915 
1916  auto itStop = myStops.begin();
1917  std::advance(itStop, nextStopIndex);
1918  MSStop newStop(stop);
1919  newStop.initPars(stop);
1920  newStop.edge = myRoute->end(); // will be patched in replaceRoute
1921  newStop.lane = stopLane;
1922  if (MSGlobals::gUseMesoSim) {
1923  newStop.segment = MSGlobals::gMesoNet->getSegmentForEdge(newStop.lane->getEdge(), newStop.getEndPos(*this));
1924  if (newStop.lane->isInternal()) {
1925  errorMsg = "Mesoscopic simulation does not allow stopping on internal edge '" + stop.edge + "' for vehicle '" + getID() + "'.";
1926  return false;
1927  }
1928  }
1929  myStops.insert(itStop, newStop);
1930 
1931  ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
1932  ConstMSEdgeVector newEdges; // only remaining
1933  newEdges.insert(newEdges.end(), myCurrEdge, itStart);
1934  if (!teleport) {
1935  newEdges.insert(newEdges.end(), toNewStop.begin(), toNewStop.end() - 1);
1936  } else {
1937  newEdges.push_back(*itStart);
1938  }
1939  if (!newDestination) {
1940  newEdges.insert(newEdges.end(), fromNewStop.begin(), fromNewStop.end() - 1);
1941  newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
1942  } else {
1943  newEdges.push_back(stopEdge);
1944  }
1945  //std::cout << SIMTIME << " insertStop veh=" << getID()
1946  // << " teleport=" << teleport
1947  // << " busStop=" << stop.busstop
1948  // << " oldEdges=" << oldRemainingEdges.size()
1949  // << " newEdges=" << newEdges.size()
1950  // << " toNewStop=" << toNewStop.size()
1951  // << " fromNewStop=" << fromNewStop.size()
1952  // << "\n";
1953 
1954  const double routeCost = router.recomputeCosts(newEdges, this, t);
1955  const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
1956  const double savings = previousCost - routeCost;
1957 
1958  if (!hasDeparted() && (int)myParameter->stops.size() >= nextStopIndex) {
1959  // stops will be rebuilt from scratch so we must patch the stops in myParameter
1960  auto it = myParameter->stops.begin() + nextStopIndex;
1961  const_cast<SUMOVehicleParameter*>(myParameter)->stops.insert(it, stop);
1962  }
1963  return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
1964 }
1965 
1966 
1967 double
1969  if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
1970  MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
1971  return batteryOfVehicle->getActualBatteryCapacity();
1972  } else {
1973  if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
1974  MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
1975  return batteryOfVehicle->getActualBatteryCapacity();
1976  }
1977  }
1978 
1979  return -1;
1980 }
1981 
1982 
1983 double
1985  if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
1986  MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
1987  return batteryOfVehicle->getActualBatteryCapacity() / batteryOfVehicle->getMaximumBatteryCapacity();
1988  } else {
1989  if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
1990  MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
1991  return batteryOfVehicle->getActualBatteryCapacity() / batteryOfVehicle->getMaximumBatteryCapacity();
1992  }
1993  }
1994 
1995  return -1;
1996 }
1997 
1998 
1999 double
2001  if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2002  MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2003  return batteryOfVehicle->getEnergyCharged();
2004  } else {
2005  if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2006  MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2007  return batteryOfVehicle->getEnergyCharged();
2008  }
2009  }
2010 
2011  return -1;
2012 }
2013 
2014 
2015 double
2017  if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2018  MSDevice_ElecHybrid* elecHybridDevice = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2019  return elecHybridDevice->getCurrentFromOverheadWire();
2020  }
2021 
2022  return NAN;
2023 }
2024 
2025 double
2027  if (isOnRoad() || isIdling()) {
2029  } else {
2030  return 0.;
2031  }
2032 }
2033 
2034 
2035 const MSEdgeWeightsStorage&
2037  return _getWeightsStorage();
2038 }
2039 
2040 
2043  return _getWeightsStorage();
2044 }
2045 
2046 
2049  if (myEdgeWeights == nullptr) {
2051  }
2052  return *myEdgeWeights;
2053 }
2054 
2055 
2056 
2057 
2058 int
2060  int boarded = myPersonDevice == nullptr ? 0 : myPersonDevice->size();
2061  return boarded + myParameter->personNumber;
2062 }
2063 
2064 int
2066  int leavingPersonNumber = 0;
2067  const std::vector<MSTransportable*>& persons = getPersons();
2068  for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
2069  MSStageDriving* const stage = dynamic_cast<MSStageDriving*>((*it_p)->getCurrentStage());
2070  const MSStop* stop = &myStops.front();
2071  const MSVehicle* joinVeh = dynamic_cast<MSVehicle*>(MSNet::getInstance()->getVehicleControl().getVehicle((*stop).pars.join));
2072  if (stop && stage->canLeaveVehicle(*it_p, *this, *stop) && !MSDevice_Transportable::willTransferAtJoin(*it_p, joinVeh)) {
2073  leavingPersonNumber++;
2074  }
2075  }
2076  return leavingPersonNumber;
2077 }
2078 
2079 std::vector<std::string>
2081  std::vector<std::string> ret;
2082  const std::vector<MSTransportable*>& persons = getPersons();
2083  for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
2084  ret.push_back((*it_p)->getID());
2085  }
2086  return ret;
2087 }
2088 
2089 int
2091  int loaded = myContainerDevice == nullptr ? 0 : myContainerDevice->size();
2092  return loaded + myParameter->containerNumber;
2093 }
2094 
2095 
2096 void
2098  // this might be called from the MSTransportable destructor so we cannot do a dynamic cast to determine the type
2099  if (myPersonDevice != nullptr) {
2101  }
2102  if (myContainerDevice != nullptr) {
2104  }
2105 }
2106 
2107 
2108 const std::vector<MSTransportable*>&
2110  if (myPersonDevice == nullptr) {
2112  } else {
2114  }
2115 }
2116 
2117 
2118 const std::vector<MSTransportable*>&
2120  if (myContainerDevice == nullptr) {
2122  } else {
2124  }
2125 }
2126 
2127 
2128 bool
2129 MSBaseVehicle::isLineStop(double position) const {
2130  if (myParameter->line == "") {
2131  // not a public transport line
2132  return false;
2133  }
2134  for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
2135  if (stop.startPos <= position && position <= stop.endPos) {
2136  return true;
2137  }
2138  }
2139  for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
2140  if (stop.startPos <= position && position <= stop.endPos) {
2141  return true;
2142  }
2143  }
2144  return false;
2145 }
2146 
2147 
2148 bool
2149 MSBaseVehicle::hasDevice(const std::string& deviceName) const {
2150  for (MSDevice* const dev : myDevices) {
2151  if (dev->deviceName() == deviceName) {
2152  return true;
2153  }
2154  }
2155  return false;
2156 }
2157 
2158 
2159 void
2160 MSBaseVehicle::createDevice(const std::string& deviceName) {
2161  if (!hasDevice(deviceName)) {
2162  if (deviceName == "rerouting") {
2163  ((SUMOVehicleParameter*)myParameter)->setParameter("has." + deviceName + ".device", "true");
2165  if (hasDeparted()) {
2166  // vehicle already departed: disable pre-insertion rerouting and enable regular routing behavior
2167  MSDevice_Routing* routingDevice = static_cast<MSDevice_Routing*>(getDevice(typeid(MSDevice_Routing)));
2168  assert(routingDevice != 0);
2169  routingDevice->notifyEnter(*this, MSMoveReminder::NOTIFICATION_DEPARTED);
2170  }
2171  } else {
2172  throw InvalidArgument("Creating device of type '" + deviceName + "' is not supported");
2173  }
2174  }
2175 }
2176 
2177 
2178 std::string
2179 MSBaseVehicle::getDeviceParameter(const std::string& deviceName, const std::string& key) const {
2180  for (MSVehicleDevice* const dev : myDevices) {
2181  if (dev->deviceName() == deviceName) {
2182  return dev->getParameter(key);
2183  }
2184  }
2185  throw InvalidArgument("No device of type '" + deviceName + "' exists");
2186 }
2187 
2188 
2189 void
2190 MSBaseVehicle::setDeviceParameter(const std::string& deviceName, const std::string& key, const std::string& value) {
2191  for (MSVehicleDevice* const dev : myDevices) {
2192  if (dev->deviceName() == deviceName) {
2193  dev->setParameter(key, value);
2194  return;
2195  }
2196  }
2197  throw InvalidArgument("No device of type '" + deviceName + "' exists");
2198 }
2199 
2200 
2201 void
2202 MSBaseVehicle::setJunctionModelParameter(const std::string& key, const std::string& value) {
2205  const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
2206  // checked in MSLink::ignoreFoe
2207  } else {
2208  throw InvalidArgument("Vehicle '" + getID() + "' does not support junctionModel parameter '" + key + "'");
2209  }
2210 }
2211 
2212 
2213 void
2214 MSBaseVehicle::setCarFollowModelParameter(const std::string& key, const std::string& value) {
2215  // handle some generic params first and then delegate to the carFollowModel itself
2218  const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
2219  // checked in MSVehicle::planMove
2220  } else {
2221  MSVehicle* microVeh = dynamic_cast<MSVehicle*>(this);
2222  if (microVeh) {
2223  // remove 'carFollowModel.' prefix
2224  const std::string attrName = key.substr(15);
2225  microVeh->getCarFollowModel().setParameter(microVeh, attrName, value);
2226  }
2227  }
2228 }
2229 
2230 
2231 void
2233  /* Design idea for additional junction model parameters:
2234  We can distinguish between 3 levels of parameters
2235  1. typically shared by multiple vehicles -> vType parameter
2236  2. specific to one vehicle but stays constant throughout the simulation -> vehicle parameter
2237  3. specific to one vehicle and expected to change during simulation -> prefixed generic vehicle parameter
2238  */
2239  for (auto item : getParameter().getParametersMap()) {
2240  if (StringUtils::startsWith(item.first, "junctionModel.")) {
2241  setJunctionModelParameter(item.first, item.second);
2242  } else if (StringUtils::startsWith(item.first, "carFollowModel.")) {
2243  setCarFollowModelParameter(item.first, item.second);
2244  }
2245  }
2246  const std::string routingModeStr = MSDevice::getStringParam(*this, OptionsCont::getOptions(), "rerouting.mode", "0", false);
2247  try {
2248  int routingMode = StringUtils::toInt(routingModeStr);
2249  if (routingMode != libsumo::ROUTING_MODE_DEFAULT) {
2250  setRoutingMode(routingMode);
2251  }
2252  } catch (NumberFormatException&) {
2253  // @todo interpret symbolic constants
2254  throw ProcessError(TLF("Could not interpret routing.mode '%'", routingModeStr));
2255  }
2256 }
2257 
2258 
2263  } else {
2265  }
2266 }
2267 
2268 
2269 void
2271  assert(type != nullptr);
2272  if (myType->isVehicleSpecific() && type != myType) {
2274  }
2275  myType = type;
2276  if (myEnergyParams != nullptr) {
2278  }
2279 }
2280 
2281 
2284  if (myType->isVehicleSpecific()) {
2285  return *myType;
2286  }
2287  MSVehicleType* type = myType->buildSingularType(myType->getID() + "@" + getID());
2288  replaceVehicleType(type);
2289  return *type;
2290 }
2291 
2292 
2293 int
2295  const MSLane* const lane = getLane();
2296  if (lane == nullptr) {
2297  return getEdge()->getLanes()[0]->getRNGIndex();
2298  } else {
2299  return lane->getRNGIndex();
2300  }
2301 }
2302 
2303 
2304 SumoRNG*
2306  const MSLane* lane = getLane();
2307  if (lane == nullptr) {
2308  return getEdge()->getLanes()[0]->getRNG();
2309  } else {
2310  return lane->getRNG();
2311  }
2312 }
2313 
2314 std::string
2315 MSBaseVehicle::getPrefixedParameter(const std::string& key, std::string& error) const {
2316  const MSVehicle* microVeh = dynamic_cast<const MSVehicle*>(this);
2317  if (StringUtils::startsWith(key, "device.")) {
2318  StringTokenizer tok(key, ".");
2319  if (tok.size() < 3) {
2320  error = "Invalid device parameter '" + key + "' for vehicle '" + getID() + "'.";
2321  return "";
2322  }
2323  try {
2324  return getDeviceParameter(tok.get(1), key.substr(tok.get(0).size() + tok.get(1).size() + 2));
2325  } catch (InvalidArgument& e) {
2326  error = "Vehicle '" + getID() + "' does not support device parameter '" + key + "' (" + e.what() + ").";
2327  return "";
2328  }
2329  } else if (StringUtils::startsWith(key, "laneChangeModel.")) {
2330  if (microVeh == nullptr) {
2331  error = "Meso Vehicle '" + getID() + "' does not support laneChangeModel parameters.";
2332  return "";
2333  }
2334  const std::string attrName = key.substr(16);
2335  try {
2336  return microVeh->getLaneChangeModel().getParameter(attrName);
2337  } catch (InvalidArgument& e) {
2338  error = "Vehicle '" + getID() + "' does not support laneChangeModel parameter '" + key + "' (" + e.what() + ").";
2339  return "";
2340  }
2341  } else if (StringUtils::startsWith(key, "carFollowModel.")) {
2342  if (microVeh == nullptr) {
2343  error = "Meso Vehicle '" + getID() + "' does not support carFollowModel parameters.";
2344  return "";
2345  }
2346  const std::string attrName = key.substr(15);
2347  try {
2348  return microVeh->getCarFollowModel().getParameter(microVeh, attrName);
2349  } catch (InvalidArgument& e) {
2350  error = "Vehicle '" + getID() + "' does not support carFollowModel parameter '" + key + "' (" + e.what() + ").";
2351  return "";
2352  }
2353  } else if (StringUtils::startsWith(key, "has.") && StringUtils::endsWith(key, ".device")) {
2354  StringTokenizer tok(key, ".");
2355  if (tok.size() != 3) {
2356  error = "Invalid check for device. Expected format is 'has.DEVICENAME.device'.";
2357  return "";
2358  }
2359  return hasDevice(tok.get(1)) ? "true" : "false";
2360  // parking related parameters start here
2361  } else if (key == "parking.rerouteCount") {
2363  } else if (StringUtils::startsWith(key, "parking.memory.")) {
2364  std::vector<std::string> values;
2365  if (getParkingMemory()) {
2366  if (key == "parking.memory.IDList") {
2367  for (const auto& item : *getParkingMemory()) {
2368  values.push_back(item.first->getID());
2369  }
2370  } else if (key == "parking.memory.score") {
2371  for (const auto& item : *getParkingMemory()) {
2372  values.push_back(item.second.score);
2373  }
2374  } else if (key == "parking.memory.blockedAtTime") {
2375  for (const auto& item : *getParkingMemory()) {
2376  values.push_back(toString(STEPS2TIME(item.second.blockedAtTime)));
2377  }
2378  } else if (key == "parking.memory.blockedAtTimeLocal") {
2379  for (const auto& item : *getParkingMemory()) {
2380  values.push_back(toString(STEPS2TIME(item.second.blockedAtTimeLocal)));
2381  }
2382  } else {
2383  error = "Unsupported parking parameter '" + key + "'.";
2384  }
2385  }
2386  return toString(values);
2387  } else {
2388  // default: custom user parameter
2389  return getParameter().getParameter(key, "");
2390  }
2391 }
2392 
2393 void
2395  if (myParkingMemory == nullptr) {
2397  }
2398  (*myParkingMemory)[pa].blockedAtTime = SIMSTEP;
2399  if (local) {
2400  (*myParkingMemory)[pa].blockedAtTimeLocal = SIMSTEP;
2401  }
2402 }
2403 
2404 void
2406  if (myParkingMemory != nullptr) {
2407  for (auto& item : *myParkingMemory) {
2408  item.second.score = "";
2409  }
2410  }
2411 }
2412 
2413 void
2414 MSBaseVehicle::rememberParkingAreaScore(const MSParkingArea* pa, const std::string& score) {
2415  if (myParkingMemory == nullptr) {
2417  }
2418  (*myParkingMemory)[pa].score = score;
2419 }
2420 
2421 
2422 SUMOTime
2424  if (myParkingMemory == nullptr) {
2425  return -1;
2426  }
2427  auto it = myParkingMemory->find(pa);
2428  if (it == myParkingMemory->end()) {
2429  return -1;
2430  } else {
2431  return local ? it->second.blockedAtTimeLocal : it->second.blockedAtTime;
2432  }
2433 }
2434 
2435 
2436 #ifdef _DEBUG
2437 void
2438 MSBaseVehicle::initMoveReminderOutput(const OptionsCont& oc) {
2439  if (oc.isSet("movereminder-output.vehicles")) {
2440  const std::vector<std::string> vehicles = oc.getStringVector("movereminder-output.vehicles");
2441  myShallTraceMoveReminders.insert(vehicles.begin(), vehicles.end());
2442  }
2443 }
2444 
2445 
2446 void
2447 MSBaseVehicle::traceMoveReminder(const std::string& type, MSMoveReminder* rem, double pos, bool keep) const {
2448  OutputDevice& od = OutputDevice::getDeviceByOption("movereminder-output");
2449  od.openTag("movereminder");
2450  od.writeAttr(SUMO_ATTR_TIME, STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()));
2451  od.writeAttr("veh", getID());
2453  od.writeAttr("type", type);
2454  od.writeAttr("pos", toString(pos));
2455  od.writeAttr("keep", toString(keep));
2456  od.closeTag();
2457 }
2458 #endif
2459 
2460 
2461 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
#define DEBUG_COND
std::vector< const MSEdge * > ConstMSEdgeVector
Definition: MSEdge.h:74
ConstMSEdgeVector::const_iterator MSRouteIterator
Definition: MSRoute.h:56
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:296
#define WRITE_ERRORF(...)
Definition: MsgHandler.h:305
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:304
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:295
#define TL(string)
Definition: MsgHandler.h:315
#define TLF(string,...)
Definition: MsgHandler.h:317
std::shared_ptr< const MSRoute > ConstMSRoutePtr
Definition: Route.h:31
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition: SUMOTime.cpp:69
#define STEPS2TIME(x)
Definition: SUMOTime.h:55
#define SIMSTEP
Definition: SUMOTime.h:61
#define SUMOTime_MAX
Definition: SUMOTime.h:34
#define SIMTIME
Definition: SUMOTime.h:62
const int VEHPARS_CFMODEL_PARAMS_SET
const int VEHPARS_PARKING_BADGES_SET
@ RANDOM
The edge is chosen randomly.
@ GIVEN
The edge index is given.
@ DEFAULT
No information given; use default.
const int STOP_INDEX_END
const int VEHPARS_JUNCTIONMODEL_PARAMS_SET
DepartLaneDefinition
Possible ways to choose a lane on depart.
@ GIVEN
The speed is given.
@ GIVEN
The position is given.
@ DEFAULT
No information given; use default.
@ BASE
Back-at-zero position.
const int STOP_SPEED_SET
const int VEHPARS_SPEEDFACTOR_SET
@ RANDOM
The lane is chosen randomly.
@ GIVEN
The arrival lane is given.
@ FIRST_ALLOWED
The rightmost lane the vehicle may use.
@ GIVEN
The speed is given.
const int VEHPARS_FORCE_REROUTE
const int STOP_INDEX_FIT
@ RANDOM
The arrival position is chosen randomly.
@ GIVEN
The arrival position is given.
@ CENTER
Half the road length.
const int STOP_JUMP_SET
const int VEHPARS_LINE_SET
@ CONTAINER_TRIGGERED
The departure is container triggered.
@ TRIGGERED
The departure is person triggered.
@ SUMO_TAG_VEHICLE
description of a vehicle
@ SUMO_TAG_PARKING_AREA
A parking area.
@ SUMO_ATTR_CF_IGNORE_IDS
@ SUMO_ATTR_JM_IGNORE_IDS
@ SUMO_ATTR_JM_IGNORE_TYPES
@ SUMO_ATTR_LINE
@ SUMO_ATTR_REROUTE
@ SUMO_ATTR_DISTANCE
@ SUMO_ATTR_SPEEDFACTOR
@ SUMO_ATTR_ROUTE
@ SUMO_ATTR_ID
@ SUMO_ATTR_CF_IGNORE_TYPES
@ SUMO_ATTR_TIME
trigger: the time of the step
int gPrecisionRandom
Definition: StdDefs.cpp:28
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MIN2(T a, T b)
Definition: StdDefs.h:76
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition: StdDefs.h:58
T MAX2(T a, T b)
Definition: StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
void setSecondary(const EnergyParams *secondaryParams)
Set secondary params.
Definition: EnergyParams.h:60
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.
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition: MELoop.cpp:325
virtual std::string getParameter(const std::string &key) const
try to retrieve the given parameter from this laneChangeModel. Throw exception for unsupported key
double getMaxSpeed() const
Returns the maximum speed (the minimum of desired and technical maximum speed)
bool haveValidStopEdges(bool silent=false) const
check whether all stop.edge MSRouteIterators are valid and in order
int myRoutingMode
routing mode (see TraCIConstants.h)
bool hasJump(const MSRouteIterator &it) const
check wether the vehicle has jump at the given part of its route
ParkingMemory * myParkingMemory
memory for parking search
void rememberBlockedParkingArea(const MSParkingArea *pa, bool local)
std::list< MSStop > myStops
The vehicle's list of stops.
double getImpatience() const
Returns this vehicles impatience.
virtual ConstMSEdgeVector::const_iterator getRerouteOrigin() const
Returns the starting point for reroutes (usually the current edge)
const std::vector< MSTransportable * > & getPersons() const
retrieve riding persons
virtual void initDevices()
const MSEdge * succEdge(int nSuccs) const
Returns the nSuccs'th successor of edge the vehicle is currently at.
void resetRoutePosition(int index, DepartLaneDefinition departLaneProcedure)
reset index of edge within route
std::map< const MSParkingArea *, PaMemory, ComparatorIdLess > ParkingMemory
virtual BaseInfluencer & getBaseInfluencer()=0
Returns the velocity/lane influencer.
std::string getDeviceParameter(const std::string &deviceName, const std::string &key) const
try to retrieve the given parameter from any of the vehicles devices, raise InvalidArgument if no dev...
bool replaceStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string &info, bool teleport, std::string &errorMsg)
int getLeavingPersonNumber() const
Returns the number of leaving persons.
MSBaseVehicle(SUMOVehicleParameter *pars, ConstMSRoutePtr route, MSVehicleType *type, const double speedFactor)
Constructor.
void calculateArrivalParams(bool onInit)
(Re-)Calculates the arrival position and lane from the vehicle parameters
virtual double getArrivalPos() const
Returns this vehicle's desired arrivalPos for its current route (may change on reroute)
void setCarFollowModelParameter(const std::string &key, const std::string &value)
set individual carFollow model parameters (not type related)
void setRoutingMode(int value)
Sets routing behavior.
void resetParkingAreaScores()
MSVehicleType * myType
This vehicle's type.
static NumericalID myCurrentNumericalIndex
bool rerouteBetweenStops(int nextStopIndex, const std::string &info, bool teleport, std::string &errorMsg)
MoveReminderCont myMoveReminders
Currently relevant move reminders.
double myDepartPos
The real depart position.
const SUMOVehicleParameter & getParameter() const
Returns the vehicle's parameter (including departure definition)
void addReminder(MSMoveReminder *rem)
Adds a MoveReminder dynamically.
void replaceParameter(const SUMOVehicleParameter *newParameter)
replace the vehicle parameter (deleting the old one)
int getNumberParkingReroutes() const
std::vector< MSVehicleDevice * > myDevices
The devices this vehicle has.
double getPreviousSpeed() const
Returns the vehicle's previous speed.
virtual void addTransportable(MSTransportable *transportable)
Adds a person or container to this vehicle.
const SUMOVehicleParameter::Stop * getNextStopParameter() const
return parameters for the next stop (SUMOVehicle Interface)
double getOdometer() const
Returns the distance that was already driven by this vehicle.
virtual bool hasArrived() const
Returns whether this vehicle has already arived (by default this is true if the vehicle has reached i...
const NumericalID myNumericalID
bool isStoppedInRange(const double pos, const double tolerance, bool checkFuture=false) const
return whether the given position is within range of the current stop
bool isJumping() const
Returns whether the vehicle is perform a jump.
void checkRouteRemoval()
remove route at the end of the simulation
MSVehicleType & getSingularType()
Replaces the current vehicle type with a new one used by this vehicle only.
SUMOTime sawBlockedParkingArea(const MSParkingArea *pa, bool local) const
virtual void replaceVehicleType(MSVehicleType *type)
Replaces the current vehicle type by the one given.
bool isStoppedParking() const
Returns whether the vehicle is on a parking stop.
bool hasValidRoute(std::string &msg, ConstMSRoutePtr route=0) const
Validates the current or given route.
double getLength() const
Returns the vehicle's length.
bool isParking() const
Returns whether the vehicle is parking.
MSParkingArea * getCurrentParkingArea()
get the current parking area stop or nullptr
const MSEdge * getEdge() const
Returns the edge the vehicle is currently at.
double getHarmonoise_NoiseEmissions() const
Returns noise emissions of the current state.
int getPersonNumber() const
Returns the number of persons.
double getRelativeStateOfCharge() const
Returns actual relative state of charge of battery (-)
void setJunctionModelParameter(const std::string &key, const std::string &value)
set individual junction model paramete (not type related)
void setDepartAndArrivalEdge()
apply departEdge and arrivalEdge attributes
void setID(const std::string &newID)
set the id (inherited from Named but forbidden for vehicles)
MSRouteIterator myCurrEdge
Iterator to current route-edge.
static MSLane * interpretOppositeStop(SUMOVehicleParameter::Stop &stop)
interpret stop lane on opposite side of the road
static std::vector< MSTransportable * > myEmptyTransportableVector
const std::vector< std::string > & getParkingBadges() const
get the valid parking access rights (vehicle settings override vehicle type settings)
bool hasDeparted() const
Returns whether this vehicle has already departed.
MSStop & getNextStop()
bool ignoreTransientPermissions() const
Returns whether this object is ignoring transient permission changes (during routing)
ConstMSRoutePtr myRoute
This vehicle's route.
const ConstMSEdgeVector getStopEdges(double &firstPos, double &lastPos, std::set< int > &jumps) const
Returns the list of still pending stop edges also returns the first and last stop position.
MSDevice_Transportable * myContainerDevice
The containers this vehicle may have.
bool allowsBoarding(const MSTransportable *t) const
whether the given transportable is allowed to board this vehicle
double getStateOfCharge() const
Returns actual state of charge of battery (Wh) RICE_CHECK: This may be a misnomer,...
MSEdgeWeightsStorage & _getWeightsStorage() const
virtual bool handleCollisionStop(MSStop &stop, const double distToStop)
bool hasDevice(const std::string &deviceName) const
check whether the vehicle is equiped with a device of the given name
SumoRNG * getRNG() const
SUMOTime getDeparture() const
Returns this vehicle's real departure time.
EnergyParams * getEmissionParameters() const
retrieve parameters for the energy consumption model
double basePos(const MSEdge *edge) const
departure position where the vehicle fits fully onto the edge (if possible)
const MSRouteIterator & getCurrentRouteEdge() const
Returns an iterator pointing to the current edge in this vehicles route.
void setDeviceParameter(const std::string &deviceName, const std::string &key, const std::string &value)
try to set the given parameter from any of the vehicles devices, raise InvalidArgument if no device p...
MSDevice_Transportable * myPersonDevice
The passengers this vehicle may have.
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
bool hasStops() const
Returns whether the vehicle has to stop somewhere.
std::string getFlowID() const
reconstruct flow id from vehicle id
const ParkingMemory * getParkingMemory() const
virtual void activateReminders(const MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
"Activates" all current move reminder
bool isLineStop(double position) const
returns whether the vehicle serves a public transport line that serves the given stop
double myChosenSpeedFactor
A precomputed factor by which the driver wants to be faster than the speed limit.
@ ROUTE_INVALID
route was checked and is valid
Definition: MSBaseVehicle.h:74
@ ROUTE_START_INVALID_LANE
Definition: MSBaseVehicle.h:78
@ ROUTE_START_INVALID_PERMISSIONS
Definition: MSBaseVehicle.h:76
std::string getPrefixedParameter(const std::string &key, std::string &error) const
retrieve parameters of devices, models and the vehicle itself
void addStops(const bool ignoreStopErrors, MSRouteIterator *searchStart=nullptr, bool addRouteStops=true)
Adds stops to the built vehicle.
void removeTransportable(MSTransportable *t)
removes a person or container
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
MSParkingArea * getNextParkingArea()
get the upcoming parking area stop or nullptr
int myArrivalLane
The destination lane where the vehicle stops.
int getRouteValidity(bool update=true, bool silent=false, std::string *msgReturn=nullptr)
check for route validity at first insertion attempt
MSStop & getStop(int nextStopIndex)
virtual ~MSBaseVehicle()
Destructor.
bool insertStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string &info, bool teleport, std::string &errorMsg)
SUMOTime myDeparture
The real departure time.
std::vector< std::string > getPersonIDList() const
Returns the list of persons.
const MSEdgeWeightsStorage & getWeightsStorage() const
Returns the vehicle's internal edge travel times/efforts container.
bool isStoppedTriggered() const
Returns whether the vehicle is on a triggered stop.
virtual bool resumeFromStopping()=0
virtual bool hasInfluencer() const =0
whether the vehicle is individually influenced (via TraCI or special parameters)
const std::set< SUMOTrafficObject::NumericalID > getUpcomingEdgeIDs() const
returns the numerical ids of edges to travel
bool stopsAtEdge(const MSEdge *edge) const
Returns whether the vehicle stops at the given edge.
void rememberParkingAreaScore(const MSParkingArea *pa, const std::string &score)
score only needed when running with gui
bool addStop(const SUMOVehicleParameter::Stop &stopPar, std::string &errorMsg, SUMOTime untilOffset=0, MSRouteIterator *searchStart=nullptr)
Adds a stop.
double getChargedEnergy() const
Returns the energy charged to the battery in the current time step (Wh)
std::vector< SUMOVehicleParameter::Stop > myPastStops
The list of stops that the vehicle has already reached.
void onDepart()
Called when the vehicle is inserted into the network.
void removeReminder(MSMoveReminder *rem)
Removes a MoveReminder dynamically.
SUMOTime getStopDuration() const
get remaining stop duration or 0 if the vehicle isn't stopped
virtual double getAcceleration() const
Returns the vehicle's acceleration.
virtual bool addTraciStop(SUMOVehicleParameter::Stop stop, std::string &errorMsg)
int getRoutingMode() const
return routing mode (configures router choice but also handling of transient permission changes)
int getRoutePosition() const
return index of edge within route
bool replaceParkingArea(MSParkingArea *parkingArea, std::string &errorMsg)
replace the current parking area stop with a new stop with merge duration
static const SUMOTime NOT_YET_DEPARTED
SUMOTime getDepartDelay() const
Returns the depart delay.
double getElecHybridCurrent() const
Returns actual current (A) of ElecHybrid device RICE_CHECK: Is this the current consumed from the ove...
SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT() const
EnergyParams * myEnergyParams
The emission parameters this vehicle may have.
const SUMOVehicleParameter * myParameter
This vehicle's parameter.
virtual bool hasValidRouteStart(std::string &msg)
checks wether the vehicle can depart on the first edge
int myRouteValidity
status of the current vehicle route
std::vector< std::pair< int, double > > getStopIndices() const
return list of route indices for the remaining stops
SUMOTime myStopUntilOffset
The offset when adding route stops with 'until' on route replacement.
virtual bool replaceRoute(ConstMSRoutePtr route, const std::string &info, bool onInit=false, int offset=0, bool addStops=true, bool removeStops=true, std::string *msgReturn=nullptr)
Replaces the current route by the given one.
virtual bool isOnRoad() const
Returns the information whether the vehicle is on a road (is simulated)
const std::vector< MSTransportable * > & getContainers() const
retrieve riding containers
const MSRoute & getRoute() const
Returns the current route.
bool reroute(SUMOTime t, const std::string &info, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, const bool onInit=false, const bool withTaz=false, const bool silent=false, const MSEdge *sink=nullptr)
Performs a rerouting using the given router.
bool stopsAt(MSStoppingPlace *stop) const
Returns whether the vehicle stops at the given stopping place.
int getRNGIndex() const
MSEdgeWeightsStorage * myEdgeWeights
void createDevice(const std::string &deviceName)
create device of the given type
bool isStopped() const
Returns whether the vehicle is at a stop.
MSDevice * getDevice(const std::type_info &type) const
Returns a device of the given type if it exists, nullptr otherwise.
bool abortNextStop(int nextStopIndex=0)
deletes the next stop at the given index if it exists
int myNumberReroutes
The number of reroutings.
double myArrivalPos
The position on the destination lane where the vehicle stops.
bool insertJump(int nextStopIndex, MSRouteIterator itStart, std::string &errorMsg)
helper function
virtual void saveState(OutputDevice &out)
Saves the (common) state of a vehicle.
double myOdometer
A simple odometer to keep track of the length of the route already driven.
void initTransientModelParams()
init model parameters from generic params
int getContainerNumber() const
Returns the number of containers.
bool replaceRouteEdges(ConstMSEdgeVector &edges, double cost, double savings, const std::string &info, bool onInit=false, bool check=false, bool removeStops=true, std::string *msgReturn=nullptr)
Replaces the current route by the given edges.
virtual std::string getParameter(const MSVehicle *veh, const std::string &key) const
try to get the given parameter for this carFollowingModel
Definition: MSCFModel.h:646
virtual void setParameter(MSVehicle *veh, const std::string &key, const std::string &value) const
try to set the given parameter for this carFollowingModel
Definition: MSCFModel.h:659
Battery device for electric vehicles.
double getActualBatteryCapacity() const
Get the actual vehicle's Battery Capacity in Wh.
double getMaximumBatteryCapacity() const
Get the total vehicle's Battery Capacity in Wh.
double getEnergyCharged() const
Get charged energy.
A device which collects info on the vehicle trip (mainly on departure and arrival)
double getMaximumBatteryCapacity() const
Get the total vehicle's Battery Capacity in kWh.
double getCurrentFromOverheadWire() const
Get actual current in the overhead wire segment.
double getEnergyCharged() const
Get charged energy.
double getActualBatteryCapacity() const
Get the actual vehicle's Battery Capacity in kWh.
A device that performs vehicle rerouting based on current edge speeds.
bool notifyEnter(SUMOTrafficObject &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Computes a new route on vehicle insertion.
static void buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into)
Build devices for the given vehicle, if needed.
A device which collects info on the vehicle trip (mainly on departure and arrival)
Definition: MSDevice_Taxi.h:49
bool allowsBoarding(const MSTransportable *t) const
whether the given person is allowed to board this taxi
const std::vector< MSTransportable * > & getTransportables() const
Returns the list of transportables using this vehicle.
static bool willTransferAtJoin(const MSTransportable *t, const MSBaseVehicle *joinVeh)
check if boardingDuration should be applied
static MSDevice_Transportable * buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into, const bool isContainer)
Build devices for the given vehicle, if needed.
int size() const
Return the number of passengers / containers.
void addTransportable(MSTransportable *transportable)
Add a passenger.
void removeTransportable(MSTransportable *transportable)
Remove a passenger (TraCI)
Abstract in-vehicle / in-person device.
Definition: MSDevice.h:62
static std::string getStringParam(const SUMOVehicle &v, const OptionsCont &oc, const std::string &paramName, const std::string &deflt, bool required=false)
Definition: MSDevice.cpp:182
static void buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into)
Build devices for the given vehicle, if needed.
Definition: MSDevice.cpp:112
A road/street connecting two junctions.
Definition: MSEdge.h:77
bool hasTransientPermissions() const
Definition: MSEdge.cpp:1576
const MSEdge * getOppositeEdge() const
Returns the opposite direction edge if on exists else a nullptr.
Definition: MSEdge.cpp:1276
const std::vector< MSLane * > * allowedLanes(const MSEdge &destination, SUMOVehicleClass vclass=SVC_IGNORING, bool ignoreTransientPermissions=false) const
Get the allowed lanes to reach the destination-edge.
Definition: MSEdge.cpp:474
bool isNormal() const
return whether this edge is an internal edge
Definition: MSEdge.h:260
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:168
double getLength() const
return the length of the edge
Definition: MSEdge.h:662
bool isTazConnector() const
Definition: MSEdge.h:288
int getNumLanes() const
Definition: MSEdge.h:172
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:265
static bool dictionary(const std::string &id, MSEdge *edge)
Inserts edge into the static dictionary Returns true if the key id isn't already in the dictionary....
Definition: MSEdge.cpp:983
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition: MSEdge.cpp:873
A storage for edge travel times and efforts.
static bool gUseMesoSim
Definition: MSGlobals.h:103
static bool gCheckRoutes
Definition: MSGlobals.h:88
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition: MSGlobals.h:109
static SUMOTime gTimeToImpatience
Definition: MSGlobals.h:75
static bool gHaveEmissions
Whether emission output of some type is needed (files or GUI)
Definition: MSGlobals.h:178
static bool gUseStopEnded
whether the simulation should replay previous stop times
Definition: MSGlobals.h:130
void descheduleDeparture(const SUMOVehicle *veh)
stops trying to emit the given vehicle (and delete it)
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
SumoRNG * getRNG() const
return the associated RNG
Definition: MSLane.h:246
int getRNGIndex() const
returns the associated RNG index
Definition: MSLane.h:241
const MSEdge * getNextNormal() const
Returns the lane's follower if it is an internal lane, the edge of the lane otherwise.
Definition: MSLane.cpp:2331
double getLength() const
Returns the lane's length.
Definition: MSLane.h:598
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition: MSLane.h:913
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition: MSLane.cpp:2355
bool isInternal() const
Definition: MSLane.cpp:2486
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:752
Something on a lane to be noticed about vehicle movement.
Notification
Definition of a vehicle state.
@ NOTIFICATION_DEPARTED
The vehicle has departed (was inserted into the network)
const std::string & getDescription() const
bool warnOnce(const std::string &typeAndID)
return whether a warning regarding the given object shall be issued
Definition: MSNet.cpp:1624
@ NEWROUTE
The vehicle got a new route.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:182
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:378
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:320
static bool hasInstance()
Returns whether the network was already constructed.
Definition: MSNet.h:152
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition: MSNet.cpp:1364
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition: MSNet.h:431
void informVehicleStateListener(const SUMOVehicle *const vehicle, VehicleState to, const std::string &info="")
Informs all added listeners about a vehicle's state change.
Definition: MSNet.cpp:1258
MSVehicleRouter & getRouterTT(const int rngIndex, const MSEdgeVector &prohibited=MSEdgeVector()) const
Definition: MSNet.cpp:1466
A lane area vehicles can halt at.
Definition: MSParkingArea.h:60
bool accepts(MSBaseVehicle *veh) const
Return the parking accepts the vehicle (due to its given badges)
void setCosts(double costs)
Sets the costs of the route.
Definition: MSRoute.h:204
static bool hasRoute(const std::string &id)
returns whether a route with the given id exists
Definition: MSRoute.cpp:152
static bool dictionary(const std::string &id, ConstMSRoutePtr route)
Adds a route to the dictionary.
Definition: MSRoute.cpp:109
static void checkDist(const std::string &id)
Checks the distribution whether it is permanent and deletes it if not.
Definition: MSRoute.cpp:187
const ConstMSEdgeVector & getEdges() const
Definition: MSRoute.h:124
void setSavings(double savings)
Sets the savings of the route.
Definition: MSRoute.h:211
static MSVehicleRouter & getRouterTT(const int rngIndex, SUMOVehicleClass svc, const MSEdgeVector &prohibited=MSEdgeVector())
return the vehicle router instance
bool canLeaveVehicle(const MSTransportable *t, const SUMOVehicle &veh, const MSStop &stop)
checks whether the person may exit at the current vehicle position
Definition: MSStop.h:44
const MSLane * lane
The lane to stop at (microsim only)
Definition: MSStop.h:50
MSStoppingPlace * containerstop
(Optional) container stop if one is assigned to the stop
Definition: MSStop.h:56
bool isOpposite
whether this an opposite-direction stop
Definition: MSStop.h:87
void initPars(const SUMOVehicleParameter::Stop &stopPar)
initialize attributes from the given stop parameters
Definition: MSStop.cpp:112
const MESegment * segment
The segment to stop at (mesosim only)
Definition: MSStop.h:52
bool reached
Information whether the stop has been reached.
Definition: MSStop.h:75
MSRouteIterator edge
The edge in the route to stop at.
Definition: MSStop.h:48
double getEndPos(const SUMOVehicle &veh) const
return halting position for upcoming stop;
Definition: MSStop.cpp:35
MSParkingArea * parkingarea
(Optional) parkingArea if one is assigned to the stop
Definition: MSStop.h:58
MSStoppingPlace * chargingStation
(Optional) charging station if one is assigned to the stop
Definition: MSStop.h:60
std::string getDescription() const
get a short description for showing in the gui
Definition: MSStop.cpp:69
SUMOTime getUntil() const
return until / ended time
Definition: MSStop.cpp:151
const SUMOVehicleParameter::Stop pars
The stop parameter.
Definition: MSStop.h:65
MSStoppingPlace * busstop
(Optional) bus stop if one is assigned to the stop
Definition: MSStop.h:54
MSStoppingPlace * overheadWireSegment
(Optional) overhead wire segment if one is assigned to the stop
Definition: MSStop.h:63
A lane area vehicles can halt at.
double getBeginLanePosition() const
Returns the begin position of this stop.
double getEndLanePosition() const
Returns the end position of this stop.
const MSLane & getLane() const
Returns the lane this stop is located at.
bool isPerson() const
Whether it is a person.
bool hasVTypeDistribution(const std::string &id) const
Asks for a vehicle type distribution.
void vehicleDeparted(const SUMOVehicle &v)
Informs this control about a vehicle's departure.
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
void removeVType(const MSVehicleType *vehType)
Abstract in-vehicle device.
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:77
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:5720
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition: MSVehicle.h:974
The car-following model and parameter.
Definition: MSVehicleType.h:63
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
double getMaxSpeed() const
Get vehicle's (technical) maximum speed [m/s].
double getDesiredMaxSpeed() const
Returns the vehicles's desired maximum speed.
const EnergyParams * getEmissionParameters() const
retrieve parameters for the energy consumption model
bool isVehicleSpecific() const
Returns whether this type belongs to a single vehicle only (was modified)
SUMOEmissionClass getEmissionClass() const
Get this vehicle type's emission class.
const std::string & getID() const
Returns the name of the vehicle type.
Definition: MSVehicleType.h:91
double getLength() const
Get vehicle's length [m].
const std::vector< std::string > & getParkingBadges() const
Returns the parking access rights of this type.
MSVehicleType * buildSingularType(const std::string &id) const
Duplicates the microsim vehicle type giving the newly created type the given id, marking it as vehicl...
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition: Named.h:67
const std::string & getID() const
Returns the id.
Definition: Named.h:74
A storage for options typed value containers)
Definition: OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:60
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
int precision()
return precision set on the device
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
static OutputDevice & getDeviceByOption(const std::string &name)
Returns the device described by the option.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
void setPrecision(int precision=gPrecision)
Sets the precision or resets it to default.
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
static const RGBColor DEFAULT_COLOR
The default color (for vehicle types and vehicles)
Definition: RGBColor.h:199
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
Definition: RandHelper.cpp:94
bool computeLooped(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent=false)
Builds the route between the given edges using the minimum effort at the given time if from == to,...
virtual bool compute(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent=false)=0
Builds the route between the given edges using the minimum effort at the given time The definition of...
virtual double recomputeCosts(const std::vector< const E * > &edges, const V *const v, SUMOTime msTime, double *lengthp=nullptr) const
long long int NumericalID
virtual double getSpeed() const =0
Returns the object's current speed.
virtual SUMOTime getWaitingTime(const bool accumulated=false) const =0
virtual const MSLane * getLane() const =0
Returns the lane the object is currently at.
virtual double getPositionOnLane() const =0
Get the object's position along the lane.
Representation of a vehicle.
Definition: SUMOVehicle.h:60
virtual bool isIdling() const =0
Returns whether the vehicle is idling (waiting to re-enter the net.
virtual double getBrakeGap(bool delayed=false) const =0
get distance for coming to a stop (used for rerouting checks)
Definition of vehicle stop (position and duration)
std::string edge
The edge to stop at.
ParkingType parking
whether the vehicle is removed from the net while stopping
std::string lane
The lane to stop at.
double speed
the speed at which this stop counts as reached (waypoint mode)
std::string parkingarea
(Optional) parking area if one is assigned to the stop
double startPos
The stopping position start.
int parametersSet
Information for the output which parameter were set.
int index
at which position in the stops list
SUMOTime jump
transfer time if there shall be a jump from this stop to the next route edge
SUMOTime until
The time at which the vehicle may continue its journey.
bool triggered
whether an arriving person lets the vehicle continue
SUMOTime ended
the time at which this stop was ended
double endPos
The stopping position end.
bool containerTriggered
whether an arriving container lets the vehicle continue
bool collision
Whether this stop was triggered by a collision.
SUMOTime arrival
The (expected) time at which the vehicle reaches the stop.
SUMOTime duration
The stopping duration.
Structure representing possible vehicle parameter.
int parametersSet
Information for the router which parameter were set, TraCI may modify this (when changing color)
ArrivalSpeedDefinition arrivalSpeedProcedure
Information how the vehicle's end speed shall be chosen.
double departSpeed
(optional) The initial speed of the vehicle
std::string vtypeid
The vehicle's type id.
SUMOTime repetitionOffset
The time offset between vehicle reinsertions.
std::vector< std::string > via
List of the via-edges the vehicle must visit.
int repetitionsDone
The number of times the vehicle was already inserted.
ArrivalLaneDefinition arrivalLaneProcedure
Information how the vehicle shall choose the lane to arrive on.
void write(OutputDevice &dev, const OptionsCont &oc, const SumoXMLTag altTag=SUMO_TAG_VEHICLE, const std::string &typeID="") const
Writes the parameters as a beginning element.
int personNumber
The static number of persons in the vehicle when it departs (not including boarding persons)
RouteIndexDefinition arrivalEdgeProcedure
Information how the vehicle's final edge shall be chosen.
double departPos
(optional) The position the vehicle shall depart from
DepartSpeedDefinition departSpeedProcedure
Information how the vehicle's initial speed shall be chosen.
double arrivalPos
(optional) The position the vehicle shall arrive on
std::string routeid
The vehicle's route id.
std::string id
The vehicle's id.
std::vector< std::string > parkingBadges
The parking access rights.
std::vector< Stop > stops
List of the stops the vehicle will make, TraCI may add entries here.
int departEdge
(optional) The initial edge within the route of the vehicle
bool wasSet(int what) const
Returns whether the given parameter was set.
ArrivalPosDefinition arrivalPosProcedure
Information how the vehicle shall choose the arrival position.
std::string toTaz
The vehicle's destination zone (district)
double arrivalSpeed
(optional) The final speed of the vehicle (not used yet)
DepartDefinition departProcedure
Information how the vehicle shall choose the depart time.
int arrivalEdge
(optional) The final edge within the route of the vehicle
std::string fromTaz
The vehicle's origin zone (district)
DepartPosDefinition departPosProcedure
Information how the vehicle shall choose the departure position.
std::string line
The vehicle's line (mainly for public transport)
int containerNumber
The static number of containers in the vehicle when it departs.
RouteIndexDefinition departEdgeProcedure
Information how the vehicle's initial edge shall be chosen.
static std::string getEdgeIDFromLane(const std::string laneID)
return edge id when given the lane ID
static int getIndexFromLane(const std::string laneID)
return lane index when given the lane ID
int size() const
returns the number of existing substrings
std::string get(int pos) const
returns the item at the given position
static bool startsWith(const std::string &str, const std::string prefix)
Checks whether a given string starts with the prefix.
static bool endsWith(const std::string &str, const std::string suffix)
Checks whether a given string ends with the suffix.
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...
TRACI_CONST int ROUTING_MODE_AGGREGATED
TRACI_CONST int ROUTING_MODE_DEFAULT
TRACI_CONST int ROUTING_MODE_IGNORE_TRANSIENT_PERMISSIONS