Eclipse SUMO - Simulation of Urban MObility
ROVehicle.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 // Copyright (C) 2002-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 /****************************************************************************/
21 // A vehicle as used by router
22 /****************************************************************************/
23 #include <config.h>
24 
25 #include <string>
26 #include <iostream>
28 #include <utils/common/ToString.h>
34 #include "RORouteDef.h"
35 #include "RORoute.h"
36 #include "ROHelper.h"
37 #include "RONet.h"
38 #include "ROLane.h"
39 #include "ROVehicle.h"
40 
41 // ===========================================================================
42 // static members
43 // ===========================================================================
44 std::map<ConstROEdgeVector, std::string> ROVehicle::mySavedRoutes;
45 
46 // ===========================================================================
47 // method definitions
48 // ===========================================================================
50  RORouteDef* route, const SUMOVTypeParameter* type,
51  const RONet* net, MsgHandler* errorHandler):
52  RORoutable(pars, type),
53  myRoute(route),
54  myJumpTime(-1) {
55  getParameter().stops.clear();
56  if (route != nullptr && route->getFirstRoute() != nullptr) {
57  for (std::vector<SUMOVehicleParameter::Stop>::const_iterator s = route->getFirstRoute()->getStops().begin(); s != route->getFirstRoute()->getStops().end(); ++s) {
58  addStop(*s, net, errorHandler);
59  }
60  }
61  for (std::vector<SUMOVehicleParameter::Stop>::const_iterator s = pars.stops.begin(); s != pars.stops.end(); ++s) {
62  addStop(*s, net, errorHandler);
63  }
64  if (pars.via.size() != 0) {
65  // via takes precedence over stop edges
66  // XXX check for inconsistencies #2275
67  myStopEdges.clear();
68  for (std::vector<std::string>::const_iterator it = pars.via.begin(); it != pars.via.end(); ++it) {
69  assert(net->getEdge(*it) != 0);
70  myStopEdges.push_back(net->getEdge(*it));
71  }
72  }
73 }
74 
75 
76 void
77 ROVehicle::addStop(const SUMOVehicleParameter::Stop& stopPar, const RONet* net, MsgHandler* errorHandler) {
78  const ROEdge* stopEdge = net->getEdge(stopPar.edge);
79  assert(stopEdge != 0); // was checked when parsing the stop
80  if (stopEdge->prohibits(this)) {
81  if (errorHandler != nullptr) {
82  errorHandler->inform("Stop edge '" + stopEdge->getID() + "' does not allow vehicle '" + getID() + "'.");
83  }
84  return;
85  }
86  // where to insert the stop
87  std::vector<SUMOVehicleParameter::Stop>::iterator iter = getParameter().stops.begin();
88  ConstROEdgeVector::iterator edgeIter = myStopEdges.begin();
89  if (stopPar.index == STOP_INDEX_END || stopPar.index >= static_cast<int>(getParameter().stops.size())) {
90  if (getParameter().stops.size() > 0) {
91  iter = getParameter().stops.end();
92  edgeIter = myStopEdges.end();
93  }
94  } else {
95  if (stopPar.index == STOP_INDEX_FIT) {
97  ConstROEdgeVector::const_iterator stopEdgeIt = std::find(edges.begin(), edges.end(), stopEdge);
98  if (stopEdgeIt == edges.end()) {
99  iter = getParameter().stops.end();
100  edgeIter = myStopEdges.end();
101  } else {
102  while (iter != getParameter().stops.end()) {
103  if (edgeIter > stopEdgeIt || (edgeIter == stopEdgeIt && iter->endPos >= stopPar.endPos)) {
104  break;
105  }
106  ++iter;
107  ++edgeIter;
108  }
109  }
110  } else {
111  iter += stopPar.index;
112  edgeIter += stopPar.index;
113  }
114  }
115  getParameter().stops.insert(iter, stopPar);
116  myStopEdges.insert(edgeIter, stopEdge);
117  if (stopPar.jump >= 0) {
118  if (stopEdge->isInternal()) {
119  if (errorHandler != nullptr) {
120  errorHandler->inform("Jumps are not supported from internal stop edge '" + stopEdge->getID() + "'.");
121  }
122  } else {
123  if (myJumpTime < 0) {
124  myJumpTime = 0;
125  }
126  myJumpTime += stopPar.jump;
127  }
128  }
129 }
130 
131 
133 
134 
135 const ROEdge*
137  return myRoute->getFirstRoute()->getFirst();
138 }
139 
140 
141 void
143  const bool removeLoops, MsgHandler* errorHandler) {
145  std::string noRouteMsg = "The vehicle '" + getID() + "' has no valid route.";
146  RORouteDef* const routeDef = getRouteDefinition();
147  // check if the route definition is valid
148  if (routeDef == nullptr) {
149  errorHandler->inform(noRouteMsg);
150  myRoutingSuccess = false;
151  return;
152  }
153  RORoute* current = routeDef->buildCurrentRoute(router, getDepartureTime(), *this);
154  if (current == nullptr || current->size() == 0) {
155  delete current;
156  if (current == nullptr || !routeDef->discardSilent()) {
157  errorHandler->inform(noRouteMsg);
158  }
159  myRoutingSuccess = false;
160  return;
161  }
162  // check whether we have to evaluate the route for not containing loops
163  if (removeLoops) {
168  current->recheckForLoops(getMandatoryEdges(requiredStart, requiredEnd));
169  // check whether the route is still valid
170  if (current->size() == 0) {
171  delete current;
172  errorHandler->inform(noRouteMsg + " (after removing loops)");
173  myRoutingSuccess = false;
174  return;
175  }
176  }
177  // add built route
178  routeDef->addAlternative(router, this, current, getDepartureTime());
179  myRoutingSuccess = true;
180 }
181 
182 
184 ROVehicle::getMandatoryEdges(const ROEdge* requiredStart, const ROEdge* requiredEnd) const {
185  ConstROEdgeVector mandatory;
186  if (requiredStart) {
187  mandatory.push_back(requiredStart);
188  }
189  for (const ROEdge* e : getStopEdges()) {
190  if (e->isInternal()) {
191  // the edges before and after the internal edge are mandatory
192  const ROEdge* before = e->getNormalBefore();
193  const ROEdge* after = e->getNormalAfter();
194  if (mandatory.size() == 0 || after != mandatory.back()) {
195  mandatory.push_back(before);
196  mandatory.push_back(after);
197  }
198  } else {
199  if (mandatory.size() == 0 || e != mandatory.back()) {
200  mandatory.push_back(e);
201  }
202  }
203  }
204  if (requiredEnd) {
205  if (mandatory.size() < 2 || mandatory.back() != requiredEnd) {
206  mandatory.push_back(requiredEnd);
207  }
208  }
209  return mandatory;
210 }
211 
212 
213 void
214 ROVehicle::collectJumps(const ConstROEdgeVector& mandatory, std::set<ConstROEdgeVector::const_iterator>& jumpStarts) const {
215  auto itM = mandatory.begin();
216  auto itS = getParameter().stops.begin();
217  auto itSEnd = getParameter().stops.end();
218  while (itM != mandatory.end() && itS != itSEnd) {
219  bool repeatMandatory = false;
220  // if we stop twice on the same edge, we must treat this as a repeated
221  // mandatory edge (even though the edge appears only once in the mandatory vector)
222  if ((*itM)->getID() == itS->edge) {
223  if (itS->jump >= 0) {
224  jumpStarts.insert(itM);
225  }
226  itS++;
227  if (itS != itSEnd && itS->edge == (itS - 1)->edge) {
228  repeatMandatory = true;
229  }
230  }
231  if (!repeatMandatory) {
232  itM++;
233  }
234  }
235 }
236 
237 
238 void
239 ROVehicle::saveAsXML(OutputDevice& os, OutputDevice* const typeos, bool asAlternatives, OptionsCont& options) const {
240  if (typeos != nullptr && getType() != nullptr && !getType()->saved) {
241  getType()->write(*typeos);
242  getType()->saved = true;
243  }
244  if (getType() != nullptr && !getType()->saved) {
245  getType()->write(os);
246  getType()->saved = asAlternatives;
247  }
248 
249  const bool writeTrip = options.exists("write-trips") && options.getBool("write-trips");
250  const bool writeGeoTrip = writeTrip && options.getBool("write-trips.geo");
251  const bool writeJunctions = writeTrip && options.getBool("write-trips.junctions");
252  const bool writeNamedRoute = !asAlternatives && options.getBool("named-routes");
253  const bool writeCosts = options.exists("write-costs") && options.getBool("write-costs");
254  const bool writeExit = options.exists("exit-times") && options.getBool("exit-times");
255  const bool writeLength = options.exists("route-length") && options.getBool("route-length");
256 
257  std::string routeID;
258  if (writeNamedRoute) {
260  auto it = mySavedRoutes.find(edges);
261  if (it == mySavedRoutes.end()) {
262  routeID = "r" + toString(mySavedRoutes.size());
263  myRoute->getUsedRoute()->writeXMLDefinition(os, this, writeCosts, false, writeExit,
264  writeLength, routeID);
265  mySavedRoutes[edges] = routeID;
266  } else {
267  routeID = it->second;
268  }
269  }
270  // write the vehicle (new style, with included routes)
271  getParameter().write(os, options, writeTrip ? SUMO_TAG_TRIP : SUMO_TAG_VEHICLE);
272 
273  // save the route
274  if (writeTrip) {
276  const ROEdge* from = nullptr;
277  const ROEdge* to = nullptr;
278  if (edges.size() > 0) {
279  if (edges.front()->isTazConnector()) {
280  if (edges.size() > 1) {
281  from = edges[1];
282  if (from->isTazConnector() && writeJunctions && edges.front()->getSuccessors().size() > 0) {
283  // routing was skipped
284  from = edges.front()->getSuccessors(getVClass()).front();
285  }
286  }
287  } else {
288  from = edges[0];
289  }
290  if (edges.back()->isTazConnector()) {
291  if (edges.size() > 1) {
292  to = edges[edges.size() - 2];
293  if (to->isTazConnector() && writeJunctions && edges.back()->getPredecessors().size() > 0) {
294  // routing was skipped
295  to = edges.back()->getPredecessors().front();
296  }
297  }
298  } else {
299  to = edges[edges.size() - 1];
300  }
301  }
302  if (from != nullptr) {
303  if (writeGeoTrip) {
304  Position fromPos = from->getLanes()[0]->getShape().positionAtOffset2D(0);
305  if (GeoConvHelper::getFinal().usingGeoProjection()) {
308  os.writeAttr(SUMO_ATTR_FROMLONLAT, fromPos);
310  } else {
311  os.writeAttr(SUMO_ATTR_FROMXY, fromPos);
312  }
313  } else if (writeJunctions) {
315  } else {
316  os.writeAttr(SUMO_ATTR_FROM, from->getID());
317  }
318  }
319  if (to != nullptr) {
320  if (writeGeoTrip) {
321  Position toPos = to->getLanes()[0]->getShape().positionAtOffset2D(to->getLanes()[0]->getShape().length2D());
322  if (GeoConvHelper::getFinal().usingGeoProjection()) {
325  os.writeAttr(SUMO_ATTR_TOLONLAT, toPos);
327  } else {
328  os.writeAttr(SUMO_ATTR_TOXY, toPos);
329  }
330  } else if (writeJunctions) {
332  } else {
333  os.writeAttr(SUMO_ATTR_TO, to->getID());
334  }
335  }
336  if (getParameter().via.size() > 0) {
337  std::vector<std::string> viaOut;
338  SumoXMLAttr viaAttr = (writeGeoTrip
340  : (writeJunctions ? SUMO_ATTR_VIAJUNCTIONS : SUMO_ATTR_VIA));
341  for (const std::string& viaID : getParameter().via) {
342  const ROEdge* viaEdge = RONet::getInstance()->getEdge(viaID);
343  if (viaEdge->isTazConnector()) {
344  if (viaEdge->getPredecessors().size() == 0) {
345  continue;
346  }
347  // XXX used edge that was used in route
348  viaEdge = viaEdge->getPredecessors().front();
349  }
350  assert(viaEdge != nullptr);
351  if (writeGeoTrip) {
352  Position viaPos = viaEdge->getLanes()[0]->getShape().positionAtOffset2D(viaEdge->getLanes()[0]->getShape().length2D() / 2);
353  if (GeoConvHelper::getFinal().usingGeoProjection()) {
355  viaOut.push_back(toString(viaPos, gPrecisionGeo));
356  } else {
357  viaOut.push_back(toString(viaPos, gPrecision));
358  }
359  } else if (writeJunctions) {
360  viaOut.push_back(viaEdge->getToJunction()->getID());
361  } else {
362  viaOut.push_back(viaEdge->getID());
363  }
364  }
365  os.writeAttr(viaAttr, viaOut);
366  }
367  } else if (writeNamedRoute) {
368  os.writeAttr(SUMO_ATTR_ROUTE, routeID);
369  } else {
370  myRoute->writeXMLDefinition(os, this, asAlternatives, writeExit, writeCosts, writeLength);
371  }
372  for (std::vector<SUMOVehicleParameter::Stop>::const_iterator stop = getParameter().stops.begin(); stop != getParameter().stops.end(); ++stop) {
373  stop->write(os);
374  }
376  os.closeTag();
377 }
378 
379 
380 /****************************************************************************/
std::vector< const ROEdge * > ConstROEdgeVector
Definition: ROEdge.h:54
const int STOP_INDEX_END
@ GIVEN
The lane is given.
@ GIVEN
The position is given.
@ GIVEN
The arrival lane is given.
const int STOP_INDEX_FIT
@ GIVEN
The arrival position is given.
@ SUMO_TAG_VEHICLE
description of a vehicle
@ SUMO_TAG_TRIP
a single trip definition (used by router)
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
@ SUMO_ATTR_FROM_JUNCTION
@ SUMO_ATTR_VIALONLAT
@ SUMO_ATTR_VIA
@ SUMO_ATTR_VIAXY
@ SUMO_ATTR_TO_JUNCTION
@ SUMO_ATTR_TOLONLAT
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_VIAJUNCTIONS
@ SUMO_ATTR_FROMXY
@ SUMO_ATTR_TOXY
@ SUMO_ATTR_ROUTE
@ SUMO_ATTR_FROMLONLAT
int gPrecision
the precision for floating point outputs
Definition: StdDefs.cpp:26
int gPrecisionGeo
Definition: StdDefs.cpp:27
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
void cartesian2geo(Position &cartesian) const
Converts the given cartesian (shifted) position to its geo (lat/long) representation.
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
bool usingGeoProjection() const
Returns whether a transformation from geo to metric coordinates will be performed.
virtual void inform(std::string msg, bool addType=true)
adds a new error to the list
Definition: MsgHandler.cpp:154
const std::string & getID() const
Returns the id.
Definition: Named.h:74
A storage for options typed value containers)
Definition: OptionsCont.h:89
bool exists(const std::string &name) const
Returns the information whether the named option is known.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
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.
void writeParams(OutputDevice &device) const
write Params in the given outputdevice
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
A basic edge for routing applications.
Definition: ROEdge.h:70
const ROEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition: ROEdge.cpp:269
const ROEdge * getNormalAfter() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
Definition: ROEdge.cpp:281
bool isTazConnector() const
Definition: ROEdge.h:168
bool prohibits(const ROVehicle *const vehicle) const
Returns whether this edge prohibits the given vehicle to pass it.
Definition: ROEdge.h:278
bool isInternal() const
return whether this edge is an internal edge
Definition: ROEdge.h:154
const RONode * getFromJunction() const
Definition: ROEdge.h:512
const std::vector< ROLane * > & getLanes() const
Returns this edge's lanes.
Definition: ROEdge.h:524
const ROEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition: ROEdge.cpp:366
const ROEdgeVector & getPredecessors() const
Returns the edge at the given position from the list of incoming edges.
Definition: ROEdge.h:370
const RONode * getToJunction() const
Definition: ROEdge.h:516
The router's network representation.
Definition: RONet.h:62
static RONet * getInstance()
Returns the pointer to the unique instance of RONet (singleton).
Definition: RONet.cpp:56
ROEdge * getEdge(const std::string &name) const
Retrieves an edge from the network.
Definition: RONet.h:157
A routable thing such as a vehicle or person.
Definition: RORoutable.h:52
const SUMOVehicleParameter & getParameter() const
Returns the definition of the vehicle / person parameter.
Definition: RORoutable.h:71
const std::string & getID() const
Returns the id of the routable.
Definition: RORoutable.h:91
SUMOVehicleClass getVClass() const
Definition: RORoutable.h:109
const SUMOVTypeParameter * getType() const
Returns the type of the routable.
Definition: RORoutable.h:82
bool myRoutingSuccess
Whether the last routing was successful.
Definition: RORoutable.h:191
Base class for a vehicle's route definition.
Definition: RORouteDef.h:53
OutputDevice & writeXMLDefinition(OutputDevice &dev, const ROVehicle *const veh, bool asAlternatives, bool withExitTimes, bool withCost, bool withLength) const
Saves the built route / route alternatives.
Definition: RORouteDef.cpp:402
RORoute * buildCurrentRoute(SUMOAbstractRouter< ROEdge, ROVehicle > &router, SUMOTime begin, const ROVehicle &veh) const
Triggers building of the complete route (via preComputeCurrentRoute) or returns precomputed route.
Definition: RORouteDef.cpp:84
const RORoute * getFirstRoute() const
Definition: RORouteDef.h:98
void addAlternative(SUMOAbstractRouter< ROEdge, ROVehicle > &router, const ROVehicle *const, RORoute *current, SUMOTime begin)
Adds an alternative to the list of routes.
Definition: RORouteDef.cpp:287
const RORoute * getUsedRoute() const
Definition: RORouteDef.h:105
bool discardSilent() const
whether this route shall be silently discarded
Definition: RORouteDef.h:137
A complete router's route.
Definition: RORoute.h:52
const ROEdge * getFirst() const
Returns the first edge in the route.
Definition: RORoute.h:91
const std::vector< SUMOVehicleParameter::Stop > & getStops() const
Returns the list of stops this route contains.
Definition: RORoute.h:187
int size() const
Returns the number of edges in this route.
Definition: RORoute.h:143
ConstROEdgeVector getNormalEdges() const
return edges that shall be written in the route definition
Definition: RORoute.cpp:102
void recheckForLoops(const ConstROEdgeVector &mandatory)
Checks whether this route contains loops and removes such.
Definition: RORoute.cpp:76
const ConstROEdgeVector & getEdgeVector() const
Returns the list of edges this route consists of.
Definition: RORoute.h:152
OutputDevice & writeXMLDefinition(OutputDevice &dev, const ROVehicle *const veh, const bool withCosts, const bool withProb, const bool withExitTimes, const bool withLength, const std::string &id="") const
Definition: RORoute.cpp:114
void collectJumps(const ConstROEdgeVector &mandatory, std::set< ConstROEdgeVector::const_iterator > &jumpStarts) const
collect mandatory-edge iterators that define jumps in the route
Definition: ROVehicle.cpp:214
const ConstROEdgeVector & getStopEdges() const
Definition: ROVehicle.h:97
static std::map< ConstROEdgeVector, std::string > mySavedRoutes
map of all routes that were already saved with a name
Definition: ROVehicle.h:169
const ROEdge * getDepartEdge() const
Returns the first edge the vehicle takes.
Definition: ROVehicle.cpp:136
RORouteDef * getRouteDefinition() const
Returns the definition of the route the vehicle takes.
Definition: ROVehicle.h:73
SUMOTime getDepartureTime() const
Returns the time the vehicle starts at, 0 for triggered vehicles.
Definition: ROVehicle.h:92
ConstROEdgeVector getMandatoryEdges(const ROEdge *requiredStart, const ROEdge *requiredEnd) const
compute mandatory edges
Definition: ROVehicle.cpp:184
void saveAsXML(OutputDevice &os, OutputDevice *const typeos, bool asAlternatives, OptionsCont &options) const
Saves the complete vehicle description.
Definition: ROVehicle.cpp:239
ConstROEdgeVector myStopEdges
The edges where the vehicle stops.
Definition: ROVehicle.h:163
ROVehicle(const SUMOVehicleParameter &pars, RORouteDef *route, const SUMOVTypeParameter *type, const RONet *net, MsgHandler *errorHandler=0)
Constructor.
Definition: ROVehicle.cpp:49
virtual ~ROVehicle()
Destructor.
Definition: ROVehicle.cpp:132
SUMOTime myJumpTime
Whether this vehicle has any jumps defined.
Definition: ROVehicle.h:166
void addStop(const SUMOVehicleParameter::Stop &stopPar, const RONet *net, MsgHandler *errorHandler)
Adds a stop to this vehicle.
Definition: ROVehicle.cpp:77
void computeRoute(const RORouterProvider &provider, const bool removeLoops, MsgHandler *errorHandler)
Definition: ROVehicle.cpp:142
RORouteDef *const myRoute
The route the vehicle takes.
Definition: ROVehicle.h:160
SUMOAbstractRouter< E, V > & getVehicleRouter(SUMOVehicleClass svc) const
Structure representing possible vehicle parameter.
void write(OutputDevice &dev) const
Writes the vtype.
bool saved
Information whether this type was already saved (needed by routers)
Definition of vehicle stop (position and duration)
std::string edge
The edge to stop at.
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
double endPos
The stopping position end.
Structure representing possible vehicle parameter.
std::vector< std::string > via
List of the via-edges the vehicle must visit.
ArrivalLaneDefinition arrivalLaneProcedure
Information how the vehicle shall choose the lane to arrive on.
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.
DepartLaneDefinition departLaneProcedure
Information how the vehicle shall choose the lane to depart from.
std::vector< Stop > stops
List of the stops the vehicle will make, TraCI may add entries here.
ArrivalPosDefinition arrivalPosProcedure
Information how the vehicle shall choose the arrival position.
DepartPosDefinition departPosProcedure
Information how the vehicle shall choose the departure position.