Eclipse SUMO - Simulation of Urban MObility
MSRoute.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 route
22 /****************************************************************************/
23 #include <config.h>
24 
25 #include <cassert>
26 #include <algorithm>
27 #include <limits>
29 #include <utils/common/RGBColor.h>
31 #include "MSEdge.h"
32 #include "MSLane.h"
33 #include "MSRoute.h"
34 
35 
36 // ===========================================================================
37 // static member variables
38 // ===========================================================================
41 #ifdef HAVE_FOX
42 FXMutex MSRoute::myDictMutex(true);
43 #endif
44 
45 
46 // ===========================================================================
47 // member method definitions
48 // ===========================================================================
49 MSRoute::MSRoute(const std::string& id,
50  const ConstMSEdgeVector& edges,
51  const bool isPermanent, const RGBColor* const c,
52  const std::vector<SUMOVehicleParameter::Stop>& stops,
53  SUMOTime replacedTime,
54  int replacedIndex) :
55  Named(id), myEdges(edges), myAmPermanent(isPermanent),
56  myColor(c),
57  myPeriod(0),
58  myCosts(-1),
59  mySavings(0),
60  myReroute(false),
61  myStops(stops),
62  myReplacedTime(replacedTime),
63  myReplacedIndex(replacedIndex)
64 {}
65 
66 
68  delete myColor;
69 }
70 
71 
73 MSRoute::begin() const {
74  return myEdges.begin();
75 }
76 
77 
79 MSRoute::end() const {
80  return myEdges.end();
81 }
82 
83 
84 int
85 MSRoute::size() const {
86  return (int)myEdges.size();
87 }
88 
89 
90 const MSEdge*
92  assert(myEdges.size() > 0);
93  return myEdges.back();
94 }
95 
96 
97 void
99 #ifdef HAVE_FOX
100  FXMutexLock f(myDictMutex);
101 #endif
102  if (!myAmPermanent) {
103  myDict.erase(getID());
104  }
105 }
106 
107 
108 bool
109 MSRoute::dictionary(const std::string& id, ConstMSRoutePtr route) {
110 #ifdef HAVE_FOX
111  FXMutexLock f(myDictMutex);
112 #endif
113  if (myDict.find(id) == myDict.end() && myDistDict.find(id) == myDistDict.end()) {
114  myDict[id] = route;
115  return true;
116  }
117  return false;
118 }
119 
120 
121 bool
122 MSRoute::dictionary(const std::string& id, RandomDistributor<ConstMSRoutePtr>* const routeDist, const bool permanent) {
123 #ifdef HAVE_FOX
124  FXMutexLock f(myDictMutex);
125 #endif
126  if (myDict.find(id) == myDict.end() && myDistDict.find(id) == myDistDict.end()) {
127  myDistDict[id] = std::make_pair(routeDist, permanent);
128  return true;
129  }
130  return false;
131 }
132 
133 
135 MSRoute::dictionary(const std::string& id, SumoRNG* rng) {
136 #ifdef HAVE_FOX
137  FXMutexLock f(myDictMutex);
138 #endif
139  RouteDict::iterator it = myDict.find(id);
140  if (it == myDict.end()) {
141  RouteDistDict::iterator it2 = myDistDict.find(id);
142  if (it2 == myDistDict.end() || it2->second.first->getOverallProb() == 0) {
143  return nullptr;
144  }
145  return it2->second.first->get(rng);
146  }
147  return it->second;
148 }
149 
150 
151 bool
152 MSRoute::hasRoute(const std::string& id) {
153 #ifdef HAVE_FOX
154  FXMutexLock f(myDictMutex);
155 #endif
156  return myDict.find(id) != myDict.end();
157 }
158 
159 
161 MSRoute::distDictionary(const std::string& id) {
162 #ifdef HAVE_FOX
163  FXMutexLock f(myDictMutex);
164 #endif
165  RouteDistDict::iterator it2 = myDistDict.find(id);
166  if (it2 == myDistDict.end()) {
167  return nullptr;
168  }
169  return it2->second.first;
170 }
171 
172 
173 void
175 #ifdef HAVE_FOX
176  FXMutexLock f(myDictMutex);
177 #endif
178  for (RouteDistDict::iterator i = myDistDict.begin(); i != myDistDict.end(); ++i) {
179  delete i->second.first;
180  }
181  myDistDict.clear();
182  myDict.clear();
183 }
184 
185 
186 void
187 MSRoute::checkDist(const std::string& id) {
188 #ifdef HAVE_FOX
189  FXMutexLock f(myDictMutex);
190 #endif
191  RouteDistDict::iterator it = myDistDict.find(id);
192  if (it != myDistDict.end() && !it->second.second) {
193  for (ConstMSRoutePtr rp : it->second.first->getVals()) {
194  const MSRoute& r = *rp;
195  r.checkRemoval();
196  }
197  delete it->second.first;
198  myDistDict.erase(it);
199  }
200 }
201 
202 
203 void
204 MSRoute::insertIDs(std::vector<std::string>& into) {
205 #ifdef HAVE_FOX
206  FXMutexLock f(myDictMutex);
207 #endif
208  into.reserve(myDict.size() + myDistDict.size() + into.size());
209  for (RouteDict::const_iterator i = myDict.begin(); i != myDict.end(); ++i) {
210  into.push_back((*i).first);
211  }
212  for (RouteDistDict::const_iterator i = myDistDict.begin(); i != myDistDict.end(); ++i) {
213  into.push_back((*i).first);
214  }
215 }
216 
217 
218 int
219 MSRoute::writeEdgeIDs(OutputDevice& os, int firstIndex, int lastIndex, bool withInternal, SUMOVehicleClass svc) const {
220  //std::cout << SIMTIME << " writeEdgeIDs " << getID() << " first=" << firstIndex << " lastIndex=" << lastIndex << " edges=" << toString(myEdges) << "\n";
221  if (lastIndex < 0) {
222  lastIndex = (int)myEdges.size();
223  }
224  int internal = 0;
225  for (int i = firstIndex; i < lastIndex; i++) {
226  os << myEdges[i]->getID() << ' ';
227  if (withInternal && i + 1 < lastIndex) {
228  const MSEdge* next = myEdges[i + 1];
229  const MSEdge* edge = myEdges[i]->getInternalFollowingEdge(next, svc);
230  // Take into account non-internal lengths until next non-internal edge
231  while (edge != nullptr && edge->isInternal()) {
232  os << edge->getID() << ' ';
233  internal++;
234  edge = edge->getInternalFollowingEdge(next, svc);
235  }
236  }
237  }
238  return internal + lastIndex - firstIndex;
239 }
240 
241 
242 bool
243 MSRoute::containsAnyOf(const MSEdgeVector& edgelist) const {
244  MSEdgeVector::const_iterator i = edgelist.begin();
245  for (; i != edgelist.end(); ++i) {
246  if (contains(*i)) {
247  return true;
248  }
249  }
250  return false;
251 }
252 
253 
254 const MSEdge*
255 MSRoute::operator[](int index) const {
256  return myEdges[index];
257 }
258 
259 
260 void
262 #ifdef HAVE_FOX
263  FXMutexLock f(myDictMutex);
264 #endif
265  for (RouteDict::iterator it = myDict.begin(); it != myDict.end(); ++it) {
266  ConstMSRoutePtr r = (*it).second;
267  out.openTag(SUMO_TAG_ROUTE);
268  out.writeAttr(SUMO_ATTR_ID, r->getID());
269  out.writeAttr(SUMO_ATTR_STATE, r->myAmPermanent);
270  out.writeAttr(SUMO_ATTR_EDGES, r->myEdges);
271  if (r->myColor != nullptr) {
272  out.writeAttr(SUMO_ATTR_COLOR, *r->myColor);
273  }
274  for (auto stop : r->getStops()) {
275  stop.write(out);
276  }
277  out.closeTag();
278  }
279  for (const auto& item : myDistDict) {
280  if (item.second.first->getVals().size() > 0) {
282  out.writeAttr(SUMO_ATTR_STATE, item.second.second);
283  std::ostringstream oss;
284  bool space = false;
285  for (const auto& route : item.second.first->getVals()) {
286  if (space) {
287  oss << " ";
288  }
289  oss << route->getID();
290  space = true;
291  }
292  out.writeAttr(SUMO_ATTR_ROUTES, oss.str());
293  out.writeAttr(SUMO_ATTR_PROBS, item.second.first->getProbs());
294  out.closeTag();
295  }
296  }
297 }
298 
299 
300 void
302 #ifdef HAVE_FOX
303  FXMutexLock f(myDictMutex);
304 #endif
305  myDistDict.clear();
306  myDict.clear();
307 }
308 
309 
310 double
311 MSRoute::getDistanceBetween(double fromPos, double toPos,
312  const MSLane* fromLane, const MSLane* toLane, int routePosition) const {
313  // std::cout << SIMTIME << " getDistanceBetween from=" << fromEdge->getID() << " to=" << toEdge->getID() << " fromPos=" << fromPos << " toPos=" << toPos << "\n";
314  assert(fromPos >= 0. && fromPos <= fromLane->getLength());
315  assert(toPos >= 0. && toPos <= toLane->getLength());
316  assert(routePosition >= 0 && routePosition < (int)myEdges.size());
317  assert(routePosition == 0 || !myEdges.front()->isInternal());
318  const MSEdge* fromEdge = &fromLane->getEdge();
319  const MSEdge* toEdge = &toLane->getEdge();
320  if (fromEdge == toEdge && fromPos <= toPos) {
321  return toPos - fromPos;
322  }
323  // TODO If fromEdge and toEdge are identical or both are internal and directly connected,
324  // the code does not check whether they are in any relation to the route.
325  if (fromEdge->isInternal()) {
326  double minDist = std::numeric_limits<double>::max();
327  for (const auto& via : fromEdge->getViaSuccessors()) {
328  const MSEdge* const succ = via.second == nullptr ? via.first : via.second;
329  assert(succ != nullptr);
330  // std::cout << " recurse fromSucc=" << succ->getID() << "\n";
331  const double d = getDistanceBetween(0., toPos, succ->getLanes()[0], toLane, routePosition);
332  if (d != std::numeric_limits<double>::max() && fromLane->getLength() - fromPos + d < minDist) {
333  minDist = fromLane->getLength() - fromPos + d;
334  }
335  }
336  return minDist;
337  }
338  if (toEdge->isInternal()) {
339  const MSEdge* const pred = toEdge->getPredecessors().front();
340  assert(pred != nullptr);
341  // std::cout << " recurse toPred=" << pred->getID() << "\n";
342  const double d = getDistanceBetween(fromPos, pred->getLength(), fromLane, pred->getLanes()[0], routePosition);
343  return d == std::numeric_limits<double>::max() ? d : toPos + d;
344  }
345  ConstMSEdgeVector::const_iterator fromIt = std::find(myEdges.begin() + routePosition, myEdges.end(), fromEdge);
346  if (fromIt == myEdges.end()) {
347  // start not contained in route
348  return std::numeric_limits<double>::max();
349  }
350  ConstMSEdgeVector::const_iterator toIt = std::find(fromIt + 1, myEdges.end(), toEdge);
351  if (toIt == myEdges.end()) {
352  // destination not contained in route
353  return std::numeric_limits<double>::max();
354  }
355  return getDistanceBetween(fromPos, toPos, fromIt, toIt, true);
356 }
357 
358 
359 double
360 MSRoute::getDistanceBetween(double fromPos, double toPos,
361  const MSRouteIterator& fromEdge, const MSRouteIterator& toEdge, bool includeInternal) const {
362  bool isFirstIteration = true;
363  double distance = -fromPos;
364  MSRouteIterator it = fromEdge;
365  if (fromEdge == toEdge) {
366  // destination position is on start edge
367  if (fromPos <= toPos) {
368  return toPos - fromPos;
369  } else {
370  // we cannot go backwards. Something is wrong here
371  return std::numeric_limits<double>::max();
372  }
373  } else if (fromEdge > toEdge) {
374  // we don't visit the edge again
375  return std::numeric_limits<double>::max();
376  }
377  for (; it != end(); ++it) {
378  if (it == toEdge && !isFirstIteration) {
379  distance += toPos;
380  break;
381  } else {
382  distance += (*it)->getLength();
383  if (includeInternal && (it + 1) != end()) {
384  // XXX the length may be wrong if there are parallel internal edges for different vClasses
385  distance += (*it)->getInternalFollowingLengthTo(*(it + 1), SVC_IGNORING);
386  }
387  }
388  isFirstIteration = false;
389  }
390  return distance;
391 }
392 
393 
394 const RGBColor&
396  if (myColor == nullptr) {
398  }
399  return *myColor;
400 }
401 
402 
403 const std::vector<SUMOVehicleParameter::Stop>&
405  return myStops;
406 }
407 
408 
409 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
std::vector< const MSEdge * > ConstMSEdgeVector
Definition: MSEdge.h:74
std::vector< MSEdge * > MSEdgeVector
Definition: MSEdge.h:73
ConstMSEdgeVector::const_iterator MSRouteIterator
Definition: MSRoute.h:56
std::shared_ptr< const MSRoute > ConstMSRoutePtr
Definition: Route.h:31
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_IGNORING
vehicles ignoring classes
@ SUMO_TAG_ROUTE_DISTRIBUTION
distribution of a route
@ SUMO_TAG_ROUTE
begin/end of the description of a route
@ SUMO_ATTR_PROBS
@ SUMO_ATTR_EDGES
the edges of a route
@ SUMO_ATTR_ROUTES
@ SUMO_ATTR_COLOR
A color information.
@ SUMO_ATTR_ID
@ SUMO_ATTR_STATE
The state of a link.
A road/street connecting two junctions.
Definition: MSEdge.h:77
const MSEdgeVector & getPredecessors() const
Definition: MSEdge.h:406
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:168
const MSConstEdgePairVector & getViaSuccessors(SUMOVehicleClass vClass=SVC_IGNORING, bool ignoreTransientPermissions=false) const
Returns the following edges with internal vias, restricted by vClass.
Definition: MSEdge.cpp:1224
double getLength() const
return the length of the edge
Definition: MSEdge.h:662
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:265
const MSEdge * getInternalFollowingEdge(const MSEdge *followerAfterInternal, SUMOVehicleClass vClass) const
Definition: MSEdge.cpp:836
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
double getLength() const
Returns the lane's length.
Definition: MSLane.h:598
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:756
static void dict_clearState()
Decrement all route references before quick-loading state.
Definition: MSRoute.cpp:301
int size() const
Returns the number of edges to pass.
Definition: MSRoute.cpp:85
static RouteDistDict myDistDict
The dictionary container.
Definition: MSRoute.h:323
static void dict_saveState(OutputDevice &out)
Saves all known routes into the given stream.
Definition: MSRoute.cpp:261
const RGBColor *const myColor
The color.
Definition: MSRoute.h:289
static RouteDict myDict
The dictionary container.
Definition: MSRoute.h:317
std::vector< SUMOVehicleParameter::Stop > myStops
List of the stops on the parsed route.
Definition: MSRoute.h:304
const std::vector< SUMOVehicleParameter::Stop > & getStops() const
Returns the stops.
Definition: MSRoute.cpp:404
MSRouteIterator end() const
Returns the end of the list of edges to pass.
Definition: MSRoute.cpp:79
int writeEdgeIDs(OutputDevice &os, int firstIndex=0, int lastIndex=-1, bool withInternal=false, SUMOVehicleClass svc=SVC_IGNORING) const
Output the edge ids up to but not including the id of the given edge.
Definition: MSRoute.cpp:219
static bool hasRoute(const std::string &id)
returns whether a route with the given id exists
Definition: MSRoute.cpp:152
std::map< std::string, ConstMSRoutePtr > RouteDict
Definition of the dictionary container.
Definition: MSRoute.h:314
virtual ~MSRoute()
Destructor.
Definition: MSRoute.cpp:67
void checkRemoval() const
removes the route from the internal dict if it is not marked as permanent
Definition: MSRoute.cpp:98
const MSEdge * operator[](int index) const
Definition: MSRoute.cpp:255
bool contains(const MSEdge *const edge) const
Definition: MSRoute.h:103
const MSEdge * getLastEdge() const
returns the destination edge
Definition: MSRoute.cpp:91
ConstMSEdgeVector myEdges
The list of edges to pass.
Definition: MSRoute.h:283
static void insertIDs(std::vector< std::string > &into)
Definition: MSRoute.cpp:204
bool containsAnyOf(const MSEdgeVector &edgelist) const
Definition: MSRoute.cpp:243
std::map< std::string, std::pair< RandomDistributor< ConstMSRoutePtr > *, bool > > RouteDistDict
Definition of the dictionary container.
Definition: MSRoute.h:320
static bool dictionary(const std::string &id, ConstMSRoutePtr route)
Adds a route to the dictionary.
Definition: MSRoute.cpp:109
const RGBColor & getColor() const
Returns the color.
Definition: MSRoute.cpp:395
static RandomDistributor< ConstMSRoutePtr > * distDictionary(const std::string &id)
Returns the named route distribution.
Definition: MSRoute.cpp:161
MSRouteIterator begin() const
Returns the begin of the list of edges to pass.
Definition: MSRoute.cpp:73
double getDistanceBetween(double fromPos, double toPos, const MSLane *fromLane, const MSLane *toLane, int routePosition=0) const
Compute the distance between 2 given edges on this route, optionally including the length of internal...
Definition: MSRoute.cpp:311
const bool myAmPermanent
whether the route may be deleted after the last vehicle abandoned it
Definition: MSRoute.h:286
static void checkDist(const std::string &id)
Checks the distribution whether it is permanent and deletes it if not.
Definition: MSRoute.cpp:187
MSRoute(const std::string &id, const ConstMSEdgeVector &edges, const bool isPermanent, const RGBColor *const c, const std::vector< SUMOVehicleParameter::Stop > &stops, SUMOTime replacedTime=-1, int replacedIndex=0)
Constructor.
Definition: MSRoute.cpp:49
static void clear()
Clears the dictionary (delete all known routes, too)
Definition: MSRoute.cpp:174
Base class for objects which have an id.
Definition: Named.h:54
const std::string & getID() const
Returns the id.
Definition: Named.h:74
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:254
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
static const RGBColor DEFAULT_COLOR
The default color (for vehicle types and vehicles)
Definition: RGBColor.h:199