Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
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-2025 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>
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// ===========================================================================
44std::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 (StopParVector::const_iterator s = route->getFirstRoute()->getStops().begin(); s != route->getFirstRoute()->getStops().end(); ++s) {
58 addStop(*s, net, errorHandler);
59 }
60 }
61 for (StopParVector::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
76void
77ROVehicle::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 StopParVector::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
135const ROEdge*
139
140
141void
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 routeDef->validateAlternatives(this, errorHandler);
154 if (routeDef->getFirstRoute() == nullptr) {
155 // everything is invalid and no new routes will be computed
156 myRoutingSuccess = false;
157 return;
158 }
159 RORoute* current = routeDef->buildCurrentRoute(router, getDepartureTime(), *this);
160 if (current == nullptr || current->size() == 0) {
161 delete current;
162 if (current == nullptr || !routeDef->discardSilent()) {
163 errorHandler->inform(noRouteMsg);
164 }
165 myRoutingSuccess = false;
166 return;
167 }
168 // check whether we have to evaluate the route for not containing loops
169 if (removeLoops) {
174 current->recheckForLoops(getMandatoryEdges(requiredStart, requiredEnd));
175 // check whether the route is still valid
176 if (current->size() == 0) {
177 delete current;
178 errorHandler->inform(noRouteMsg + " (after removing loops)");
179 myRoutingSuccess = false;
180 return;
181 }
182 }
183 // add built route
184 routeDef->addAlternative(router, this, current, getDepartureTime(), errorHandler);
185 myRoutingSuccess = true;
186}
187
188
190ROVehicle::getMandatoryEdges(const ROEdge* requiredStart, const ROEdge* requiredEnd) const {
191 ConstROEdgeVector mandatory;
192 if (requiredStart) {
193 mandatory.push_back(requiredStart);
194 }
195 for (const ROEdge* e : getStopEdges()) {
196 if (e->isInternal()) {
197 // the edges before and after the internal edge are mandatory
198 const ROEdge* before = e->getNormalBefore();
199 const ROEdge* after = e->getNormalAfter();
200 if (mandatory.size() == 0 || after != mandatory.back()) {
201 mandatory.push_back(before);
202 mandatory.push_back(after);
203 }
204 } else {
205 if (mandatory.size() == 0 || e != mandatory.back()) {
206 mandatory.push_back(e);
207 }
208 }
209 }
210 if (requiredEnd) {
211 if (mandatory.size() < 2 || mandatory.back() != requiredEnd) {
212 mandatory.push_back(requiredEnd);
213 }
214 }
215 return mandatory;
216}
217
218
219void
220ROVehicle::collectJumps(const ConstROEdgeVector& mandatory, std::set<ConstROEdgeVector::const_iterator>& jumpStarts) const {
221 auto itM = mandatory.begin();
222 auto itS = getParameter().stops.begin();
223 auto itSEnd = getParameter().stops.end();
224 while (itM != mandatory.end() && itS != itSEnd) {
225 bool repeatMandatory = false;
226 // if we stop twice on the same edge, we must treat this as a repeated
227 // mandatory edge (even though the edge appears only once in the mandatory vector)
228 if ((*itM)->getID() == itS->edge) {
229 if (itS->jump >= 0) {
230 jumpStarts.insert(itM);
231 }
232 itS++;
233 if (itS != itSEnd && itS->edge == (itS - 1)->edge) {
234 repeatMandatory = true;
235 }
236 }
237 if (!repeatMandatory) {
238 itM++;
239 }
240 }
241}
242
243
244void
245ROVehicle::saveAsXML(OutputDevice& os, OutputDevice* const typeos, bool asAlternatives, OptionsCont& options, int cloneIndex) const {
246 if (typeos != nullptr && getType() != nullptr && !getType()->saved) {
247 getType()->write(*typeos);
248 getType()->saved = true;
249 }
250 if (getType() != nullptr && !getType()->saved) {
251 getType()->write(os);
252 getType()->saved = asAlternatives;
253 }
254
255 const bool writeTrip = options.exists("write-trips") && options.getBool("write-trips");
256 const bool writeGeoTrip = writeTrip && options.getBool("write-trips.geo");
257 const bool writeJunctions = writeTrip && options.getBool("write-trips.junctions");
258 const bool writeNamedRoute = !asAlternatives && options.getBool("named-routes");
259 const bool writeCosts = options.exists("write-costs") && options.getBool("write-costs");
260 const bool writeExit = options.exists("exit-times") && options.getBool("exit-times");
261 const bool writeLength = options.exists("route-length") && options.getBool("route-length");
262 const bool writeFlow = options.exists("keep-flows") && options.getBool("keep-flows") && isPartOfFlow();
263
264 std::string routeID;
265 if (writeNamedRoute) {
267 auto it = mySavedRoutes.find(edges);
268 if (it == mySavedRoutes.end()) {
269 routeID = "r" + toString(mySavedRoutes.size());
270 myRoute->getUsedRoute()->writeXMLDefinition(os, this, writeCosts, false, writeExit,
271 writeLength, routeID);
272 mySavedRoutes[edges] = routeID;
273 } else {
274 routeID = it->second;
275 }
276 }
277 const SumoXMLTag tag = writeFlow ? SUMO_TAG_FLOW : (writeTrip ? SUMO_TAG_TRIP : SUMO_TAG_VEHICLE);
278 // write the vehicle (new style, with included routes)
279 if (cloneIndex == 0) {
280 getParameter().write(os, options, tag);
281 } else {
283 // @note id collisions may occur if scale-suffic occurs in other vehicle ids
284 p.id += options.getString("scale-suffix") + toString(cloneIndex);
285 p.write(os, options, tag);
286 }
287 // save the route
288 if (writeTrip) {
290 const ROEdge* from = nullptr;
291 const ROEdge* to = nullptr;
292 if (edges.size() > 0) {
293 if (edges.front()->isTazConnector()) {
294 if (edges.size() > 1) {
295 from = edges[1];
296 if (from->isTazConnector() && writeJunctions && edges.front()->getSuccessors().size() > 0) {
297 // routing was skipped
298 from = edges.front()->getSuccessors(getVClass()).front();
299 }
300 }
301 } else {
302 from = edges[0];
303 }
304 if (edges.back()->isTazConnector()) {
305 if (edges.size() > 1) {
306 to = edges[edges.size() - 2];
307 if (to->isTazConnector() && writeJunctions && edges.back()->getPredecessors().size() > 0) {
308 // routing was skipped
309 to = edges.back()->getPredecessors().front();
310 }
311 }
312 } else {
313 to = edges[edges.size() - 1];
314 }
315 }
316 if (from != nullptr) {
317 if (writeGeoTrip) {
318 Position fromPos = from->getLanes()[0]->getShape().positionAtOffset2D(0);
319 if (GeoConvHelper::getFinal().usingGeoProjection()) {
322 os.writeAttr(SUMO_ATTR_FROMLONLAT, fromPos);
324 } else {
325 os.writeAttr(SUMO_ATTR_FROMXY, fromPos);
326 }
327 } else if (writeJunctions) {
329 } else {
330 os.writeAttr(SUMO_ATTR_FROM, from->getID());
331 }
332 }
333 if (to != nullptr) {
334 if (writeGeoTrip) {
335 Position toPos = to->getLanes()[0]->getShape().positionAtOffset2D(to->getLanes()[0]->getShape().length2D());
336 if (GeoConvHelper::getFinal().usingGeoProjection()) {
339 os.writeAttr(SUMO_ATTR_TOLONLAT, toPos);
341 } else {
342 os.writeAttr(SUMO_ATTR_TOXY, toPos);
343 }
344 } else if (writeJunctions) {
346 } else {
347 os.writeAttr(SUMO_ATTR_TO, to->getID());
348 }
349 }
350 if (getParameter().via.size() > 0) {
351 std::vector<std::string> viaOut;
352 SumoXMLAttr viaAttr = (writeGeoTrip
354 : (writeJunctions ? SUMO_ATTR_VIAJUNCTIONS : SUMO_ATTR_VIA));
355 for (const std::string& viaID : getParameter().via) {
356 const ROEdge* viaEdge = RONet::getInstance()->getEdge(viaID);
357 if (viaEdge->isTazConnector()) {
358 if (viaEdge->getPredecessors().size() == 0) {
359 continue;
360 }
361 // XXX used edge that was used in route
362 viaEdge = viaEdge->getPredecessors().front();
363 }
364 assert(viaEdge != nullptr);
365 if (writeGeoTrip) {
366 Position viaPos = viaEdge->getLanes()[0]->getShape().positionAtOffset2D(viaEdge->getLanes()[0]->getShape().length2D() / 2);
367 if (GeoConvHelper::getFinal().usingGeoProjection()) {
369 viaOut.push_back(toString(viaPos, gPrecisionGeo));
370 } else {
371 viaOut.push_back(toString(viaPos, gPrecision));
372 }
373 } else if (writeJunctions) {
374 viaOut.push_back(viaEdge->getToJunction()->getID());
375 } else {
376 viaOut.push_back(viaEdge->getID());
377 }
378 }
379 os.writeAttr(viaAttr, viaOut);
380 }
381 } else if (writeNamedRoute) {
382 os.writeAttr(SUMO_ATTR_ROUTE, routeID);
383 } else {
384 myRoute->writeXMLDefinition(os, this, asAlternatives, writeExit, writeCosts, writeLength);
385 }
386 for (StopParVector::const_iterator stop = getParameter().stops.begin(); stop != getParameter().stops.end(); ++stop) {
387 stop->write(os);
388 }
390 os.closeTag();
391}
392
393
394/****************************************************************************/
std::vector< const ROEdge * > ConstROEdgeVector
Definition ROEdge.h:57
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.
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ SUMO_TAG_VEHICLE
description of a vehicle
@ SUMO_TAG_FLOW
a flow definition using from and to edges or a route
@ 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:27
int gPrecisionGeo
Definition StdDefs.cpp:29
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
void cartesian2geo(Position &cartesian) const
Converts the given cartesian (shifted) position to its geo (lat/long) representation.
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
const std::string & getID() const
Returns the id.
Definition Named.h:74
A storage for options typed value containers)
Definition OptionsCont.h:89
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
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.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
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:73
const ROEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition ROEdge.cpp:293
const ROEdge * getNormalAfter() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
Definition ROEdge.cpp:305
const RONode * getToJunction() const
Definition ROEdge.h:543
bool isTazConnector() const
Definition ROEdge.h:174
bool prohibits(const ROVehicle *const vehicle) const
Returns whether this edge prohibits the given vehicle to pass it.
Definition ROEdge.h:284
const RONode * getFromJunction() const
Definition ROEdge.h:539
bool isInternal() const
return whether this edge is an internal edge
Definition ROEdge.h:160
const ROEdgeVector & getPredecessors() const
Returns the edge at the given position from the list of incoming edges.
Definition ROEdge.h:376
const ROEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition ROEdge.cpp:390
const std::vector< ROLane * > & getLanes() const
Returns this edge's lanes.
Definition ROEdge.h:551
The router's network representation.
Definition RONet.h:63
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:169
A routable thing such as a vehicle or person.
Definition RORoutable.h:53
SUMOVehicleClass getVClass() const
Definition RORoutable.h:117
bool isPartOfFlow() const
Definition RORoutable.h:141
bool myRoutingSuccess
Whether the last routing was successful.
Definition RORoutable.h:204
const SUMOVTypeParameter * getType() const
Returns the type of the routable.
Definition RORoutable.h:86
const std::string & getID() const
Returns the id of the routable.
Definition RORoutable.h:95
const SUMOVehicleParameter & getParameter() const
Returns the definition of the vehicle / person parameter.
Definition RORoutable.h:75
Base class for a vehicle's route definition.
Definition RORouteDef.h:53
const RORoute * getFirstRoute() const
Definition RORouteDef.h:104
OutputDevice & writeXMLDefinition(OutputDevice &dev, const ROVehicle *const veh, bool asAlternatives, bool withExitTimes, bool withCost, bool withLength) const
Saves the built route / route alternatives.
RORoute * buildCurrentRoute(SUMOAbstractRouter< ROEdge, ROVehicle > &router, SUMOTime begin, const ROVehicle &veh) const
Triggers building of the complete route (via preComputeCurrentRoute) or returns precomputed route.
const RORoute * getUsedRoute() const
Definition RORouteDef.h:111
void addAlternative(SUMOAbstractRouter< ROEdge, ROVehicle > &router, const ROVehicle *const, RORoute *current, SUMOTime begin, MsgHandler *errorHandler)
Adds an alternative to the list of routes.
void validateAlternatives(const ROVehicle *veh, MsgHandler *errorHandler)
removes invalid alternatives and raise an error or warning
bool discardSilent() const
whether this route shall be silently discarded
Definition RORouteDef.h:143
A complete router's route.
Definition RORoute.h:52
OutputDevice & writeXMLDefinition(OutputDevice &dev, const ROVehicle *const veh, const bool withCosts, const bool asAlternatives, const bool withExitTimes, const bool withLength, const std::string &id="") const
Definition RORoute.cpp:132
const StopParVector & getStops() const
Returns the list of stops this route contains.
Definition RORoute.h:190
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:120
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
const ROEdge * getFirst() const
Returns the first edge in the route.
Definition RORoute.h:91
void collectJumps(const ConstROEdgeVector &mandatory, std::set< ConstROEdgeVector::const_iterator > &jumpStarts) const
collect mandatory-edge iterators that define jumps in the route
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.
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
RORouteDef * getRouteDefinition() const
Returns the definition of the route the vehicle takes.
Definition ROVehicle.h:73
void saveAsXML(OutputDevice &os, OutputDevice *const typeos, bool asAlternatives, OptionsCont &options, int cloneIndex=0) const
Saves the complete vehicle description.
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
const ConstROEdgeVector & getStopEdges() const
Definition ROVehicle.h:97
virtual ~ROVehicle()
Destructor.
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)
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::string id
The vehicle's id.
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.