SUMO - Simulation of Urban MObility
IntermodalRouter.h
Go to the documentation of this file.
1 /****************************************************************************/
7 // The Pedestrian Router build a special network and (delegegates to a SUMOAbstractRouter)
8 /****************************************************************************/
9 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
10 // Copyright (C) 2001-2016 DLR (http://www.dlr.de/) and contributors
11 /****************************************************************************/
12 //
13 // This file is part of SUMO.
14 // SUMO is free software: you can redistribute it and/or modify
15 // it under the terms of the GNU General Public License as published by
16 // the Free Software Foundation, either version 3 of the License, or
17 // (at your option) any later version.
18 //
19 /****************************************************************************/
20 #ifndef IntermodalRouter_h
21 #define IntermodalRouter_h
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 
33 #include <string>
34 #include <vector>
35 #include <algorithm>
36 #include <assert.h>
38 #include <utils/common/SUMOTime.h>
39 #include <utils/common/ToString.h>
40 #include "SUMOAbstractRouter.h"
41 #include "SUMOVehicleParameter.h"
42 #include "DijkstraRouterTT.h"
43 #include "IntermodalNetwork.h"
44 #include "CarEdge.h"
45 #include "PedestrianRouter.h"
46 
47 //#define IntermodalRouter_DEBUG_ROUTES
48 
49 
50 // ===========================================================================
51 // class definitions
52 // ===========================================================================
57 template<class E, class L, class N, class V, class INTERNALROUTER = DijkstraRouterTT<IntermodalEdge<E, L, N, V>, IntermodalTrip<E, N, V>, prohibited_withPermissions<IntermodalEdge<E, L, N, V>, IntermodalTrip<E, N, V> > > >
58 class IntermodalRouter : public SUMOAbstractRouter<E, IntermodalTrip<E, N, V> > {
59 private:
66 
67 public:
68  struct TripItem {
69  TripItem(const std::string& _line = "") : line(_line) {}
70  std::string line;
71  std::string destStop;
72  std::vector<const E*> edges;
73  };
74 
77  SUMOAbstractRouter<E, _IntermodalTrip>(0, "IntermodalRouter"), myAmClone(false), myInternalRouter(0), myIntermodalNet(0), myNumericalID(0), myCallback(callback) {
78  }
79 
81  virtual ~IntermodalRouter() {
82  delete myInternalRouter;
83  if (!myAmClone) {
84  delete myIntermodalNet;
85  }
86  }
87 
89  createNet();
91  }
92 
93  int splitEdge(_IntermodalEdge* const toSplit, _IntermodalEdge* afterSplit, const SUMOReal pos,
94  _IntermodalEdge* const fwdConn, _IntermodalEdge* const backConn = 0) {
95  int splitIndex = 1;
96  std::vector<_IntermodalEdge*>& splitList = myAccessSplits[toSplit];
97  if (splitList.empty()) {
98  splitList.push_back(toSplit);
99  }
100  typename std::vector<_IntermodalEdge*>::iterator splitIt = splitList.begin();
101  SUMOReal totalLength = 0.;
102  while (splitIt != splitList.end() && totalLength + (*splitIt)->getLength() + POSITION_EPS < pos) {
103  totalLength += (*splitIt)->getLength();
104  ++splitIt;
105  splitIndex++;
106  }
107  assert(splitIt != splitList.end());
108  _IntermodalEdge* const beforeSplit = *splitIt;
109  if (fabs(totalLength - pos) < POSITION_EPS && splitIt + 1 != splitList.end()) {
110  // don't split, use the present split edges
111  splitIndex = -1;
112  afterSplit = *(splitIt + 1);
113  } else {
114  myIntermodalNet->addEdge(afterSplit);
115  afterSplit->setSuccessors(beforeSplit->getSuccessors(SVC_IGNORING));
116  beforeSplit->clearSuccessors();
117  beforeSplit->addSuccessor(afterSplit);
118  afterSplit->setLength(totalLength - pos);
119  beforeSplit->setLength(beforeSplit->getLength() - afterSplit->getLength());
120  splitList.insert(splitIt + 1, afterSplit);
121  }
122  // add access to / from edge
123  _AccessEdge* access = new _AccessEdge(myNumericalID++, beforeSplit, fwdConn);
124  myIntermodalNet->addEdge(access);
125  beforeSplit->addSuccessor(access);
126  access->addSuccessor(fwdConn);
127  if (backConn == 0) {
128  _AccessEdge* exit = new _AccessEdge(myNumericalID++, fwdConn, afterSplit);
129  myIntermodalNet->addEdge(exit);
130  fwdConn->addSuccessor(exit);
131  exit->addSuccessor(afterSplit);
132  } else {
133  _AccessEdge* backward = new _AccessEdge(myNumericalID++, beforeSplit, backConn);
134  myIntermodalNet->addEdge(backward);
135  beforeSplit->addSuccessor(backward);
136  backward->addSuccessor(backConn);
137  }
138  return splitIndex;
139  }
140 
141  void addAccess(const std::string& stopId, const E* stopEdge, const SUMOReal pos) {
142  assert(stopEdge != 0);
143  if (myStopConnections.count(stopId) == 0) {
144  myStopConnections[stopId] = new StopEdge<E, L, N, V>(stopId, myNumericalID++, stopEdge);
146  }
147  _IntermodalEdge* const stopConn = myStopConnections[stopId];
148  const L* lane = getSidewalk<E, L>(stopEdge);
149  if (lane != 0) {
150  const std::pair<_IntermodalEdge*, _IntermodalEdge*>& pair = myIntermodalNet->getBothDirections(stopEdge);
151  _IntermodalEdge* const fwdSplit = new PedestrianEdge<E, L, N, V>(myNumericalID++, stopEdge, lane, true, pos);
152  const int splitIndex = splitEdge(pair.first, fwdSplit, pos, stopConn);
153  _IntermodalEdge* const backSplit = new PedestrianEdge<E, L, N, V>(myNumericalID++, stopEdge, lane, false, pos);
154  splitEdge(pair.second, backSplit, stopEdge->getLength() - pos, stopConn);
155  if (splitIndex >= 0) {
156  _IntermodalEdge* carSplit = 0;
157  if (myCarLookup.count(stopEdge) > 0) {
158  carSplit = new CarEdge<E, L, N, V>(myNumericalID++, stopEdge, pos);
159  splitEdge(myCarLookup[stopEdge], carSplit, pos, fwdSplit, backSplit);
160  }
161 
162  _IntermodalEdge* const prevDep = myIntermodalNet->getDepartEdge(stopEdge, pos);
163  _IntermodalEdge* const backBeforeSplit = myAccessSplits[pair.second][myAccessSplits[pair.second].size() - 1 - splitIndex];
164  // depart and arrival edges (the router can decide the initial direction to take and the direction to arrive from)
165  _IntermodalEdge* const depConn = new _IntermodalEdge(stopEdge->getID() + "_depart_connector" + toString(pos), myNumericalID++, stopEdge, "!connector");
166  depConn->addSuccessor(fwdSplit);
167  depConn->addSuccessor(backBeforeSplit);
168  prevDep->removeSuccessor(backBeforeSplit);
169  prevDep->addSuccessor(backSplit);
170  if (carSplit != 0) {
171  depConn->addSuccessor(carSplit);
172  }
173 
174  _IntermodalEdge* const arrConn = new _IntermodalEdge(stopEdge->getID() + "_arrival_connector" + toString(pos), myNumericalID++, stopEdge, "!connector");
175  fwdSplit->addSuccessor(arrConn);
176  backBeforeSplit->addSuccessor(arrConn);
177  if (carSplit != 0) {
178  carSplit->addSuccessor(arrConn);
179  }
180  myIntermodalNet->addConnectors(depConn, arrConn, splitIndex);
181  }
182  }
183  }
184 
185  void addSchedule(const SUMOVehicleParameter& pars) {
186  SUMOTime lastUntil = 0;
187  std::vector<SUMOVehicleParameter::Stop> validStops;
188  for (std::vector<SUMOVehicleParameter::Stop>::const_iterator s = pars.stops.begin(); s != pars.stops.end(); ++s) {
189  if (myStopConnections.count(s->busstop) > 0 && s->until >= lastUntil) {
190  validStops.push_back(*s);
191  lastUntil = s->until;
192  }
193  }
194  if (validStops.size() < 2) {
195  WRITE_WARNING("Ignoring public transport line '" + pars.line + "' with less than two usable stops.");
196  return;
197  }
198 
199  typename std::vector<_PTEdge*>& lineEdges = myPTLines[pars.line];
200  if (lineEdges.empty()) {
201  _IntermodalEdge* lastStop = 0;
202  SUMOTime lastTime = 0;
203  for (std::vector<SUMOVehicleParameter::Stop>::const_iterator s = validStops.begin(); s != validStops.end(); ++s) {
204  _IntermodalEdge* currStop = myStopConnections[s->busstop];
205  if (lastStop != 0) {
206  _PTEdge* const newEdge = new _PTEdge(s->busstop, myNumericalID++, lastStop, currStop->getEdge(), pars.line);
207  myIntermodalNet->addEdge(newEdge);
208  newEdge->addSchedule(lastTime, pars.repetitionEnd + lastTime - pars.depart, pars.repetitionOffset, STEPS2TIME(s->until - lastTime));
209  lastStop->addSuccessor(newEdge);
210  newEdge->addSuccessor(currStop);
211  lineEdges.push_back(newEdge);
212  }
213  lastTime = s->until;
214  lastStop = currStop;
215  }
216  } else {
217  if (validStops.size() != lineEdges.size() + 1) {
218  WRITE_WARNING("Number of stops for public transport line '" + pars.line + "' does not match earlier definitions, ignoring schedule.");
219  return;
220  }
221  if (lineEdges.front()->getEntryStop() != myStopConnections[validStops.front().busstop]) {
222  WRITE_WARNING("Different stop for '" + pars.line + "' compared to earlier definitions, ignoring schedule.");
223  return;
224  }
225  typename std::vector<_PTEdge*>::const_iterator lineEdge = lineEdges.begin();
226  typename std::vector<SUMOVehicleParameter::Stop>::const_iterator s = validStops.begin() + 1;
227  for (; s != validStops.end(); ++s, ++lineEdge) {
228  if ((*lineEdge)->getSuccessors(SVC_IGNORING)[0] != myStopConnections[s->busstop]) {
229  WRITE_WARNING("Different stop for '" + pars.line + "' compared to earlier definitions, ignoring schedule.");
230  return;
231  }
232  }
233  SUMOTime lastTime = validStops.front().until;
234  for (lineEdge = lineEdges.begin(), s = validStops.begin() + 1; lineEdge != lineEdges.end(); ++lineEdge, ++s) {
235  (*lineEdge)->addSchedule(lastTime, pars.repetitionEnd + lastTime - pars.depart, pars.repetitionOffset, STEPS2TIME(s->until - lastTime));
236  lastTime = s->until;
237  }
238  }
239  }
240 
243  bool compute(const E* from, const E* to, SUMOReal departPos, SUMOReal arrivalPos, SUMOReal speed,
244  const V* const vehicle, const SVCPermissions modeSet, SUMOTime msTime,
245  std::vector<TripItem>& into) {
246  createNet();
247  _IntermodalTrip trip(from, to, departPos, arrivalPos, speed, msTime, 0, vehicle, modeSet);
248  std::vector<const _IntermodalEdge*> intoPed;
249  const bool success = myInternalRouter->compute(myIntermodalNet->getDepartEdge(from, departPos),
250  myIntermodalNet->getArrivalEdge(to, arrivalPos),
251  &trip, msTime, intoPed);
252  if (success) {
253  std::string lastLine = "";
254  for (int i = 0; i < (int)intoPed.size(); ++i) {
255  if (intoPed[i]->includeInRoute(false)) {
256  if (intoPed[i]->getLine() == "!stop") {
257  into.back().destStop = intoPed[i]->getID();
258  } else {
259  if (intoPed[i]->getLine() != lastLine) {
260  lastLine = intoPed[i]->getLine();
261  if (lastLine == "!car") {
262  into.push_back(TripItem(vehicle->getID()));
263  } else if (lastLine == "!ped") {
264  into.push_back(TripItem());
265  } else {
266  into.push_back(TripItem(lastLine));
267  }
268  }
269  if (into.back().edges.empty() || into.back().edges.back() != intoPed[i]->getEdge()) {
270  into.back().edges.push_back(intoPed[i]->getEdge());
271  }
272  }
273  }
274  }
275  }
276 #ifdef IntermodalRouter_DEBUG_ROUTES
277  SUMOReal time = STEPS2TIME(msTime);
278  for (int i = 0; i < intoPed.size(); ++i) {
279  time += myInternalRouter->getEffort(intoPed[i], &trip, time);
280  }
281  std::cout << TIME2STEPS(msTime) << " trip from " << from->getID() << " to " << to->getID()
282  << " departPos=" << departPos
283  << " arrivalPos=" << arrivalPos
284  << " edges=" << toString(intoPed)
285 // << " resultEdges=" << toString(into)
286  << " time=" << time
287  << "\n";
288 #endif
289  return success;
290  }
291 
294  bool compute(const E*, const E*, const _IntermodalTrip* const,
295  SUMOTime, std::vector<const E*>&) {
296  throw ProcessError("Do not use this method");
297  }
298 
299  SUMOReal recomputeCosts(const std::vector<const E*>&, const _IntermodalTrip* const, SUMOTime) const {
300  throw ProcessError("Do not use this method");
301  }
302 
303  void prohibit(const std::vector<E*>& toProhibit) {
304  std::vector<_IntermodalEdge*> toProhibitPE;
305  for (typename std::vector<E*>::const_iterator it = toProhibit.begin(); it != toProhibit.end(); ++it) {
306  toProhibitPE.push_back(myIntermodalNet->getBothDirections(*it).first);
307  toProhibitPE.push_back(myIntermodalNet->getBothDirections(*it).second);
308  toProhibitPE.push_back(getCarEdge(*it));
309  }
310  myInternalRouter->prohibit(toProhibitPE);
311  }
312 
313 private:
314  IntermodalRouter(_IntermodalNetwork* net):
315  SUMOAbstractRouter<E, _IntermodalTrip>(0, "PedestrianRouter"), myAmClone(true),
316  myInternalRouter(new INTERNALROUTER(net->getAllEdges(), true, &_IntermodalEdge::getTravelTimeStatic)),
317  myIntermodalNet(net), myNumericalID((int)net->getAllEdges().size()) {}
318 
319  void addCarEdges(const std::vector<E*>& edges) {
320  for (typename std::vector<E*>::const_iterator i = edges.begin(); i != edges.end(); ++i) {
321  const E* const edge = *i;
322  if (!edge->isInternal()) {
323  myCarLookup[edge] = new CarEdge<E, L, N, V>(myNumericalID++, edge);
325  }
326  }
327  for (typename std::vector<E*>::const_iterator i = edges.begin(); i != edges.end(); ++i) {
328  const E* const edge = *i;
329  if (!edge->isInternal()) {
330  _IntermodalEdge* startConnector = myIntermodalNet->getDepartEdge(edge);
331  _IntermodalEdge* endConnector = myIntermodalNet->getArrivalEdge(edge);
332  _IntermodalEdge* carEdge = getCarEdge(edge);
333  const std::vector<E*>& successors = edge->getSuccessors();
334  for (typename std::vector<E*>::const_iterator it = successors.begin(); it != successors.end(); ++it) {
335  carEdge->addSuccessor(getCarEdge(*it));
336  }
337  startConnector->addSuccessor(carEdge);
338  carEdge->addSuccessor(endConnector);
339  }
340  }
341  }
342 
343  inline void createNet() {
344  if (myIntermodalNet == 0) {
345  myIntermodalNet = new _IntermodalNetwork(E::getAllEdges(), myNumericalID);
346  myNumericalID = (int)myIntermodalNet->getAllEdges().size();
347  addCarEdges(E::getAllEdges());
348  myCallback(*this);
350  }
351  }
352 
354  _IntermodalEdge* getCarEdge(const E* e) {
355  typename std::map<const E*, _IntermodalEdge*>::const_iterator it = myCarLookup.find(e);
356  if (it == myCarLookup.end()) {
357  throw ProcessError("Car edge '" + e->getID() + "' not found in pedestrian network.");
358  }
359  return it->second;
360  }
361 
362 private:
363  const bool myAmClone;
364  INTERNALROUTER* myInternalRouter;
365  _IntermodalNetwork* myIntermodalNet;
368 
370  std::map<const E*, _IntermodalEdge*> myCarLookup;
371 
373  std::map<std::string, std::vector<_PTEdge*> > myPTLines;
374 
376  std::map<std::string, _IntermodalEdge*> myStopConnections;
377 
379  std::map<_IntermodalEdge*, std::vector<_IntermodalEdge*> > myAccessSplits;
380 
381 
382 private:
385 
386 };
387 
388 
389 
394 template<class E, class L, class N, class V>
396 public:
399  IntermodalRouter<E, L, N, V>* interRouter)
400  : myVehRouter(vehRouter), myPedRouter(pedRouter), myInterRouter(interRouter) {}
401 
403  : myVehRouter(original.getVehicleRouter().clone()),
404  myPedRouter(static_cast<PedestrianRouterDijkstra<E, L, N, V>*>(original.myPedRouter == 0 ? 0 : original.getPedestrianRouter().clone())),
405  myInterRouter(static_cast<IntermodalRouter<E, L, N, V>*>(original.myInterRouter == 0 ? 0 : original.getIntermodalRouter().clone())) {}
406 
408  return *myVehRouter;
409  }
410 
412  return *myPedRouter;
413  }
414 
416  return *myInterRouter;
417  }
418 
419  virtual ~RouterProvider() {
420  delete myVehRouter;
421  delete myPedRouter;
422  delete myInterRouter;
423  }
424 
425 
426 private:
430 
431 
432 private:
435 
436 };
437 
438 
439 #endif
440 
441 /****************************************************************************/
SUMOTime repetitionEnd
The time at which the flow ends (only needed when using repetitionProbability)
bool compute(const E *from, const E *to, SUMOReal departPos, SUMOReal arrivalPos, SUMOReal speed, const V *const vehicle, const SVCPermissions modeSet, SUMOTime msTime, std::vector< TripItem > &into)
Builds the route between the given edges using the minimum effort at the given time The definition of...
IntermodalRouter< E, L, N, V > & getIntermodalRouter() const
IntermodalRouter & operator=(const IntermodalRouter &s)
Invalidated assignment operator.
long long int SUMOTime
Definition: SUMOTime.h:43
std::map< const E *, _IntermodalEdge * > myCarLookup
retrieve the car edge for the given input edge E
void addSchedule(const SUMOTime begin, const SUMOTime end, const SUMOTime period, const SUMOReal travelTimeSec)
Definition: CarEdge.h:158
const std::vector< _IntermodalEdge * > & getAllEdges()
RouterProvider(const RouterProvider &original)
virtual ~RouterProvider()
SUMOAbstractRouter< E, V > *const myVehRouter
void addEdge(_IntermodalEdge *edge)
void(* CreateNetCallback)(IntermodalRouter< E, L, N, V, INTERNALROUTER > &)
_IntermodalEdge * getDepartEdge(const E *e, const SUMOReal pos=-1.)
Returns the departing Intermodal edge.
AccessEdge< E, L, N, V > _AccessEdge
int SVCPermissions
void addSuccessor(IntermodalEdge *s)
_IntermodalNetwork * myIntermodalNet
std::map< _IntermodalEdge *, std::vector< _IntermodalEdge * > > myAccessSplits
retrieve the splitted edges for the given "original"
the car edge type that is given to the internal router (SUMOAbstractRouter)
Definition: CarEdge.h:44
std::map< std::string, std::vector< _PTEdge * > > myPTLines
retrieve the public transport edges for the given line
void addAccess(const std::string &stopId, const E *stopEdge, const SUMOReal pos)
const std::string & getID() const
Returns the id.
Definition: Named.h:66
#define TIME2STEPS(x)
Definition: SUMOTime.h:66
SUMOReal getLength() const
TripItem(const std::string &_line="")
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
SUMOTime repetitionOffset
The time offset between vehicle reinsertions.
void removeSuccessor(const IntermodalEdge *const edge)
_IntermodalEdge * getArrivalEdge(const E *e, const SUMOReal pos=-1.)
Returns the arriving Intermodal edge.
std::vector< Stop > stops
List of the stops the vehicle will make.
const E * getEdge() const
#define new
Definition: debug_new.h:121
PublicTransportEdge< E, L, N, V > _PTEdge
bool compute(const E *, const E *, const _IntermodalTrip *const, SUMOTime, std::vector< const E *> &)
Builds the route between the given edges using the minimum effort at the given time The definition of...
CreateNetCallback myCallback
int splitEdge(_IntermodalEdge *const toSplit, _IntermodalEdge *afterSplit, const SUMOReal pos, _IntermodalEdge *const fwdConn, _IntermodalEdge *const backConn=0)
IntermodalRouter(_IntermodalNetwork *net)
void setSuccessors(const std::vector< IntermodalEdge *> &edges)
IntermodalTrip< E, N, V > _IntermodalTrip
SUMOAbstractRouter< E, _IntermodalTrip > * clone()
SUMOTime depart
The vehicle&#39;s departure time.
#define STEPS2TIME(x)
Definition: SUMOTime.h:65
the "vehicle" type that is given to the internal router (SUMOAbstractRouter)
PedestrianRouterDijkstra< E, L, N, V > & getPedestrianRouter() const
IntermodalRouter(CreateNetCallback callback)
Constructor.
#define POSITION_EPS
Definition: config.h:187
std::vector< const E * > edges
_IntermodalEdge * getCarEdge(const E *e)
Returns the associated car edge.
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:55
PedestrianRouterDijkstra< E, L, N, V > *const myPedRouter
the pedestrian network storing edges, connections and the mappings to the "real" edges ...
void addSchedule(const SUMOVehicleParameter &pars)
std::string line
The vehicle&#39;s line (mainly for public transport)
the base edge type that is given to the internal router (SUMOAbstractRouter)
INTERNALROUTER * myInternalRouter
std::map< std::string, _IntermodalEdge * > myStopConnections
retrieve the connecting edges for the given "bus" stop
SUMOAbstractRouter< E, V > & getVehicleRouter() const
IntermodalNetwork< E, L, N, V > _IntermodalNetwork
Structure representing possible vehicle parameter.
IntermodalEdge< E, L, N, V > _IntermodalEdge
virtual ~IntermodalRouter()
Destructor.
the public transport edge type connecting the stop edges
Definition: CarEdge.h:132
const EdgePair & getBothDirections(const E *e)
Returns the pair of forward and backward edge.
void prohibit(const std::vector< E *> &toProhibit)
IntermodalRouter< E, L, N, V > *const myInterRouter
static SUMOReal getTravelTimeStatic(const IntermodalEdge *const edge, const IntermodalTrip< E, N, V > *const trip, SUMOReal time)
#define SUMOReal
Definition: config.h:213
void setLength(const SUMOReal length)
the pedestrian edge type that is given to the internal router (SUMOAbstractRouter) ...
RouterProvider(SUMOAbstractRouter< E, V > *vehRouter, PedestrianRouterDijkstra< E, L, N, V > *pedRouter, IntermodalRouter< E, L, N, V > *interRouter)
void addConnectors(_IntermodalEdge *const depConn, _IntermodalEdge *const arrConn, const int splitIndex)
SUMOReal recomputeCosts(const std::vector< const E *> &, const _IntermodalTrip *const, SUMOTime) const
the stop edge type representing bus and train stops
Definition: CarEdge.h:115
vehicles ignoring classes
void addCarEdges(const std::vector< E *> &edges)
the access edge connecting diferent modes that is given to the internal router (SUMOAbstractRouter) ...
Definition: CarEdge.h:186