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.org/sumo
3 // Copyright (C) 2001-2022 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 <mesosim/MELoop.h>
41 #include "MSGlobals.h"
42 #include "MSVehicleControl.h"
43 #include "MSVehicleType.h"
44 #include "MSEdge.h"
45 #include "MSLane.h"
46 #include "MSMoveReminder.h"
47 #include "MSEdgeWeightsStorage.h"
48 #include "MSNet.h"
49 #include "MSStop.h"
50 #include "MSParkingArea.h"
51 #include "MSInsertionControl.h"
52 #include "MSBaseVehicle.h"
53 
54 //#define DEBUG_REROUTE
55 //#define DEBUG_ADD_STOP
56 //#define DEBUG_COND (getID() == "")
57 //#define DEBUG_COND (true)
58 //#define DEBUG_REPLACE_ROUTE
59 #define DEBUG_COND (isSelected())
60 
61 // ===========================================================================
62 // static members
63 // ===========================================================================
65 std::vector<MSTransportable*> MSBaseVehicle::myEmptyTransportableVector;
66 #ifdef _DEBUG
67 std::set<std::string> MSBaseVehicle::myShallTraceMoveReminders;
68 #endif
70 
71 // ===========================================================================
72 // Influencer method definitions
73 // ===========================================================================
74 
76  myRoutingMode(0)
77 {}
78 
81  if (myRoutingMode == 1) {
82  return MSRoutingEngine::getRouterTT(rngIndex, svc);
83  } else {
84  return MSNet::getInstance()->getRouterTT(rngIndex);
85  }
86 }
87 
88 
89 
90 // ===========================================================================
91 // method definitions
92 // ===========================================================================
93 
94 double
96  throw ProcessError("getPreviousSpeed() is not available for non-MSVehicles.");
97 }
98 
99 
101  MSVehicleType* type, const double speedFactor) :
102  SUMOVehicle(pars->id),
103  myParameter(pars),
104  myRoute(route),
105  myType(type),
106  myCurrEdge(route->begin()),
107  myChosenSpeedFactor(pars->speedFactor < 0 ? speedFactor : pars->speedFactor),
108  myMoveReminders(0),
109  myPersonDevice(nullptr),
110  myContainerDevice(nullptr),
112  myDepartPos(-1),
113  myArrivalPos(-1),
114  myArrivalLane(-1),
115  myNumberReroutes(0),
117  myOdometer(0.),
120  myEdgeWeights(nullptr)
121 #ifdef _DEBUG
122  , myTraceMoveReminders(myShallTraceMoveReminders.count(pars->id) > 0)
123 #endif
124 {
125  if ((*myRoute->begin())->isTazConnector() || myRoute->getLastEdge()->isTazConnector()) {
127  }
129  if ((pars->parametersSet & VEHPARS_FORCE_REROUTE) == 0) {
131  }
132  if (!pars->wasSet(VEHPARS_FORCE_REROUTE)) {
134  }
136 }
137 
138 
140  delete myEdgeWeights;
141  myRoute->release();
142  if (myParameter->repetitionNumber == 0) {
144  }
145  for (MSVehicleDevice* dev : myDevices) {
146  delete dev;
147  }
148  delete myParameter;
149  delete myParkingMemory;
150 }
151 
152 
153 void
156  for (MSVehicleDevice* dev : myDevices) {
157  myMoveReminders.push_back(std::make_pair(dev, 0.));
158  }
159 }
160 
161 
162 void
163 MSBaseVehicle::setID(const std::string& /*newID*/) {
164  throw ProcessError("Changing a vehicle ID is not permitted");
165 }
166 
169  return *myParameter;
170 }
171 
172 const EnergyParams*
174  MSDevice_Battery* batteryDevice = static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
175  MSDevice_ElecHybrid* elecHybridDevice = static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
176  if (batteryDevice != nullptr) {
177  if (elecHybridDevice != nullptr) {
178  WRITE_WARNING("MSBaseVehicle::getEmissionParameters(): both batteryDevice and elecHybridDevice defined, returning batteryDevice parameters.");
179  }
180  return &batteryDevice->getEnergyParams();
181  } else {
182  if (elecHybridDevice != nullptr) {
183  return &elecHybridDevice->getEnergyParams();
184  } else {
185  return nullptr;
186  }
187  }
188 }
189 
190 void
192  delete myParameter;
193  myParameter = newParameter;
194 }
195 
196 double
198  return myType->getMaxSpeed();
199 }
200 
201 
202 const MSEdge*
203 MSBaseVehicle::succEdge(int nSuccs) const {
204  if (myCurrEdge + nSuccs < myRoute->end() && std::distance(myCurrEdge, myRoute->begin()) <= nSuccs) {
205  return *(myCurrEdge + nSuccs);
206  } else {
207  return nullptr;
208  }
209 }
210 
211 
212 const MSEdge*
214  return *myCurrEdge;
215 }
216 
217 
218 void
219 MSBaseVehicle::reroute(SUMOTime t, const std::string& info, SUMOAbstractRouter<MSEdge, SUMOVehicle>& router, const bool onInit, const bool withTaz, const bool silent) {
220  // check whether to reroute
221  const MSEdge* source = withTaz && onInit ? MSEdge::dictionary(myParameter->fromTaz + "-source") : getRerouteOrigin();
222  if (source == nullptr) {
223  source = getRerouteOrigin();
224  }
225  const MSEdge* sink = withTaz ? MSEdge::dictionary(myParameter->toTaz + "-sink") : myRoute->getLastEdge();
226  if (sink == nullptr) {
227  sink = myRoute->getLastEdge();
228  }
229  ConstMSEdgeVector oldEdgesRemaining(source == *myCurrEdge ? myCurrEdge : myCurrEdge + 1, myRoute->end());
230  ConstMSEdgeVector edges;
231  ConstMSEdgeVector stops;
232  if (myParameter->via.size() == 0) {
233  double firstPos = -1;
234  double lastPos = -1;
235  stops = getStopEdges(firstPos, lastPos);
236  if (stops.size() > 0) {
237  const double sourcePos = onInit ? 0 : getPositionOnLane();
238  // avoid superfluous waypoints for first and last edge
239  const bool skipFirst = stops.front() == source && (source != getEdge() || sourcePos + getBrakeGap() <= firstPos);
240  const bool skipLast = stops.back() == sink && myArrivalPos >= lastPos;
241 #ifdef DEBUG_REROUTE
242  if (DEBUG_COND) {
243  std::cout << SIMTIME << " reroute " << info << " veh=" << getID() << " lane=" << Named::getIDSecure(getLane())
244  << " source=" << source->getID() << " sourcePos=" << sourcePos << " firstPos=" << firstPos << " arrivalPos=" << myArrivalPos << " lastPos=" << lastPos
245  << " route=" << toString(myRoute->getEdges()) << " stopEdges=" << toString(stops) << " skipFirst=" << skipFirst << " skipLast=" << skipLast << "\n";
246  }
247 #endif
248  if (stops.size() == 1 && (skipFirst || skipLast)) {
249  stops.clear();
250  } else {
251  if (skipFirst) {
252  stops.erase(stops.begin());
253  }
254  if (skipLast) {
255  stops.erase(stops.end() - 1);
256  }
257  }
258  }
259  } else {
260  // via takes precedence over stop edges
261  // XXX check for inconsistencies #2275
262  for (std::vector<std::string>::const_iterator it = myParameter->via.begin(); it != myParameter->via.end(); ++it) {
263  MSEdge* viaEdge = MSEdge::dictionary(*it);
264  if (viaEdge == source || viaEdge == sink) {
265  continue;
266  }
267  assert(viaEdge != 0);
268  if (!viaEdge->isTazConnector() && viaEdge->allowedLanes(getVClass()) == nullptr) {
269  throw ProcessError("Vehicle '" + getID() + "' is not allowed on any lane of via edge '" + viaEdge->getID() + "'.");
270  }
271  stops.push_back(viaEdge);
272  }
273  }
274 
275  for (MSRouteIterator s = stops.begin(); s != stops.end(); ++s) {
276  // !!! need to adapt t here
277  ConstMSEdgeVector into;
278  router.computeLooped(source, *s, this, t, into, silent);
279  //std::cout << SIMTIME << " reroute veh=" << getID() << " source=" << source->getID() << " target=" << (*s)->getID() << " edges=" << toString(into) << "\n";
280  if (into.size() > 0) {
281  into.pop_back();
282  edges.insert(edges.end(), into.begin(), into.end());
283  if ((*s)->isTazConnector()) {
284  source = into.back();
285  edges.pop_back();
286  } else {
287  source = *s;
288  }
289  } else {
290  std::string error = "Vehicle '" + getID() + "' has no valid route from edge '" + source->getID() + "' to stop edge '" + (*s)->getID() + "'.";
291  if (MSGlobals::gCheckRoutes || silent) {
292  throw ProcessError(error);
293  } else {
294  WRITE_WARNING(error);
295  edges.push_back(source);
296  }
297  source = *s;
298  }
299  }
300  // router.setHint(myCurrEdge, myRoute->end(), this, t);
301  router.compute(source, sink, this, t, edges, silent);
302  if (edges.empty() && silent) {
303  return;
304  }
305  if (!edges.empty() && edges.front()->isTazConnector()) {
306  edges.erase(edges.begin());
307  }
308  if (!edges.empty() && edges.back()->isTazConnector()) {
309  edges.pop_back();
310  }
311  const double routeCost = router.recomputeCosts(edges, this, t);
312  const double previousCost = onInit ? routeCost : router.recomputeCosts(oldEdgesRemaining, this, t);
313  const double savings = previousCost - routeCost;
314  //if (getID() == "43") std::cout << SIMTIME << " pCost=" << previousCost << " cost=" << routeCost
315  // << " onInit=" << onInit
316  // << " prevEdges=" << toString(oldEdgesRemaining)
317  // << " newEdges=" << toString(edges)
318  // << "\n";
319  replaceRouteEdges(edges, routeCost, savings, info, onInit);
320  // this must be called even if the route could not be replaced
321  if (onInit) {
322  if (edges.empty()) {
324  throw ProcessError("Vehicle '" + getID() + "' has no valid route.");
325  } else if (source->isTazConnector()) {
326  WRITE_WARNING("Removing vehicle '" + getID() + "' which has no valid route.");
328  return;
329  }
330  }
332  calculateArrivalParams(onInit);
333  }
334 }
335 
336 
337 bool
338 MSBaseVehicle::replaceRouteEdges(ConstMSEdgeVector& edges, double cost, double savings, const std::string& info, bool onInit, bool check, bool removeStops, std::string* msgReturn) {
339  if (edges.empty()) {
340  WRITE_WARNING("No route for vehicle '" + getID() + "' found.");
341  if (msgReturn != nullptr) {
342  *msgReturn = "No route found";
343  }
344  return false;
345  }
346  // build a new id, first
347  std::string id = getID();
348  if (id[0] != '!') {
349  id = "!" + id;
350  }
351  const std::string idSuffix = id + "!var#";
352  int varIndex = 1;
353  id = idSuffix + toString(varIndex);
354  while (MSRoute::hasRoute(id)) {
355  id = idSuffix + toString(++varIndex);
356  }
357  int oldSize = (int)edges.size();
358  if (!onInit) {
359  const MSEdge* const origin = getRerouteOrigin();
360  if (origin != *myCurrEdge && edges.front() == origin) {
361  edges.insert(edges.begin(), *myCurrEdge);
362  oldSize = (int)edges.size();
363  }
364  edges.insert(edges.begin(), myRoute->begin(), myCurrEdge);
365  }
367  // re-assign stop iterators when rerouting to a new parkingArea
368  return true;
369  }
370  const RGBColor& c = myRoute->getColor();
371  MSRoute* newRoute = new MSRoute(id, edges, false, &c == &RGBColor::DEFAULT_COLOR ? nullptr : new RGBColor(c), std::vector<SUMOVehicleParameter::Stop>());
372  newRoute->setCosts(cost);
373  newRoute->setSavings(savings);
374  if (!MSRoute::dictionary(id, newRoute)) {
375  delete newRoute;
376  if (msgReturn != nullptr) {
377  *msgReturn = "duplicate routeID '" + id + "'";
378  }
379  return false;
380  }
381 
382  std::string msg;
383  if (check && !hasValidRoute(msg, newRoute)) {
384  WRITE_WARNING("Invalid route replacement for vehicle '" + getID() + "'. " + msg);
386  newRoute->addReference();
387  newRoute->release();
388  if (msgReturn != nullptr) {
389  *msgReturn = msg;
390  }
391  return false;
392  }
393  }
394  if (!replaceRoute(newRoute, info, onInit, (int)edges.size() - oldSize, false, removeStops, msgReturn)) {
395  newRoute->addReference();
396  newRoute->release();
397  return false;
398  }
399  return true;
400 }
401 
402 
403 bool
404 MSBaseVehicle::replaceRoute(const MSRoute* newRoute, const std::string& info, bool onInit, int offset, bool addRouteStops, bool removeStops, std::string* msgReturn) {
405  const ConstMSEdgeVector& edges = newRoute->getEdges();
406  // rebuild in-vehicle route information
407  if (onInit) {
408  myCurrEdge = newRoute->begin();
409  } else {
410  MSRouteIterator newCurrEdge = std::find(edges.begin() + offset, edges.end(), *myCurrEdge);
411  if (newCurrEdge == edges.end()) {
412  if (msgReturn != nullptr) {
413  *msgReturn = "current edge '" + (*myCurrEdge)->getID() + "' not found in new route";
414  }
415  return false;
416  }
417  if (getLane() != nullptr) {
418  if (getLane()->getEdge().isInternal() && (
419  (newCurrEdge + 1) == edges.end() || (*(newCurrEdge + 1)) != &(getLane()->getOutgoingViaLanes().front().first->getEdge()))) {
420  if (msgReturn != nullptr) {
421  *msgReturn = "Vehicle is on junction-internal edge leading elsewhere";
422  }
423  return false;
424  } else if (getPositionOnLane() > getLane()->getLength()
425  && (myCurrEdge + 1) != myRoute->end()
426  && (newCurrEdge + 1) != edges.end()
427  && *(myCurrEdge + 1) != *(newCurrEdge + 1)) {
428  if (msgReturn != nullptr) {
429  *msgReturn = "Vehicle is moving past junction and committed to move to another successor edge";
430  }
431  return false;
432  }
433  }
434  myCurrEdge = newCurrEdge;
435  }
436  const bool stopsFromScratch = onInit && myRoute->getStops().empty();
437  // check whether the old route may be deleted (is not used by anyone else)
438  newRoute->addReference();
439  myRoute->release();
440  // assign new route
441  myRoute = newRoute;
442  // update arrival definition
443  calculateArrivalParams(onInit);
444  // save information that the vehicle was rerouted
448  // if we did not drive yet it may be best to simply reassign the stops from scratch
449  if (stopsFromScratch) {
450  myStops.clear();
452  } else {
453  // recheck old stops
454  MSRouteIterator searchStart = myCurrEdge;
455  double lastPos = getPositionOnLane() + getBrakeGap();
456  if (getLane() != nullptr && getLane()->isInternal()
457  && myStops.size() > 0 && !myStops.front().lane->isInternal()) {
458  // searchStart is still incoming to the intersection so lastPos
459  // relative to that edge must be adapted
460  lastPos += (*myCurrEdge)->getLength();
461  }
462 #ifdef DEBUG_REPLACE_ROUTE
463  if (DEBUG_COND) {
464  std::cout << " replaceRoute on " << (*myCurrEdge)->getID() << " lane=" << Named::getIDSecure(getLane()) << " stopsFromScratch=" << stopsFromScratch << "\n";
465  }
466 #endif
467  for (std::list<MSStop>::iterator iter = myStops.begin(); iter != myStops.end();) {
468  double endPos = iter->getEndPos(*this);
469 #ifdef DEBUG_REPLACE_ROUTE
470  if (DEBUG_COND) {
471  std::cout << " stopEdge=" << iter->lane->getEdge().getID() << " start=" << (searchStart - myCurrEdge) << " endPos=" << endPos << " lastPos=" << lastPos << "\n";
472  }
473 #endif
474  if (*searchStart != &iter->lane->getEdge()
475  || endPos < lastPos) {
476  if (searchStart != edges.end() && !iter->reached) {
477  searchStart++;
478  }
479  }
480  lastPos = endPos;
481 
482  iter->edge = std::find(searchStart, edges.end(), &iter->lane->getEdge());
483 #ifdef DEBUG_REPLACE_ROUTE
484  if (DEBUG_COND) {
485  std::cout << " foundIndex=" << (iter->edge - myCurrEdge) << " end=" << (edges.end() - myCurrEdge) << "\n";
486  }
487 #endif
488  if (iter->edge == edges.end()) {
489  if (removeStops) {
490  iter = myStops.erase(iter);
491  continue;
492  } else {
493  assert(false);
494  }
495  } else {
496  searchStart = iter->edge;
497  }
498  ++iter;
499  }
500  // add new stops
501  if (addRouteStops) {
502  for (std::vector<SUMOVehicleParameter::Stop>::const_iterator i = newRoute->getStops().begin(); i != newRoute->getStops().end(); ++i) {
503  std::string error;
505  if (error != "") {
506  WRITE_WARNING(error);
507  }
508  }
509  }
510  }
511  return true;
512 }
513 
514 
515 double
517  return 0;
518 }
519 
520 
521 void
526 }
527 
528 
529 bool
531  return myDeparture != NOT_YET_DEPARTED;
532 }
533 
534 
535 bool
537  return succEdge(1) == nullptr;
538 }
539 
540 
541 int
543  return (int) std::distance(myRoute->begin(), myCurrEdge);
544 }
545 
546 
547 void
549  myCurrEdge = myRoute->begin() + index;
550  const_cast<SUMOVehicleParameter*>(myParameter)->departLaneProcedure = departLaneProcedure;
551  // !!! hack
552  myArrivalPos = (*(myRoute->end() - 1))->getLanes()[0]->getLength();
553 }
554 
555 double
558 }
559 
560 bool
562  if (t->isPerson() && getPersonNumber() >= getVehicleType().getPersonCapacity()) {
563  return false;
564  } else if (!t->isPerson() && getContainerNumber() >= getVehicleType().getContainerCapacity()) {
565  return false;
566  }
567  if (isStopped() && myStops.begin()->pars.permitted.size() > 0
568  && myStops.begin()->pars.permitted.count(t->getID()) == 0) {
569  return false;
570  }
571  MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(getDevice(typeid(MSDevice_Taxi)));
572  if (taxiDevice != nullptr) {
573  return taxiDevice->allowsBoarding(t);
574  }
575  return true;
576 }
577 
578 
579 void
581  if (transportable->isPerson()) {
582  if (myPersonDevice == nullptr) {
584  myMoveReminders.push_back(std::make_pair(myPersonDevice, 0.));
587  }
588  }
589  myPersonDevice->addTransportable(transportable);
590  } else {
591  if (myContainerDevice == nullptr) {
593  myMoveReminders.push_back(std::make_pair(myContainerDevice, 0.));
596  }
597  }
598  myContainerDevice->addTransportable(transportable);
599  }
600 }
601 
602 
603 bool
604 MSBaseVehicle::hasValidRoute(std::string& msg, const MSRoute* route) const {
605  MSRouteIterator start = myCurrEdge;
606  if (route == nullptr) {
607  route = myRoute;
608  } else {
609  start = route->begin();
610  }
611  MSRouteIterator last = route->end() - 1;
612  // check connectivity, first
613  for (MSRouteIterator e = start; e != last; ++e) {
614  if ((*e)->allowedLanes(**(e + 1), myType->getVehicleClass()) == nullptr) {
615  msg = "No connection between edge '" + (*e)->getID() + "' and edge '" + (*(e + 1))->getID() + "'.";
616  return false;
617  }
618  }
619  last = route->end();
620  // check usable lanes, then
621  for (MSRouteIterator e = start; e != last; ++e) {
622  if ((*e)->prohibits(this)) {
623  msg = "Edge '" + (*e)->getID() + "' prohibits.";
624  return false;
625  }
626  }
627  return true;
628 }
629 
630 
631 bool
633  if (myRoute->getEdges().size() > 0 && !(*myCurrEdge)->prohibits(this)) {
635  return true;
636  } else {
637  msg = "Vehicle '" + getID() + "' is not allowed to depart on its first edge.";
639  return false;
640  }
641 }
642 
643 
644 int
645 MSBaseVehicle::getRouteValidity(bool update, bool silent, std::string* msgReturn) {
646  if (!update) {
647  return myRouteValidity;
648  }
649  // insertion check must be done in any case
650  std::string msg;
651  if (!hasValidRouteStart(msg)) {
653  throw ProcessError(msg);
654  } else if (!silent) {
655  // vehicle will be discarded
656  WRITE_WARNING(msg);
657  } else if (msgReturn != nullptr) {
658  *msgReturn = msg;
659  }
660  }
662  && (myRouteValidity & ROUTE_UNCHECKED) != 0
663  // we could check after the first rerouting
665  if (!hasValidRoute(msg, myRoute)) {
667  throw ProcessError("Vehicle '" + getID() + "' has no valid route. " + msg);
668  }
669  }
671  return myRouteValidity;
672 }
673 
674 void
676 #ifdef _DEBUG
677  if (myTraceMoveReminders) {
678  traceMoveReminder("add", rem, 0, true);
679  }
680 #endif
681  myMoveReminders.push_back(std::make_pair(rem, 0.));
682 }
683 
684 
685 void
687  for (MoveReminderCont::iterator r = myMoveReminders.begin(); r != myMoveReminders.end(); ++r) {
688  if (r->first == rem) {
689 #ifdef _DEBUG
690  if (myTraceMoveReminders) {
691  traceMoveReminder("remove", rem, 0, false);
692  }
693 #endif
694  myMoveReminders.erase(r);
695  return;
696  }
697  }
698 }
699 
700 
701 void
703  for (MoveReminderCont::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end();) {
704  if (rem->first->notifyEnter(*this, reason, enteredLane)) {
705 #ifdef _DEBUG
706  if (myTraceMoveReminders) {
707  traceMoveReminder("notifyEnter", rem->first, rem->second, true);
708  }
709 #endif
710  ++rem;
711  } else {
712 #ifdef _DEBUG
713  if (myTraceMoveReminders) {
714  traceMoveReminder("notifyEnter", rem->first, rem->second, false);
715  }
716 #endif
717  rem = myMoveReminders.erase(rem);
718  }
719  }
720 }
721 
722 
723 void
725  if (myRoute->getLastEdge()->isTazConnector()) {
726  return;
727  }
729  if (!onInit) {
730  arrivalEdge = myRoute->getLastEdge();
731  // ingnore arrivalEdge parameter after rerouting
732  const_cast<SUMOVehicleParameter*>(myParameter)->arrivalEdge = -1;
733  }
734  const std::vector<MSLane*>& lanes = arrivalEdge->getLanes();
735  const double lastLaneLength = lanes[0]->getLength();
736  switch (myParameter->arrivalPosProcedure) {
738  if (fabs(myParameter->arrivalPos) > lastLaneLength) {
739  WRITE_WARNING("Vehicle '" + getID() + "' will not be able to arrive at the given position!");
740  }
741  // Maybe we should warn the user about invalid inputs!
742  myArrivalPos = MIN2(myParameter->arrivalPos, lastLaneLength);
743  if (myArrivalPos < 0) {
744  myArrivalPos = MAX2(myArrivalPos + lastLaneLength, 0.);
745  }
746  break;
748  myArrivalPos = RandHelper::rand(lastLaneLength);
749  break;
751  myArrivalPos = lastLaneLength / 2.;
752  break;
753  default:
754  myArrivalPos = lastLaneLength;
755  break;
756  }
758  if (myParameter->arrivalLane >= (int)lanes.size() || !lanes[myParameter->arrivalLane]->allowsVehicleClass(myType->getVehicleClass())) {
759  WRITE_WARNING("Vehicle '" + getID() + "' will not be able to arrive at the given lane '" + arrivalEdge->getID() + "_" + toString(myParameter->arrivalLane) + "'!");
760  }
761  myArrivalLane = MIN2(myParameter->arrivalLane, (int)(lanes.size() - 1));
763  myArrivalLane = -1;
764  for (MSLane* lane : lanes) {
765  if (lane->allowsVehicleClass(myType->getVehicleClass())) {
766  myArrivalLane = lane->getIndex();
767  break;
768  }
769  }
770  if (myArrivalLane == -1) {
771  WRITE_WARNING("Vehicle '" + getID() + "' has no usable arrivalLane on edge '" + arrivalEdge->getID() + "'.");
772  myArrivalLane = 0;
773  }
775  // pick random lane among all usable lanes
776  std::vector<MSLane*> usable;
777  for (MSLane* lane : lanes) {
778  if (lane->allowsVehicleClass(myType->getVehicleClass())) {
779  usable.push_back(lane);
780  }
781  }
782  if (usable.empty()) {
783  WRITE_WARNING("Vehicle '" + getID() + "' has no usable arrivalLane on edge '" + arrivalEdge->getID() + "'.");
784  myArrivalLane = 0;
785  } else {
786  myArrivalLane = usable[RandHelper::rand(0, (int)usable.size())]->getIndex();;
787  }
788  }
790  for (std::vector<MSLane*>::const_iterator l = lanes.begin(); l != lanes.end(); ++l) {
791  if (myParameter->arrivalSpeed <= (*l)->getVehicleMaxSpeed(this)) {
792  return;
793  }
794  }
795  WRITE_WARNING("Vehicle '" + getID() + "' will not be able to arrive with the given speed!");
796  }
797 }
798 
799 void
803  const int routeEdges = (int)myRoute->getEdges().size();
805  // write specific edge in vehroute output for reproducibility
806  pars->departEdge = RandHelper::rand(0, routeEdges);
808  }
809  assert(pars->departEdge >= 0);
810  if (pars->departEdge >= routeEdges) {
811  WRITE_WARNING("Ignoring departEdge " + toString(pars->departEdge) + " for vehicle '" + getID() + " with " + toString(routeEdges) + " route edges");
812  } else {
813  myCurrEdge += pars->departEdge;
814  }
815  }
817  const int routeEdges = (int)myRoute->getEdges().size();
818  const int begin = (int)(myCurrEdge - myRoute->begin());
819  // write specific edge in vehroute output for reproducibility
820  pars->arrivalEdge = RandHelper::rand(begin, routeEdges);
822  assert(pars->arrivalEdge >= begin);
823  assert(pars->arrivalEdge < routeEdges);
824  }
825 }
826 
827 
828 double
830  return MAX2(0., MIN2(1., getVehicleType().getImpatience() +
832 }
833 
834 
836 MSBaseVehicle::getDevice(const std::type_info& type) const {
837  for (MSVehicleDevice* const dev : myDevices) {
838  if (typeid(*dev) == type) {
839  return dev;
840  }
841  }
842  return nullptr;
843 }
844 
845 
846 void
848  // this saves lots of departParameters which are only needed for vehicles that did not yet depart
849  // the parameters may hold the name of a vTypeDistribution but we are interested in the actual type
851  // params and stops must be written in child classes since they may wish to add additional attributes first
853  std::ostringstream os;
854  os << myOdometer << " " << myNumberReroutes;
855  out.writeAttr(SUMO_ATTR_DISTANCE, os.str());
858  }
860  out.writeAttr(SUMO_ATTR_REROUTE, true);
861  }
863  // could be set from stop
865  }
866  // here starts the vehicle internal part (see loading)
867  // @note: remember to close the vehicle tag when calling this in a subclass!
868 }
869 
870 
871 bool
872 MSBaseVehicle::handleCollisionStop(MSStop& stop, const double distToStop) {
873  UNUSED_PARAMETER(stop);
874  UNUSED_PARAMETER(distToStop);
875  return true;
876 }
877 
878 
879 bool
881  return !myStops.empty() && myStops.begin()->reached /*&& myState.mySpeed < SUMO_const_haltingSpeed @todo #1864#*/;
882 }
883 
884 
885 bool
887  return isStopped() && myStops.begin()->pars.parking && (
888  myStops.begin()->parkingarea == nullptr || !myStops.begin()->parkingarea->parkOnRoad());
889 }
890 
891 
892 bool
894  return isStopped() && (myStops.begin()->triggered || myStops.begin()->containerTriggered || myStops.begin()->joinTriggered);
895 }
896 
897 
898 bool
899 MSBaseVehicle::isStoppedInRange(const double pos, const double tolerance) const {
900  if (isStopped()) {
901  const MSStop& stop = myStops.front();
902  return stop.pars.startPos - tolerance <= pos && stop.pars.endPos + tolerance >= pos;
903  }
904  return false;
905 }
906 
907 
908 double
909 MSBaseVehicle::basePos(const MSEdge* edge) const {
910  double result = MIN2(getVehicleType().getLength() + POSITION_EPS, edge->getLength());
911  if (hasStops()
912  && myStops.front().edge == myRoute->begin()
913  && (&myStops.front().lane->getEdge()) == *myStops.front().edge) {
914  result = MIN2(result, MAX2(0.0, myStops.front().getEndPos(*this)));
915  }
916  return result;
917 }
918 
919 MSLane*
921  const std::string edgeID = SUMOXMLDefinitions::getEdgeIDFromLane(stop.lane);
922  const int laneIndex = SUMOXMLDefinitions::getIndexFromLane(stop.lane);
923  const MSEdge* edge = MSEdge::dictionary(edgeID);
924  if (edge != nullptr && edge->getOppositeEdge() != nullptr
925  && laneIndex < (edge->getNumLanes() + edge->getOppositeEdge()->getNumLanes())) {
926  const int oppositeIndex = edge->getOppositeEdge()->getNumLanes() + edge->getNumLanes() - 1 - laneIndex;
927  stop.edge = edgeID;
928  return edge->getOppositeEdge()->getLanes()[oppositeIndex];
929  } else {
930  return nullptr;
931  }
932 }
933 
934 bool
935 MSBaseVehicle::addStop(const SUMOVehicleParameter::Stop& stopPar, std::string& errorMsg, SUMOTime untilOffset, bool collision,
936  MSRouteIterator* searchStart) {
937  MSStop stop(stopPar);
938  if (stopPar.lane == "") {
939  // use rightmost allowed lane
940  MSEdge* e = MSEdge::dictionary(stopPar.edge);
941  for (MSLane* cand : e->getLanes()) {
942  if (cand->allowsVehicleClass(getVClass())) {
943  stop.lane = cand;
944  break;
945  }
946  }
947  if (stop.lane == nullptr) {
948  errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on any lane of edge '" + stopPar.edge + "'.";
949  return false;
950  }
951  } else {
952  stop.lane = MSLane::dictionary(stopPar.lane);
953  if (stop.lane == nullptr) {
954  // must be an opposite stop
955  SUMOVehicleParameter::Stop tmp = stopPar;
956  stop.lane = interpretOppositeStop(tmp);
957  assert(stop.lane != nullptr);
958  }
960  errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on lane '" + stopPar.lane + "'.";
961  return false;
962  }
963  }
965  stop.segment = MSGlobals::gMesoNet->getSegmentForEdge(stop.lane->getEdge(), stop.getEndPos(*this));
966  if (stop.lane->isInternal()) {
967  errorMsg = "Mesoscopic simulation does not allow stopping on internal edge '" + stopPar.edge + "' for vehicle '" + myParameter->id + "'.";
968  return false;
969  }
970  }
971  stop.initPars(stopPar);
972  if (stopPar.until != -1) {
973  // !!! it would be much cleaner to invent a constructor for stops which takes "until" as an argument
974  const_cast<SUMOVehicleParameter::Stop&>(stop.pars).until += untilOffset;
975  }
976  if (stopPar.arrival != -1) {
977  const_cast<SUMOVehicleParameter::Stop&>(stop.pars).arrival += untilOffset;
978  }
979  stop.collision = collision;
980  std::string stopType = "stop";
981  std::string stopID = "";
982  if (stop.busstop != nullptr) {
983  stopType = "busStop";
984  stopID = stop.busstop->getID();
985  } else if (stop.containerstop != nullptr) {
986  stopType = "containerStop";
987  stopID = stop.containerstop->getID();
988  } else if (stop.chargingStation != nullptr) {
989  stopType = "chargingStation";
990  stopID = stop.chargingStation->getID();
991  } else if (stop.overheadWireSegment != nullptr) {
992  stopType = "overheadWireSegment";
993  stopID = stop.overheadWireSegment->getID();
994  } else if (stop.parkingarea != nullptr) {
995  stopType = "parkingArea";
996  stopID = stop.parkingarea->getID();
997  }
998  const std::string errorMsgStart = stopID == "" ? stopType : stopType + " '" + stopID + "'";
999 
1000  if (stop.pars.startPos < 0 || stop.pars.endPos > stop.lane->getLength()) {
1001  errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' has an invalid position.";
1002  return false;
1003  }
1004  if (stopType != "stop" && stopType != "parkingArea" && myType->getLength() / 2. > stop.pars.endPos - stop.pars.startPos
1005  && MSNet::getInstance()->warnOnce(stopType + ":" + stopID)) {
1006  errorMsg = errorMsgStart + " on lane '" + stop.lane->getID() + "' is too short for vehicle '" + myParameter->id + "'.";
1007  }
1008  const MSEdge* stopLaneEdge = &stop.lane->getEdge();
1009  const MSEdge* stopEdge;
1010  if (stopLaneEdge->getOppositeEdge() != nullptr && stopLaneEdge->getOppositeEdge()->getID() == stopPar.edge) {
1011  // stop lane is on the opposite side
1012  stopEdge = stopLaneEdge->getOppositeEdge();
1013  stop.isOpposite = true;
1014  } else {
1015  // if stop is on an internal edge the normal edge before the intersection is used
1016  stopEdge = stopLaneEdge->getNormalBefore();
1017  }
1018  if (searchStart == nullptr) {
1019  searchStart = &myCurrEdge;
1020  }
1021 #ifdef DEBUG_ADD_STOP
1022  if (DEBUG_COND) {
1023  std::cout << " stopEdge=" << stopEdge->getID() << " searchStart=" << (**searchStart)->getID() << " index=" << (int)((*searchStart) - myRoute->begin()) << " route=" << toString(myRoute->getEdges()) << "\n";
1024  }
1025 #endif
1026  stop.edge = std::find(*searchStart, myRoute->end(), stopEdge);
1027  MSRouteIterator prevStopEdge = myCurrEdge;
1028  const MSEdge* prevEdge = (getLane() == nullptr ? getEdge() : &getLane()->getEdge());
1029  double prevStopPos = getPositionOnLane();
1030  // where to insert the stop
1031  std::list<MSStop>::iterator iter = myStops.begin();
1032  if (stopPar.index == STOP_INDEX_END || stopPar.index >= static_cast<int>(myStops.size())) {
1033  iter = myStops.end();
1034  if (myStops.size() > 0 && myStops.back().edge >= *searchStart) {
1035  prevStopEdge = myStops.back().edge;
1036  prevEdge = &myStops.back().lane->getEdge();
1037  prevStopPos = myStops.back().pars.endPos;
1038  stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1039 #ifdef DEBUG_ADD_STOP
1040  if (DEBUG_COND) {
1041  std::cout << " (@end) prevStopEdge=" << (*prevStopEdge)->getID() << " index=" << (int)(prevStopEdge - myRoute->begin()) << "\n";
1042  }
1043 #endif
1044  if (prevStopEdge == stop.edge // laneEdge check is insufficient for looped routes
1045  && prevEdge == &stop.lane->getEdge() // route iterator check insufficient for internal lane stops
1046  && prevStopPos > stop.pars.endPos) {
1047  stop.edge = std::find(prevStopEdge + 1, myRoute->end(), stopEdge);
1048  }
1049  }
1050  } else {
1051  if (stopPar.index == STOP_INDEX_FIT) {
1052  while (iter != myStops.end() && (iter->edge < stop.edge ||
1053  (iter->pars.endPos < stop.pars.endPos && iter->edge == stop.edge))) {
1054  prevStopEdge = iter->edge;
1055  prevStopPos = iter->pars.endPos;
1056  ++iter;
1057  }
1058  } else {
1059  int index = stopPar.index;
1060  while (index > 0) {
1061  prevStopEdge = iter->edge;
1062  prevStopPos = iter->pars.endPos;
1063  ++iter;
1064  --index;
1065  }
1066 #ifdef DEBUG_ADD_STOP
1067  if (DEBUG_COND) {
1068  std::cout << " (@fit) prevStopEdge=" << (*prevStopEdge)->getID() << " index=" << (int)(prevStopEdge - myRoute->begin()) << "\n";
1069  }
1070 #endif
1071  stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1072  }
1073  }
1074  const bool wasTooClose = errorMsg != "" && errorMsg.find("too close") != std::string::npos;
1075  if (stop.edge == myRoute->end()) {
1076  if (!wasTooClose) {
1077  errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is not downstream the current route.";
1078  }
1079  return false;
1080  }
1081 
1082  const bool tooClose = (prevStopEdge == stop.edge && prevEdge == &stop.lane->getEdge() &&
1083  prevStopPos + (iter == myStops.begin() ? getBrakeGap() : 0) > stop.pars.endPos + POSITION_EPS);
1084 
1085  if (prevStopEdge > stop.edge ||
1086  // a collision-stop happens after vehicle movement and may move the
1087  // vehicle backwards on it's lane (prevStopPos is the vehicle position)
1088  (tooClose && !collision)
1089  || (stop.lane->getEdge().isInternal() && stop.lane->getNextNormal() != *(stop.edge + 1))) {
1090  // check if the edge occurs again later in the route
1091  //std::cout << " could not add stop " << errorMsgStart << " prevStops=" << myStops.size() << " searchStart=" << (*searchStart - myRoute->begin()) << " route=" << toString(myRoute->getEdges()) << "\n";
1092  if (tooClose && prevStopPos <= stop.pars.endPos + POSITION_EPS) {
1093  errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.pars.lane + "' is too close to brake.";
1094  }
1095  MSRouteIterator next = stop.edge + 1;
1096  return addStop(stopPar, errorMsg, untilOffset, collision, &next);
1097  }
1098  if (wasTooClose) {
1099  errorMsg = "";
1100  }
1101  // David.C:
1102  //if (!stop.parking && (myCurrEdge == stop.edge && myState.myPos > stop.endPos - getCarFollowModel().brakeGap(myState.mySpeed))) {
1103  const double endPosOffset = stop.lane->getEdge().isInternal() ? (*stop.edge)->getLength() : 0;
1104  const double distToStop = stop.pars.endPos + endPosOffset - getPositionOnLane();
1105  if (collision && !handleCollisionStop(stop, distToStop)) {
1106  return false;
1107  }
1108  if (!hasDeparted() && myCurrEdge == stop.edge) {
1109  double pos = -1;
1111  pos = myParameter->departPos;
1112  if (pos < 0.) {
1113  pos += (*myCurrEdge)->getLength();
1114  }
1115  }
1117  pos = MIN2(stop.pars.endPos + endPosOffset, basePos(*myCurrEdge));
1118  }
1119  if (pos > stop.pars.endPos + endPosOffset) {
1120  if (stop.edge != myRoute->end()) {
1121  // check if the edge occurs again later in the route
1122  MSRouteIterator next = stop.edge + 1;
1123  return addStop(stopPar, errorMsg, untilOffset, collision, &next);
1124  }
1125  errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is before departPos.";
1126  return false;
1127  }
1128  }
1129  if (iter != myStops.begin()) {
1130  std::list<MSStop>::iterator iter2 = iter;
1131  iter2--;
1132  if (stop.pars.until >= 0 && iter2->pars.until > stop.pars.until) {
1133  errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1134  + "' set to end at " + time2string(stop.pars.until)
1135  + " earlier than previous stop at " + time2string(iter2->pars.until) + ".";
1136  }
1137  }
1138  myStops.insert(iter, stop);
1139  //std::cout << " added stop " << errorMsgStart << " totalStops=" << myStops.size() << " searchStart=" << (*searchStart - myRoute->begin())
1140  // << " routeIndex=" << (stop.edge - myRoute->begin())
1141  // << " stopIndex=" << std::distance(myStops.begin(), iter)
1142  // << " route=" << toString(myRoute->getEdges()) << "\n";
1143  return true;
1144 }
1145 
1146 
1147 void
1148 MSBaseVehicle::addStops(const bool ignoreStopErrors, MSRouteIterator* searchStart) {
1149  for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
1150  std::string errorMsg;
1151  if (!addStop(stop, errorMsg, myParameter->depart, stop.startPos == stop.endPos, searchStart) && !ignoreStopErrors) {
1152  throw ProcessError(errorMsg);
1153  }
1154  if (errorMsg != "") {
1155  WRITE_WARNING(errorMsg);
1156  }
1157  }
1159  for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
1160  std::string errorMsg;
1161  if (!addStop(stop, errorMsg, untilOffset, stop.startPos == stop.endPos, searchStart) && !ignoreStopErrors) {
1162  throw ProcessError(errorMsg);
1163  }
1164  if (errorMsg != "") {
1165  WRITE_WARNING(errorMsg);
1166  }
1167  }
1168 }
1169 
1170 
1171 bool
1173  MSRouteIterator start = myCurrEdge;
1174  const std::string err = "for vehicle '" + getID() + "' at time=" + time2string(SIMSTEP);
1175  int i = 0;
1176  bool ok = true;
1177  double lastPos = getPositionOnLane();
1178  if (getLane() != nullptr && getLane()->isInternal()
1179  && myStops.size() > 0 && !myStops.front().lane->isInternal()) {
1180  // start edge is still incoming to the intersection so lastPos
1181  // relative to that edge must be adapted
1182  lastPos += (*myCurrEdge)->getLength();
1183  }
1184  for (const MSStop& stop : myStops) {
1185  const double endPos = stop.getEndPos(*this);
1186  MSRouteIterator it;
1187  const std::string prefix = "Stop " + toString(i) + " on edge '" + stop.lane->getEdge().getID() + "' ";
1188  if (stop.lane->isInternal()) {
1189  // find the normal predecessor and ensure that the next route edge
1190  // matches the successor of the internal edge successor
1191  it = std::find(start, myRoute->end(), stop.lane->getEdge().getNormalBefore());
1192  if (it != myRoute->end() && (
1193  it + 1 == myRoute->end() || *(it + 1) != stop.lane->getEdge().getNormalSuccessor())) {
1194  it = myRoute->end(); // signal failure
1195  }
1196  } else {
1197  const MSEdge* const stopEdge = &stop.lane->getEdge();
1198  it = std::find(start, myRoute->end(), stopEdge);
1199  }
1200  if (it == myRoute->end()) {
1201  WRITE_ERROR(prefix + "is not found after edge '" + (*start)->getID() + "' (" + toString(start - myCurrEdge) + " after current " + err);
1202  ok = false;
1203  } else {
1204  MSRouteIterator it2;
1205  for (it2 = myRoute->begin(); it2 != myRoute->end(); it2++) {
1206  if (it2 == stop.edge) {
1207  break;
1208  }
1209  }
1210  if (it2 == myRoute->end()) {
1211  WRITE_ERROR(prefix + "used invalid route index " + err);
1212  ok = false;
1213  } else if (it2 < start) {
1214  WRITE_ERROR(prefix + "used invalid (relative) route index " + toString(it2 - myCurrEdge) + " expected after " + toString(start - myCurrEdge) + " " + err);
1215  ok = false;
1216  } else {
1217  if (it != stop.edge) {
1218  double brakeGap = i == 0 ? getBrakeGap() : 0;
1219  if (endPos >= lastPos + brakeGap) {
1220  WRITE_WARNING(prefix + "is used in " + toString(stop.edge - myCurrEdge) + " edges but first encounter is in "
1221  + toString(it - myCurrEdge) + " edges " + err);
1222  }
1223  }
1224  start = stop.edge;
1225  }
1226  }
1227  lastPos = endPos;
1228  i++;
1229  }
1230  return ok;
1231 }
1232 
1233 
1234 const ConstMSEdgeVector
1235 MSBaseVehicle::getStopEdges(double& firstPos, double& lastPos) const {
1236  assert(haveValidStopEdges());
1237  ConstMSEdgeVector result;
1238  const MSStop* prev = nullptr;
1239  const MSEdge* internalSuccessor = nullptr;
1240  for (const MSStop& stop : myStops) {
1241  if (stop.reached) {
1242  continue;
1243  }
1244  const double stopPos = stop.getEndPos(*this);
1245  if ((prev == nullptr
1246  || prev->edge != stop.edge
1247  || (prev->lane == stop.lane && prev->getEndPos(*this) > stopPos))
1248  && *stop.edge != internalSuccessor) {
1249  result.push_back(*stop.edge);
1250  if (stop.lane->isInternal()) {
1251  internalSuccessor = stop.lane->getNextNormal();
1252  result.push_back(internalSuccessor);
1253  } else {
1254  internalSuccessor = nullptr;
1255  }
1256  }
1257  prev = &stop;
1258  if (firstPos < 0) {
1259  firstPos = stopPos;
1260  }
1261  lastPos = stopPos;
1262  }
1263  //std::cout << "getStopEdges veh=" << getID() << " result=" << toString(result) << "\n";
1264  return result;
1265 }
1266 
1267 
1268 std::vector<std::pair<int, double> >
1270  std::vector<std::pair<int, double> > result;
1271  for (std::list<MSStop>::const_iterator iter = myStops.begin(); iter != myStops.end(); ++iter) {
1272  result.push_back(std::make_pair(
1273  (int)(iter->edge - myRoute->begin()),
1274  iter->getEndPos(*this)));
1275  }
1276  return result;
1277 }
1278 
1279 
1280 MSStop&
1282  assert(myStops.size() > 0);
1283  return myStops.front();
1284 }
1285 
1286 
1289  if (hasStops()) {
1290  return &myStops.front().pars;
1291  }
1292  return nullptr;
1293 }
1294 
1295 
1296 bool
1298  //if the stop exists update the duration
1299  for (std::list<MSStop>::iterator iter = myStops.begin(); iter != myStops.end(); iter++) {
1300  if (iter->lane->getID() == stop.lane && fabs(iter->pars.endPos - stop.endPos) < POSITION_EPS) {
1301  // update existing stop
1302  if (stop.duration == 0 && stop.until < 0 && !iter->reached) {
1303  myStops.erase(iter);
1304  // XXX also erase from myParameter->stops ?
1305  } else {
1306  iter->duration = stop.duration;
1307  iter->triggered = stop.triggered;
1308  iter->containerTriggered = stop.containerTriggered;
1309  const_cast<SUMOVehicleParameter::Stop&>(iter->pars).until = stop.until;
1310  const_cast<SUMOVehicleParameter::Stop&>(iter->pars).parking = stop.parking;
1311  }
1312  return true;
1313  }
1314  }
1315  const bool result = addStop(stop, errorMsg);
1316  if (result) {
1318  myParameter->stops.push_back(stop);
1319  }
1320  return result;
1321 }
1322 
1323 
1324 bool
1325 MSBaseVehicle::abortNextStop(int nextStopIndex) {
1326  if (hasStops() && nextStopIndex < (int)myStops.size()) {
1327  if (nextStopIndex == 0 && isStopped()) {
1329  } else {
1330  auto stopIt = myStops.begin();
1331  std::advance(stopIt, nextStopIndex);
1332  myStops.erase(stopIt);
1333  }
1334  return true;
1335  } else {
1336  return false;
1337  }
1338 }
1339 
1340 
1341 bool
1342 MSBaseVehicle::replaceStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string& info, bool teleport, std::string& errorMsg) {
1343  const int n = (int)myStops.size();
1344  if (nextStopIndex < 0 || nextStopIndex >= n) {
1345  errorMsg = ("Invalid nextStopIndex '" + toString(nextStopIndex) + "' for " + toString(n) + " remaining stops");
1346  return false;
1347  }
1348  if (nextStopIndex == 0 && isStopped()) {
1349  errorMsg = "Cannot replace reached stop";
1350  return false;
1351  }
1353  MSLane* stopLane = MSLane::dictionary(stop.lane);
1354  MSEdge* stopEdge = &stopLane->getEdge();
1355 
1356  auto itStop = myStops.begin();
1357  std::advance(itStop, nextStopIndex);
1358  MSStop& replacedStop = *itStop;
1359 
1360  if (replacedStop.lane == stopLane && replacedStop.pars.endPos == stop.endPos && !teleport) {
1361  // only replace stop attributes
1362  const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
1363  replacedStop.initPars(stop);
1364  return true;
1365  }
1366 
1367  if (!stopLane->allowsVehicleClass(getVClass())) {
1368  errorMsg = ("Disallowed stop lane '" + stopLane->getID() + "'");
1369  return false;
1370  }
1371 
1372  const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
1373  std::vector<MSStop> stops(myStops.begin(), myStops.end());
1374  const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
1375  MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
1376  double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
1377  MSRouteIterator itEnd = nextStopIndex == n - 1 ? oldEdges.end() - 1 : stops[nextStopIndex + 1].edge;
1378  auto endPos = nextStopIndex == n - 1 ? getArrivalPos() : stops[nextStopIndex + 1].pars.endPos;
1380 
1381  bool newDestination = nextStopIndex == n - 1 && stops[nextStopIndex].edge == oldEdges.end() - 1;
1382 
1383  ConstMSEdgeVector toNewStop;
1384  if (!teleport) {
1385  router.compute(*itStart, startPos, stopEdge, stop.endPos, this, t, toNewStop, true);
1386  if (toNewStop.size() == 0) {
1387  errorMsg = "No route found from edge '" + (*itStart)->getID() + "' to stop edge '" + stopEdge->getID() + "'";
1388  return false;
1389  }
1390  }
1391 
1392  ConstMSEdgeVector fromNewStop;
1393  if (!newDestination) {
1394  router.compute(stopEdge, stop.endPos, *itEnd, endPos, this, t, fromNewStop, true);
1395  if (fromNewStop.size() == 0) {
1396  errorMsg = "No route found from stop edge '" + stopEdge->getID() + "' to edge '" + (*itEnd)->getID() + "'";
1397  return false;
1398  }
1399  }
1400 
1401  const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
1402  replacedStop.initPars(stop);
1403  replacedStop.edge = myRoute->end(); // will be patched in replaceRoute
1404  replacedStop.lane = stopLane;
1405  if (MSGlobals::gUseMesoSim) {
1406  replacedStop.segment = MSGlobals::gMesoNet->getSegmentForEdge(replacedStop.lane->getEdge(), replacedStop.getEndPos(*this));
1407  if (replacedStop.lane->isInternal()) {
1408  errorMsg = "Mesoscopic simulation does not allow stopping on internal edge '" + stop.edge + "' for vehicle '" + getID() + "'.";
1409  return false;
1410  }
1411  }
1412 
1413  ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
1414  ConstMSEdgeVector newEdges; // only remaining
1415  newEdges.insert(newEdges.end(), myCurrEdge, itStart);
1416  if (!teleport) {
1417  newEdges.insert(newEdges.end(), toNewStop.begin(), toNewStop.end() - 1);
1418  } else {
1419  newEdges.push_back(*itStart);
1420  }
1421  if (!newDestination) {
1422  newEdges.insert(newEdges.end(), fromNewStop.begin(), fromNewStop.end() - 1);
1423  newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
1424  } else {
1425  newEdges.push_back(stopEdge);
1426  }
1427  //std::cout << SIMTIME << " replaceStop veh=" << getID()
1428  // << " oldEdges=" << oldRemainingEdges.size()
1429  // << " newEdges=" << newEdges.size()
1430  // << " toNewStop=" << toNewStop.size()
1431  // << " fromNewStop=" << fromNewStop.size()
1432  // << "\n";
1433 
1434  const double routeCost = router.recomputeCosts(newEdges, this, t);
1435  const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
1436  const double savings = previousCost - routeCost;
1437  if (!hasDeparted()) {
1438  // stops will be rebuilt from scratch so we must patch the stops in myParameter
1439  const_cast<SUMOVehicleParameter*>(myParameter)->stops[nextStopIndex] = stop;
1440  }
1441  return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
1442 }
1443 
1444 
1445 
1446 
1447 double
1449  if (isOnRoad() || isIdling()) {
1451  } else {
1452  return 0.;
1453  }
1454 }
1455 
1456 
1457 double
1459  if (isOnRoad() || isIdling()) {
1461  } else {
1462  return 0.;
1463  }
1464 }
1465 
1466 
1467 double
1469  if (isOnRoad() || isIdling()) {
1471  } else {
1472  return 0.;
1473  }
1474 }
1475 
1476 
1477 double
1479  if (isOnRoad() || isIdling()) {
1481  } else {
1482  return 0.;
1483  }
1484 }
1485 
1486 
1487 double
1489  if (isOnRoad() || isIdling()) {
1491  } else {
1492  return 0.;
1493  }
1494 }
1495 
1496 
1497 double
1499  if (isOnRoad() || isIdling()) {
1501  } else {
1502  return 0.;
1503  }
1504 }
1505 
1506 
1507 double
1509  if (isOnRoad() || isIdling()) {
1511  } else {
1512  return 0.;
1513  }
1514 }
1515 
1516 double
1518  if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
1519  MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
1520  return batteryOfVehicle->getActualBatteryCapacity();
1521  } else {
1522  if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
1523  MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
1524  return batteryOfVehicle->getActualBatteryCapacity();
1525  }
1526  }
1527 
1528  return -1;
1529 }
1530 
1531 double
1533  if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
1534  MSDevice_ElecHybrid* elecHybridDevice = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
1535  return elecHybridDevice->getCurrentFromOverheadWire();
1536  }
1537 
1538  return NAN;
1539 }
1540 
1541 double
1543  if (isOnRoad() || isIdling()) {
1545  } else {
1546  return 0.;
1547  }
1548 }
1549 
1550 
1551 const MSEdgeWeightsStorage&
1553  return _getWeightsStorage();
1554 }
1555 
1556 
1559  return _getWeightsStorage();
1560 }
1561 
1562 
1565  if (myEdgeWeights == nullptr) {
1567  }
1568  return *myEdgeWeights;
1569 }
1570 
1571 
1572 
1573 
1574 int
1576  int boarded = myPersonDevice == nullptr ? 0 : myPersonDevice->size();
1577  return boarded + myParameter->personNumber;
1578 }
1579 
1580 std::vector<std::string>
1582  std::vector<std::string> ret;
1583  const std::vector<MSTransportable*>& persons = getPersons();
1584  for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
1585  ret.push_back((*it_p)->getID());
1586  }
1587  return ret;
1588 }
1589 
1590 int
1592  int loaded = myContainerDevice == nullptr ? 0 : myContainerDevice->size();
1593  return loaded + myParameter->containerNumber;
1594 }
1595 
1596 
1597 void
1599  // this might be called from the MSTransportable destructor so we cannot do a dynamic cast to determine the type
1600  if (myPersonDevice != nullptr) {
1602  }
1603  if (myContainerDevice != nullptr) {
1605  }
1606 }
1607 
1608 
1609 const std::vector<MSTransportable*>&
1611  if (myPersonDevice == nullptr) {
1613  } else {
1615  }
1616 }
1617 
1618 
1619 const std::vector<MSTransportable*>&
1621  if (myContainerDevice == nullptr) {
1623  } else {
1625  }
1626 }
1627 
1628 
1629 bool
1630 MSBaseVehicle::isLineStop(double position) const {
1631  if (myParameter->line == "") {
1632  // not a public transport line
1633  return false;
1634  }
1635  for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
1636  if (stop.startPos <= position && position <= stop.endPos) {
1637  return true;
1638  }
1639  }
1640  for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
1641  if (stop.startPos <= position && position <= stop.endPos) {
1642  return true;
1643  }
1644  }
1645  return false;
1646 }
1647 
1648 
1649 bool
1650 MSBaseVehicle::hasDevice(const std::string& deviceName) const {
1651  for (MSDevice* const dev : myDevices) {
1652  if (dev->deviceName() == deviceName) {
1653  return true;
1654  }
1655  }
1656  return false;
1657 }
1658 
1659 
1660 void
1661 MSBaseVehicle::createDevice(const std::string& deviceName) {
1662  if (!hasDevice(deviceName)) {
1663  if (deviceName == "rerouting") {
1664  ((SUMOVehicleParameter*)myParameter)->setParameter("has." + deviceName + ".device", "true");
1666  if (hasDeparted()) {
1667  // vehicle already departed: disable pre-insertion rerouting and enable regular routing behavior
1668  MSDevice_Routing* routingDevice = static_cast<MSDevice_Routing*>(getDevice(typeid(MSDevice_Routing)));
1669  assert(routingDevice != 0);
1670  routingDevice->notifyEnter(*this, MSMoveReminder::NOTIFICATION_DEPARTED);
1671  }
1672  } else {
1673  throw InvalidArgument("Creating device of type '" + deviceName + "' is not supported");
1674  }
1675  }
1676 }
1677 
1678 
1679 std::string
1680 MSBaseVehicle::getDeviceParameter(const std::string& deviceName, const std::string& key) const {
1681  for (MSVehicleDevice* const dev : myDevices) {
1682  if (dev->deviceName() == deviceName) {
1683  return dev->getParameter(key);
1684  }
1685  }
1686  throw InvalidArgument("No device of type '" + deviceName + "' exists");
1687 }
1688 
1689 
1690 void
1691 MSBaseVehicle::setDeviceParameter(const std::string& deviceName, const std::string& key, const std::string& value) {
1692  for (MSVehicleDevice* const dev : myDevices) {
1693  if (dev->deviceName() == deviceName) {
1694  dev->setParameter(key, value);
1695  return;
1696  }
1697  }
1698  throw InvalidArgument("No device of type '" + deviceName + "' exists");
1699 }
1700 
1701 
1702 void
1703 MSBaseVehicle::setJunctionModelParameter(const std::string& key, const std::string& value) {
1706  const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
1707  // checked in MSLink::ignoreFoe
1708  } else {
1709  throw InvalidArgument("Vehicle '" + getID() + "' does not support junctionModel parameter '" + key + "'");
1710  }
1711 }
1712 
1713 
1714 void
1716  /* Design idea for additioanl junction model parameters:
1717  We can distinguish between 3 levels of parameters
1718  1. typically shared buy multiple vehicles -> vType parameter
1719  2. specific to one vehicle but stays constant throughout the simulation -> vehicle parameter
1720  3. specific to one vehicle and expected to change during simulation -> prefixed generic vehicle parameter
1721  */
1722  for (auto item : getParameter().getParametersMap()) {
1723  if (StringUtils::startsWith(item.first, "junctionModel.")) {
1724  setJunctionModelParameter(item.first, item.second);
1725  }
1726  }
1727 }
1728 
1729 
1730 void
1732  assert(type != nullptr);
1733  if (myType->isVehicleSpecific() && type != myType) {
1735  }
1736  myType = type;
1737 }
1738 
1739 
1742  if (myType->isVehicleSpecific()) {
1743  return *myType;
1744  }
1745  MSVehicleType* type = myType->buildSingularType(myType->getID() + "@" + getID());
1746  replaceVehicleType(type);
1747  return *type;
1748 }
1749 
1750 
1751 int
1753  const MSLane* const lane = getLane();
1754  if (lane == nullptr) {
1755  return getEdge()->getLanes()[0]->getRNGIndex();
1756  } else {
1757  return lane->getRNGIndex();
1758  }
1759 }
1760 
1761 
1762 SumoRNG*
1764  const MSLane* lane = getLane();
1765  if (lane == nullptr) {
1766  return getEdge()->getLanes()[0]->getRNG();
1767  } else {
1768  return lane->getRNG();
1769  }
1770 }
1771 
1772 std::string
1773 MSBaseVehicle::getPrefixedParameter(const std::string& key, std::string& error) const {
1774  const MSVehicle* microVeh = dynamic_cast<const MSVehicle*>(this);
1775  if (StringUtils::startsWith(key, "device.")) {
1776  StringTokenizer tok(key, ".");
1777  if (tok.size() < 3) {
1778  error = "Invalid device parameter '" + key + "' for vehicle '" + getID() + "'.";
1779  return "";
1780  }
1781  try {
1782  return getDeviceParameter(tok.get(1), key.substr(tok.get(0).size() + tok.get(1).size() + 2));
1783  } catch (InvalidArgument& e) {
1784  error = "Vehicle '" + getID() + "' does not support device parameter '" + key + "' (" + e.what() + ").";
1785  return "";
1786  }
1787  } else if (StringUtils::startsWith(key, "laneChangeModel.")) {
1788  if (microVeh == nullptr) {
1789  error = "Meso Vehicle '" + getID() + "' does not support laneChangeModel parameters.";
1790  return "";
1791  }
1792  const std::string attrName = key.substr(16);
1793  try {
1794  return microVeh->getLaneChangeModel().getParameter(attrName);
1795  } catch (InvalidArgument& e) {
1796  error = "Vehicle '" + getID() + "' does not support laneChangeModel parameter '" + key + "' (" + e.what() + ").";
1797  return "";
1798  }
1799  } else if (StringUtils::startsWith(key, "carFollowModel.")) {
1800  if (microVeh == nullptr) {
1801  error = "Meso Vehicle '" + getID() + "' does not support carFollowModel parameters.";
1802  return "";
1803  }
1804  const std::string attrName = key.substr(15);
1805  try {
1806  return microVeh->getCarFollowModel().getParameter(microVeh, attrName);
1807  } catch (InvalidArgument& e) {
1808  error = "Vehicle '" + getID() + "' does not support carFollowModel parameter '" + key + "' (" + e.what() + ").";
1809  return "";
1810  }
1811  } else if (StringUtils::startsWith(key, "has.") && StringUtils::endsWith(key, ".device")) {
1812  StringTokenizer tok(key, ".");
1813  if (tok.size() != 3) {
1814  error = "Invalid check for device. Expected format is 'has.DEVICENAME.device'.";
1815  return "";
1816  }
1817  return hasDevice(tok.get(1)) ? "true" : "false";
1818  } else {
1819  return getParameter().getParameter(key, "");
1820  }
1821 }
1822 
1823 void
1825  if (myParkingMemory == nullptr) {
1827  }
1828  (*myParkingMemory)[pa].blockedAtTime = SIMSTEP;
1829  if (local) {
1830  (*myParkingMemory)[pa].blockedAtTimeLocal = SIMSTEP;
1831  }
1832 }
1833 
1834 void
1836  if (myParkingMemory != nullptr) {
1837  for (auto& item : *myParkingMemory) {
1838  item.second.score = "";
1839  }
1840  }
1841 }
1842 
1843 void
1844 MSBaseVehicle::rememberParkingAreaScore(const MSParkingArea* pa, const std::string& score) {
1845  if (myParkingMemory == nullptr) {
1847  }
1848  (*myParkingMemory)[pa].score = score;
1849 }
1850 
1851 
1852 SUMOTime
1854  if (myParkingMemory == nullptr) {
1855  return -1;
1856  }
1857  auto it = myParkingMemory->find(pa);
1858  if (it == myParkingMemory->end()) {
1859  return -1;
1860  } else {
1861  return local ? it->second.blockedAtTimeLocal : it->second.blockedAtTime;
1862  }
1863 }
1864 
1865 #ifdef _DEBUG
1866 void
1867 MSBaseVehicle::initMoveReminderOutput(const OptionsCont& oc) {
1868  if (oc.isSet("movereminder-output.vehicles")) {
1869  const std::vector<std::string> vehicles = oc.getStringVector("movereminder-output.vehicles");
1870  myShallTraceMoveReminders.insert(vehicles.begin(), vehicles.end());
1871  }
1872 }
1873 
1874 
1875 void
1876 MSBaseVehicle::traceMoveReminder(const std::string& type, MSMoveReminder* rem, double pos, bool keep) const {
1877  OutputDevice& od = OutputDevice::getDeviceByOption("movereminder-output");
1878  od.openTag("movereminder");
1879  od.writeAttr(SUMO_ATTR_TIME, STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()));
1880  od.writeAttr("veh", getID());
1882  od.writeAttr("type", type);
1883  od.writeAttr("pos", toString(pos));
1884  od.writeAttr("keep", toString(keep));
1885  od.closeTag();
1886 }
1887 #endif
1888 
1889 
1890 /****************************************************************************/
#define DEBUG_COND
std::vector< const MSEdge * > ConstMSEdgeVector
Definition: MSEdge.h:74
ConstMSEdgeVector::const_iterator MSRouteIterator
Definition: MSRoute.h:54
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:288
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:280
std::string time2string(SUMOTime t)
convert SUMOTime to string
Definition: SUMOTime.cpp:68
#define STEPS2TIME(x)
Definition: SUMOTime.h:53
#define SIMSTEP
Definition: SUMOTime.h:59
#define SUMOTime_MAX
Definition: SUMOTime.h:33
#define SIMTIME
Definition: SUMOTime.h:60
long long int SUMOTime
Definition: SUMOTime.h:32
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ 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 VEHPARS_SPEEDFACTOR_SET
@ RANDOM
The lane is chosen randomly.
@ GIVEN
The arrival lane is given.
@ FIRST_ALLOWED
The rightmost lane the vehicle may use.
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 VEHPARS_LINE_SET
@ DEPART_CONTAINER_TRIGGERED
The departure is container triggered.
@ DEPART_TRIGGERED
The departure is person triggered.
@ SUMO_TAG_PARKING_AREA_REROUTE
entry for an alternative parking zone
@ SUMO_TAG_VEHICLE
description of a vehicle
@ 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_TIME
trigger: the time of the step
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MIN2(T a, T b)
Definition: StdDefs.h:74
T MAX2(T a, T b)
Definition: StdDefs.h:80
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
An upper class for objects with additional parameters.
Definition: EnergyParams.h:41
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:314
virtual std::string getParameter(const std::string &key) const
try to retrieve the given parameter from this laneChangeModel. Throw exception for unsupported key
SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT(const int rngIndex, SUMOVehicleClass svc) const
double getMaxSpeed() const
Returns the maximum speed.
MSVehicleDevice * getDevice(const std::type_info &type) const
Returns a device of the given type if it exists or 0.
void addStops(const bool ignoreStopErrors, MSRouteIterator *searchStart=nullptr)
Adds stops to the built vehicle.
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.
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 initJunctionModelParams()
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)
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 resetParkingAreaScores()
MSVehicleType * myType
This vehicle's type.
MoveReminderCont myMoveReminders
Currently relevant move reminders.
bool allowsBoarding(MSTransportable *t) const
whether the given transportable is allowed to board this vehicle
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.
double getFuelConsumption() const
Returns fuel consumption of the current state.
void replaceParameter(const SUMOVehicleParameter *newParameter)
replace the vehicle parameter (deleting the old one)
double getCO2Emissions() const
Returns CO2 emission of the current state.
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)
const EnergyParams * getEmissionParameters() const
Returns the vehicle's emission model parameter.
double getElectricityConsumption() const
Returns electricity consumption of the current state.
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
static NumericalID myCurrentNumericalIndex
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.
double getLength() const
Returns the vehicle's length.
bool isParking() const
Returns whether the vehicle is parking.
const MSEdge * getEdge() const
Returns the edge the vehicle is currently at.
double getHarmonoise_NoiseEmissions() const
Returns noise emissions of the current state.
bool hasValidRoute(std::string &msg, const MSRoute *route=0) const
Validates the current or given route.
bool isStoppedInRange(const double pos, const double tolerance) const
return whether the given position is within range of the current stop
int getPersonNumber() const
Returns the number of persons.
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
double getNOxEmissions() const
Returns NOx emission of the current state.
void setID(const std::string &newID)
set the id (inherited from Named but forbidden for vehicles)
double getPMxEmissions() const
Returns PMx emission of the current state.
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
bool hasDeparted() const
Returns whether this vehicle has already departed.
MSStop & getNextStop()
double getCOEmissions() const
Returns CO emission of the current state.
MSDevice_Transportable * myContainerDevice
The containers this vehicle may have.
MSBaseVehicle(SUMOVehicleParameter *pars, const MSRoute *route, MSVehicleType *type, const double speedFactor)
Constructor.
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 type
SumoRNG * getRNG() const
virtual const MSEdge * getRerouteOrigin() const
Returns the starting point for reroutes (usually the current edge)
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 MSRoute * myRoute
This vehicle's route.
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
bool hasStops() const
Returns whether the vehicle has to stop somewhere.
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:70
@ ROUTE_START_INVALID_PERMISSIONS
Definition: MSBaseVehicle.h:72
std::string getPrefixedParameter(const std::string &key, std::string &error) const
retrieve parameters of devices, models and the vehicle itself
void removeTransportable(MSTransportable *t)
removes a person or container
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
virtual bool replaceRoute(const MSRoute *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.
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
virtual ~MSBaseVehicle()
Destructor.
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
bool addStop(const SUMOVehicleParameter::Stop &stopPar, std::string &errorMsg, SUMOTime untilOffset=0, bool collision=false, MSRouteIterator *searchStart=nullptr)
Adds a stop.
void rememberParkingAreaScore(const MSParkingArea *pa, const std::string &score)
score only needed when running with gui
double getHCEmissions() const
Returns HC emission of the current state.
void onDepart()
Called when the vehicle is inserted into the network.
void removeReminder(MSMoveReminder *rem)
Removes a MoveReminder dynamically.
bool haveValidStopEdges() const
check whether all stop.edge MSRouteIterators are valid and in order
virtual double getAcceleration() const
Returns the vehicle's acceleration.
virtual bool addTraciStop(SUMOVehicleParameter::Stop stop, std::string &errorMsg)
int getRoutePosition() const
return index of edge within route
static const SUMOTime NOT_YET_DEPARTED
double getElecHybridCurrent() const
Returns actual current (A) of ElecHybrid device RICE_CHECK: Is this the current consumed from the ove...
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
const ConstMSEdgeVector getStopEdges(double &firstPos, double &lastPos) const
Returns the list of still pending stop edges also returns the first and last stop position.
SUMOTime myStopUntilOffset
The offset when adding route stops with 'until' on route replacement.
virtual bool isOnRoad() const
Returns the information whether the vehicle is on a road (is simulated)
void reroute(SUMOTime t, const std::string &info, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, const bool onInit=false, const bool withTaz=false, const bool silent=false)
Performs a rerouting using the given router.
const std::vector< MSTransportable * > & getContainers() const
retrieve riding containers
const MSRoute & getRoute() const
Returns the current route.
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.
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.
virtual void saveState(OutputDevice &out)
Saves the (common) state of a vehicle.
double myOdometer
A simple odometer to keep track of the length of the route already driven.
int getContainerNumber() const
Returns the number of containers.
bool replaceRouteEdges(ConstMSEdgeVector &edges, double cost, double savings, const std::string &info, bool onInit=false, bool check=false, bool removeStops=true, std::string *msgReturn=nullptr)
Replaces the current route by the given edges.
virtual std::string getParameter(const MSVehicle *veh, const std::string &key) const
try to get the given parameter for this carFollowingModel
Definition: MSCFModel.h:600
Battery device for electric vehicles.
double getActualBatteryCapacity() const
Get the actual vehicle's Battery Capacity in Wh.
const EnergyParams & getEnergyParams() const
retrieve parameters for the energy consumption model
A device which collects info on the vehicle trip (mainly on departure and arrival)
const EnergyParams & getEnergyParams() const
retrieve parameters for the energy consumption model
double getCurrentFromOverheadWire() const
Get actual current in the overhead wire segment.
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:48
bool allowsBoarding(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 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:61
static void buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into)
Build devices for the given vehicle, if needed.
Definition: MSDevice.cpp:101
A road/street connecting two junctions.
Definition: MSEdge.h:77
const MSEdge * getOppositeEdge() const
Returns the opposite direction edge if on exists else a nullptr.
Definition: MSEdge.cpp:1163
const std::vector< MSLane * > * allowedLanes(const MSEdge &destination, SUMOVehicleClass vclass=SVC_IGNORING) const
Get the allowed lanes to reach the destination-edge.
Definition: MSEdge.cpp:408
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:641
bool isTazConnector() const
Definition: MSEdge.h:285
int getNumLanes() const
Definition: MSEdge.h:172
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:262
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:885
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition: MSEdge.cpp:794
A storage for edge travel times and efforts.
static bool gUseMesoSim
Definition: MSGlobals.h:94
static bool gCheckRoutes
Definition: MSGlobals.h:82
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition: MSGlobals.h:100
static SUMOTime gTimeToImpatience
Definition: MSGlobals.h:69
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:82
SumoRNG * getRNG() const
return the associated RNG
Definition: MSLane.h:217
int getRNGIndex() const
returns the associated RNG index
Definition: MSLane.h:212
const MSEdge * getNextNormal() const
Returns the lane's follower if it is an internal lane, the edge of the lane otherwise.
Definition: MSLane.cpp:1967
double getLength() const
Returns the lane's length.
Definition: MSLane.h:541
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition: MSLane.h:814
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition: MSLane.cpp:1991
bool isInternal() const
Definition: MSLane.cpp:2122
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:674
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:1510
@ NEWROUTE
The vehicle got a new route.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:174
SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT(const int rngIndex, const MSEdgeVector &prohibited=MSEdgeVector()) const
Definition: MSNet.cpp:1352
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:376
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:318
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition: MSNet.h:429
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:1144
A lane area vehicles can halt at.
Definition: MSParkingArea.h:58
void addReference() const
increments the reference counter for the route
Definition: MSRoute.cpp:94
int size() const
Returns the number of edges to pass.
Definition: MSRoute.cpp:81
const std::vector< SUMOVehicleParameter::Stop > & getStops() const
Returns the stops.
Definition: MSRoute.cpp:389
MSRouteIterator end() const
Returns the end of the list of edges to pass.
Definition: MSRoute.cpp:75
static bool dictionary(const std::string &id, const MSRoute *route)
Adds a route to the dictionary.
Definition: MSRoute.cpp:113
void setCosts(double costs)
Sets the costs of the route.
Definition: MSRoute.h:185
static bool hasRoute(const std::string &id)
returns whether a route with the given id exists
Definition: MSRoute.cpp:156
void release() const
deletes the route if there are no further references to it
Definition: MSRoute.cpp:100
const MSEdge * getLastEdge() const
returns the destination edge
Definition: MSRoute.cpp:87
const RGBColor & getColor() const
Returns the color.
Definition: MSRoute.cpp:380
MSRouteIterator begin() const
Returns the begin of the list of edges to pass.
Definition: MSRoute.cpp:69
static void checkDist(const std::string &id)
Checks the distribution whether it is permanent and deletes it if not.
Definition: MSRoute.cpp:194
const ConstMSEdgeVector & getEdges() const
Definition: MSRoute.h:120
SUMOTime getPeriod() const
returns the period
Definition: MSRoute.h:156
void setSavings(double savings)
Sets the savings of the route.
Definition: MSRoute.h:192
static SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT(const int rngIndex, SUMOVehicleClass svc, const MSEdgeVector &prohibited=MSEdgeVector())
return the router instance
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 collision
Whether this stop was triggered by a collision.
Definition: MSStop.h:85
bool isOpposite
whether this an opposite-direction stop
Definition: MSStop.h:89
void initPars(const SUMOVehicleParameter::Stop &stopPar)
initialize attributes from the given stop parameters
Definition: MSStop.cpp:108
const MESegment * segment
The segment to stop at (mesosim only)
Definition: MSStop.h:52
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:34
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
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
bool isPerson() const
Whether it is a person.
void vehicleDeparted(const SUMOVehicle &v)
Informs this control about a vehicle's departure.
void removeVType(const MSVehicleType *vehType)
Abstract in-vehicle device.
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:75
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:5051
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition: MSVehicle.h:917
The car-following model and parameter.
Definition: MSVehicleType.h:62
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
double getMaxSpeed() const
Get vehicle's maximum speed [m/s].
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:90
double getLength() const
Get vehicle's length [m].
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:58
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.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:248
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.
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
static double compute(const SUMOEmissionClass c, const EmissionType e, const double v, const double a, const double slope, const EnergyParams *param=0)
Returns the amount of the emitted pollutant given the vehicle type and state (in mg/s or ml/s for fue...
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.h:119
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,...
double recomputeCosts(const std::vector< const E * > &edges, const V *const v, SUMOTime msTime, double *lengthp=nullptr) const
virtual bool compute(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent=false)=0
Builds the route between the given edges using the minimum effort at the given time The definition of...
virtual SUMOTime getWaitingTime() const =0
virtual double getSlope() const =0
Returns the slope of the road at object's position in degrees.
virtual double getSpeed() const =0
Returns the object's current speed.
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
long long int NumericalID
Definition: SUMOVehicle.h:62
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 (used only in NETEDIT)
std::string lane
The lane to stop at.
double startPos
The stopping position start.
int index
at which position in the stops list
SUMOTime until
The time at which the vehicle may continue its journey.
bool triggered
whether an arriving person lets the vehicle continue
double endPos
The stopping position end.
bool parking
whether the vehicle is removed from the net while stopping
bool containerTriggered
whether an arriving container lets the vehicle continue
SUMOTime arrival
The (expected) time at which the vehicle reaches the stop.
SUMOTime duration
The stopping duration.
Structure representing possible vehicle parameter.
int parametersSet
Information for the router which parameter were set, TraCI may modify this (when changing color)
ArrivalSpeedDefinition arrivalSpeedProcedure
Information how the vehicle's end speed shall be chosen.
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
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< 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.