Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
IntermodalRouter.h
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-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/****************************************************************************/
19// The IntermodalRouter builds a special network and (delegates to a SUMOAbstractRouter)
20/****************************************************************************/
21#pragma once
22#include <config.h>
23
24#include <string>
25#include <vector>
26#include <algorithm>
27#include <assert.h>
33#include "SUMOAbstractRouter.h"
34#include "DijkstraRouter.h"
35#include "AStarRouter.h"
36#include "IntermodalNetwork.h"
37#include "EffortCalculator.h"
38#include "CarEdge.h"
39#include "StopEdge.h"
40#include "PedestrianRouter.h"
41
42//#define IntermodalRouter_DEBUG_ROUTES
43
44
45// ===========================================================================
46// class definitions
47// ===========================================================================
52template<class E, class L, class N, class V>
53class IntermodalRouter : public SUMOAbstractRouter<E, IntermodalTrip<E, N, V> > {
54public:
57
58private:
59 typedef void(*CreateNetCallback)(IntermodalRouter <E, L, N, V>&);
66
67public:
68 struct TripItem {
69 TripItem(const std::string& _line = "") :
70 line(_line), intended(_line) {}
71 std::string line;
72 std::string vType = "";
73 std::string destStop = "";
74 std::string intended; // intended public transport vehicle id
75 double depart = -1.; // intended public transport departure
76 std::vector<const E*> edges;
77 double traveltime = 0.;
78 double cost = 0.;
79 double length = 0.;
82 std::string description = "";
83 std::vector<double> exitTimes;
84 };
85
87 IntermodalRouter(CreateNetCallback callback, const int carWalkTransfer, double taxiWait, const std::string& routingAlgorithm,
88 const int routingMode = 0, EffortCalculator* calc = nullptr) :
89 SUMOAbstractRouter<E, _IntermodalTrip>("IntermodalRouter", true, nullptr, nullptr, false, false),
90 myAmClone(false), myInternalRouter(nullptr), myIntermodalNet(nullptr),
91 myCallback(callback), myCarWalkTransfer(carWalkTransfer), myTaxiWait(taxiWait),
92 myRoutingAlgorithm(routingAlgorithm),
93 myRoutingMode(routingMode), myExternalEffort(calc) {
94 }
95
98 delete myInternalRouter;
99 if (!myAmClone) {
100 delete myIntermodalNet;
101 }
102 }
103
108
109 int getCarWalkTransfer() const {
110 return myCarWalkTransfer;
111 }
112
115 bool compute(const E* from, const E* to,
116 const double departPos, const std::string& originStopID,
117 const double arrivalPos, const std::string& stopID,
118 const double speed, const V* const vehicle,
119 const SUMOVTypeParameter& pars,
120 const SVCPermissions modeSet, const SUMOTime msTime,
121 std::vector<TripItem>& into, const double externalFactor = 0.) {
122 createNet();
123 _IntermodalTrip trip(from, to, departPos, arrivalPos, speed, msTime, nullptr, pars, vehicle, modeSet, myExternalEffort, externalFactor);
124 std::vector<const _IntermodalEdge*> intoEdges;
125 //std::cout << "compute from=" << from->getID() << " to=" << to->getID() << " dPos=" << departPos << " aPos=" << arrivalPos << " stopID=" << stopID << " speed=" << speed << " veh=" << Named::getIDSecure(vehicle) << " modeSet=" << modeSet << " t=" << msTime << " iFrom=" << myIntermodalNet->getDepartEdge(from, trip.departPos)->getID() << " iTo=" << (stopID != "" ? myIntermodalNet->getStopEdge(stopID) : myIntermodalNet->getArrivalEdge(to, trip.arrivalPos))->getID() << "\n";
126 const _IntermodalEdge* iFrom = originStopID != "" ? myIntermodalNet->getStopEdge(originStopID) : myIntermodalNet->getDepartEdge(from, trip.departPos);
127 const _IntermodalEdge* iTo = stopID != "" ? myIntermodalNet->getStopEdge(stopID) : myIntermodalNet->getArrivalEdge(to, trip.arrivalPos);
128 const bool success = myInternalRouter->compute(iFrom, iTo, &trip, msTime, intoEdges, true);
129 if (success) {
130 std::string lastLine = "";
131 const _IntermodalEdge* lastLineEdge = nullptr;
132 double lastLineTime = STEPS2TIME(msTime);
133 double time = STEPS2TIME(msTime);
134 double effort = 0.;
135 double length = 0.;
136 const _IntermodalEdge* prev = nullptr;
137 for (const _IntermodalEdge* iEdge : intoEdges) {
138 bool addedEdge = false;
139 if (iEdge->includeInRoute(false)) {
140 if (iEdge->getLine() == "!stop") {
141 if (into.size() > 0) {
142 // previous stage ends at stop
143 into.back().destStop = iEdge->getID();
144 if (myExternalEffort != nullptr) {
145 into.back().description = myExternalEffort->output(iEdge->getNumericalID());
146 }
147 if (lastLine == "!ped") {
148 lastLine = ""; // a stop always starts a new trip item
149 }
150 } else {
151 // trip starts at stop
152 lastLine = "";
153 into.push_back(TripItem("!stop"));
154 into.back().destStop = iEdge->getID();
155 }
156 } else {
157 if (iEdge->getLine() != lastLine || loopedLineTransfer(lastLineEdge, iEdge, lastLineTime, time)) {
158 lastLine = iEdge->getLine();
159 lastLineEdge = iEdge;
160 lastLineTime = time;
161 if (lastLine == "!car") {
162 into.push_back(TripItem(vehicle->getID()));
163 into.back().vType = vehicle->getParameter().vtypeid;
164 } else if (lastLine == "!ped") {
165 into.push_back(TripItem());
166 } else {
167 into.push_back(TripItem(lastLine));
168 into.back().depart = iEdge->getIntended(time, into.back().intended);
169 }
170 into.back().departPos = iEdge->getStartPos();
171 }
172 if (into.back().edges.empty() || into.back().edges.back() != iEdge->getEdge()) {
173 into.back().edges.push_back(iEdge->getEdge());
174 into.back().arrivalPos = iEdge->getEndPos();
175 addedEdge = true;
176 }
177 }
178 }
179 const double prevTime = time;
180 const double prevEffort = effort;
181 const double prevLength = length;
182 myInternalRouter->updateViaCost(prev, iEdge, &trip, time, effort, length);
183 // correct intermodal length:
184 length += iEdge->getPartialLength(&trip) - iEdge->getLength();
185 prev = iEdge;
186 if (!into.empty()) {
187 into.back().traveltime += time - prevTime;
188 into.back().cost += effort - prevEffort;
189 into.back().length += length - prevLength;
190 if (into.back().depart < 0) {
191 into.back().depart = prevTime;
192 }
193 if (addedEdge) {
194 into.back().exitTimes.push_back(time);
195 }
196 }
197 }
198 } else {
199 const std::string oType = originStopID != "" ? "stop" : "edge";
200 const std::string oID = originStopID != "" ? originStopID : from->getID();
201 const std::string dType = stopID != "" ? "stop" : "edge";
202 const std::string dID = stopID != "" ? stopID : to->getID();
203 this->myErrorMsgHandler->informf(TL("No connection between % '%' and % '%' found."), oType, oID, dType, dID);
204 }
205 if (into.size() > 0) {
206 into.back().arrivalPos = arrivalPos;
207 }
208#ifdef IntermodalRouter_DEBUG_ROUTES
209 double time = STEPS2TIME(msTime);
210 for (const _IntermodalEdge* iEdge : intoEdges) {
211 const double edgeEffort = myInternalRouter->getEffort(iEdge, &trip, time);
212 time += edgeEffort;
213 std::cout << iEdge->getID() << "(" << iEdge->getLine() << "): " << edgeEffort << " l=" << iEdge->getLength() << " pL=" << iEdge->getPartialLength(&trip) << "\n";
214 }
215 std::cout << TIME2STEPS(msTime) << " trip from " << from->getID() << " to " << (to != nullptr ? to->getID() : stopID)
216 << " departPos=" << trip.departPos
217 << " arrivalPos=" << trip.arrivalPos
218 << " modes=" << getVehicleClassNames(modeSet)
219 << " edges=" << toString(intoEdges)
220// << " resultEdges=" << toString(into)
221 << " time=" << time
222 << "\n";
223#endif
224 return success;
225 }
226
229 bool compute(const E*, const E*, const _IntermodalTrip* const,
230 SUMOTime, std::vector<const E*>&, bool) {
231 throw ProcessError(TL("Do not use this method"));
232 }
233
234 inline void setBulkMode(const bool mode) {
236 if (myInternalRouter != nullptr) {
238 }
239 }
240
241 void prohibit(const _Prohibitions& toProhibit) {
242 createNet();
243 typename _InternalRouter::Prohibitions toProhibitPE;
244 for (auto item : toProhibit) {
245 toProhibitPE[myIntermodalNet->getBothDirections(item.first).first] = item.second;
246 toProhibitPE[myIntermodalNet->getBothDirections(item.first).second] = item.second;
247 toProhibitPE[myIntermodalNet->getCarEdge(item.first)] = item.second;
248 }
249 myInternalRouter->prohibit(toProhibitPE);
250 }
251
253 createNet();
256 dev.writeAttr(SUMO_ATTR_ID, e->getID());
257 dev.writeAttr(SUMO_ATTR_LINE, e->getLine());
258 dev.writeAttr(SUMO_ATTR_LENGTH, e->getLength());
259 dev.writeAttr("successors", toString(e->getSuccessors(SVC_IGNORING)));
260 dev.closeTag();
261 }
262 }
263
265 createNet();
267 _IntermodalTrip trip(nullptr, nullptr, 0., 0., DEFAULT_PEDESTRIAN_SPEED, 0, nullptr,
268 dummyVT, nullptr, SVC_PASSENGER | SVC_BICYCLE | SVC_BUS);
271 dev.writeAttr(SUMO_ATTR_ID, e->getID());
272 dev.writeAttr("traveltime", e->getTravelTime(&trip, 0.));
273 dev.writeAttr("effort", e->getEffort(&trip, 0.));
274 dev.closeTag();
275 }
276 }
277
279 return myIntermodalNet;
280 }
281
285
286private:
287 IntermodalRouter(Network* net, const int carWalkTransfer, double taxiWait, const std::string& routingAlgorithm,
288 const int routingMode, EffortCalculator* calc) :
289 SUMOAbstractRouter<E, _IntermodalTrip>("IntermodalRouterClone", true, nullptr, nullptr, false, false),
290 myAmClone(true), myInternalRouter(nullptr), myIntermodalNet(net),
291 myCarWalkTransfer(carWalkTransfer),
292 myTaxiWait(taxiWait),
293 myRoutingAlgorithm(routingAlgorithm), myRoutingMode(routingMode), myExternalEffort(calc) {
294 createNet();
295 }
296
297 static inline double getCombined(const _IntermodalEdge* const edge, const _IntermodalTrip* const trip, double time) {
298 return edge->getTravelTime(trip, time) + trip->externalFactor * trip->calc->getEffort(edge->getNumericalID());
299 }
300
301 inline void createNet() {
302 if (myIntermodalNet == nullptr) {
303 myIntermodalNet = new Network(E::getAllEdges(), false, myCarWalkTransfer);
304 myIntermodalNet->addCarEdges(E::getAllEdges(), myTaxiWait);
305 myCallback(*this);
306 }
307 if (myInternalRouter == nullptr) {
308 switch (myRoutingMode) {
309 case 0:
310 if (myRoutingAlgorithm == "astar") {
313 } else {
316 }
317 break;
318 case 1:
320 break;
321 case 2:
323 break;
324 case 3:
325 if (myExternalEffort != nullptr) {
326 std::vector<std::string> edgeLines;
327 for (const auto e : myIntermodalNet->getAllEdges()) {
328 edgeLines.push_back(e->getLine());
329 }
330 myExternalEffort->init(edgeLines);
331 }
333 break;
334 }
335 }
336 }
337
338
339 bool loopedLineTransfer(const _IntermodalEdge* prev, const _IntermodalEdge* cur, double prevTime, double time) {
340 assert(prev != nullptr);
341 if (myIntermodalNet->isLooped(cur->getLine())) {
342 // check if the last two edges are served by different vehicles
343 std::string intended1;
344 std::string intended2;
345 prev->getIntended(prevTime, intended1);
346 cur->getIntended(time, intended2);
347 return intended1 != intended2;
348 }
349 return false;
350 }
351
352private:
353 const bool myAmClone;
358 const double myTaxiWait;
359 const std::string myRoutingAlgorithm;
360 const int myRoutingMode;
362
363
364private:
367
368};
long long int SUMOTime
Definition GUI.h:36
#define TL(string)
Definition MsgHandler.h:304
#define STEPS2TIME(x)
Definition SUMOTime.h:55
#define TIME2STEPS(x)
Definition SUMOTime.h:57
const std::string & getVehicleClassNames(SVCPermissions permissions, bool expand)
Returns the ids of the given classes, divided using a ' '.
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
const std::string DEFAULT_PEDTYPE_ID
const double DEFAULT_PEDESTRIAN_SPEED
@ SVC_IGNORING
vehicles ignoring classes
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_BUS
vehicle is a bus
@ SVC_PEDESTRIAN
pedestrian
@ SUMO_TAG_EDGE
begin/end of the description of an edge
@ SUMO_ATTR_LINE
@ SUMO_ATTR_LENGTH
@ SUMO_ATTR_ID
double gWeightsRandomFactor
Definition StdDefs.cpp:35
const double INVALID_DOUBLE
invalid double
Definition StdDefs.h:68
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
Computes the shortest path through a network using the A* algorithm.
Definition AStarRouter.h:76
Computes the shortest path through a network using the Dijkstra algorithm.
the effort calculator interface
virtual double getEffort(const int numericalID) const =0
virtual std::string output(const int edge) const =0
virtual void init(const std::vector< std::string > &edges)=0
the base edge type that is given to the internal router (SUMOAbstractRouter)
static double getTravelTimeStatic(const IntermodalEdge *const edge, const IntermodalTrip< E, N, V > *const trip, double time)
const std::string & getLine() const
virtual double getTravelTime(const IntermodalTrip< E, N, V > *const, double) const
int getNumericalID() const
virtual double getIntended(const double, std::string &) const
get intended vehicle id and departure time of next public transport ride
static double getEffortStatic(const IntermodalEdge *const edge, const IntermodalTrip< E, N, V > *const trip, double time)
virtual double getTravelTimeAggregated(const IntermodalTrip< E, N, V > *const trip, double time) const
static double getTravelTimeStaticRandomized(const IntermodalEdge *const edge, const IntermodalTrip< E, N, V > *const trip, double time)
the intermodal network storing edges, connections and the mappings to the "real" edges
const std::vector< _IntermodalEdge * > & getAllEdges()
_IntermodalEdge * getCarEdge(const E *e) const
Returns the associated car edge.
_IntermodalEdge * getStopEdge(const std::string &stopId) const
Returns the associated stop edge.
bool isLooped(const std::string lineID) const
const EdgePair & getBothDirections(const E *e) const
Returns the pair of forward and backward edge.
void addCarEdges(const std::vector< E * > &edges, double taxiWait)
_IntermodalEdge * getArrivalEdge(const E *e, const double pos) const
Returns the arriving intermodal edge.
const _IntermodalEdge * getDepartEdge(const E *e, const double pos) const
Returns the departing intermodal edge.
EffortCalculator * getExternalEffort() const
SUMOAbstractRouter< _IntermodalEdge, _IntermodalTrip > _InternalRouter
IntermodalTrip< E, N, V > _IntermodalTrip
CreateNetCallback myCallback
static double getCombined(const _IntermodalEdge *const edge, const _IntermodalTrip *const trip, double time)
void(* CreateNetCallback)(IntermodalRouter< E, L, N, V > &)
bool compute(const E *from, const E *to, const double departPos, const std::string &originStopID, const double arrivalPos, const std::string &stopID, const double speed, const V *const vehicle, const SUMOVTypeParameter &pars, const SVCPermissions modeSet, const SUMOTime msTime, std::vector< TripItem > &into, const double externalFactor=0.)
Builds the route between the given edges using the minimum effort at the given time The definition of...
IntermodalEdge< E, L, N, V > _IntermodalEdge
const int myCarWalkTransfer
virtual ~IntermodalRouter()
Destructor.
IntermodalNetwork< E, L, N, V > Network
IntermodalRouter(Network *net, const int carWalkTransfer, double taxiWait, const std::string &routingAlgorithm, const int routingMode, EffortCalculator *calc)
SUMOAbstractRouter< E, _IntermodalTrip > * clone()
IntermodalRouter(CreateNetCallback callback, const int carWalkTransfer, double taxiWait, const std::string &routingAlgorithm, const int routingMode=0, EffortCalculator *calc=nullptr)
Constructor.
bool compute(const E *, const E *, const _IntermodalTrip *const, SUMOTime, std::vector< const E * > &, bool)
Builds the route between the given edges using the minimum effort at the given time The definition of...
DijkstraRouter< _IntermodalEdge, _IntermodalTrip > _InternalDijkstra
const std::string myRoutingAlgorithm
IntermodalRouter & operator=(const IntermodalRouter &s)
Invalidated assignment operator.
const double myTaxiWait
bool loopedLineTransfer(const _IntermodalEdge *prev, const _IntermodalEdge *cur, double prevTime, double time)
void prohibit(const _Prohibitions &toProhibit)
Network * getNetwork() const
void writeWeights(OutputDevice &dev)
void setBulkMode(const bool mode)
EffortCalculator *const myExternalEffort
SUMOAbstractRouter< E, SUMOVehicle >::Prohibitions _Prohibitions
_InternalRouter * myInternalRouter
int getCarWalkTransfer() const
void writeNetwork(OutputDevice &dev)
MapMatcher< E, L, N > _MapMatcher
AStarRouter< _IntermodalEdge, _IntermodalTrip, _MapMatcher > _InternalAStar
the "vehicle" type that is given to the internal router (SUMOAbstractRouter)
const EffortCalculator *const calc
const double departPos
const double arrivalPos
const double externalFactor
Provides utility functions for matching locations to edges (during route parsing)
Definition MapMatcher.h:45
void informf(const std::string &format, T value, Targs... Fargs)
adds a new formatted message
Definition MsgHandler.h:116
const std::string & getID() const
Returns the id.
Definition Named.h:74
Static storage of an output device and its base (abstract) implementation.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
virtual void setBulkMode(const bool mode)
std::map< const E *, RouterProhibition > Prohibitions
void updateViaCost(const E *const prev, const E *const e, const V *const v, double &time, double &effort, double &length) const
double getEffort(const E *const e, const V *const v, double t) const
virtual void prohibit(const Prohibitions &toProhibit)
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...
MsgHandler * myErrorMsgHandler
the handler for routing errors
Structure representing possible vehicle parameter.
TripItem(const std::string &_line="")
std::vector< double > exitTimes
std::vector< const E * > edges