1 /****************************************************************************/ 2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo 3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others. 4 // This program and the accompanying materials 5 // are made available under the terms of the Eclipse Public License v2.0 6 // which accompanies this distribution, and is available at 7 // http://www.eclipse.org/legal/epl-v20.html 8 // SPDX-License-Identifier: EPL-2.0 9 /****************************************************************************/ 10 /// @file IntermodalRouter.h 11 /// @author Jakob Erdmann 12 /// @author Michael Behrisch 13 /// @date Mon, 03 March 2014 14 /// @version $Id$ 15 /// 16 // The IntermodalRouter builds a special network and (delegates to a SUMOAbstractRouter) 17 /****************************************************************************/ 18 #ifndef IntermodalRouter_h 19 #define IntermodalRouter_h 20 21 22 // =========================================================================== 23 // included modules 24 // =========================================================================== 25 #include <config.h> 26 27 #include <string> 28 #include <vector> 29 #include <algorithm> 30 #include <assert.h> 31 #include <utils/common/MsgHandler.h> 32 #include <utils/common/SUMOTime.h> 33 #include <utils/common/ToString.h> 34 #include <utils/iodevices/OutputDevice.h> 35 #include "SUMOAbstractRouter.h" 36 #include "DijkstraRouter.h" 37 #include "AStarRouter.h" 38 #include "IntermodalNetwork.h" 39 #include "EffortCalculator.h" 40 #include "CarEdge.h" 41 #include "StopEdge.h" 42 #include "PedestrianRouter.h" 43 44 //#define IntermodalRouter_DEBUG_ROUTES 45 46 47 // =========================================================================== 48 // class definitions 49 // =========================================================================== 50 /** 51 * @class IntermodalRouter 52 * The router for pedestrians (on a bidirectional network of sidewalks and crossings) 53 */ 54 template<class E, class L, class N, class V> 55 class IntermodalRouter : public SUMOAbstractRouter<E, IntermodalTrip<E, N, V> > { 56 public: 57 typedef IntermodalNetwork<E, L, N, V> Network; 58 59 private: 60 typedef void(*CreateNetCallback)(IntermodalRouter <E, L, N, V>&); 61 typedef IntermodalEdge<E, L, N, V> _IntermodalEdge; 62 typedef IntermodalTrip<E, N, V> _IntermodalTrip; 63 typedef SUMOAbstractRouterPermissions<_IntermodalEdge, _IntermodalTrip> _InternalRouter; 64 typedef DijkstraRouter<_IntermodalEdge, _IntermodalTrip, _InternalRouter> _InternalDijkstra; 65 typedef AStarRouter<_IntermodalEdge, _IntermodalTrip, _InternalRouter> _InternalAStar; 66 67 public: 68 struct TripItem { 69 TripItem(const std::string& _line = "") : lineTripItem70 line(_line), intended(_line), depart(-1), traveltime(0.), cost(0.) {} 71 std::string line; 72 std::string vType; 73 std::string destStop; 74 std::string intended; // intended public transport vehicle id 75 double depart; // intended public transport departure 76 std::vector<const E*> edges; 77 double traveltime; 78 double cost; 79 double length; 80 double departPos; 81 double arrivalPos; 82 std::string description; 83 }; 84 85 /// Constructor 86 IntermodalRouter(CreateNetCallback callback, const int carWalkTransfer, const std::string& routingAlgorithm, 87 const int routingMode = 0, EffortCalculator* calc = nullptr) : 88 SUMOAbstractRouter<E, _IntermodalTrip>("IntermodalRouter", true), 89 myAmClone(false), myInternalRouter(nullptr), myIntermodalNet(nullptr), 90 myCallback(callback), myCarWalkTransfer(carWalkTransfer), myRoutingAlgorithm(routingAlgorithm), 91 myRoutingMode(routingMode), myExternalEffort(calc) { 92 } 93 94 /// Destructor ~IntermodalRouter()95 virtual ~IntermodalRouter() { 96 delete myInternalRouter; 97 if (!myAmClone) { 98 delete myIntermodalNet; 99 } 100 } 101 clone()102 SUMOAbstractRouter<E, _IntermodalTrip>* clone() { 103 createNet(); 104 return new IntermodalRouter<E, L, N, V>(myIntermodalNet, myCarWalkTransfer, myRoutingAlgorithm, myRoutingMode, myExternalEffort); 105 } 106 107 /** @brief Builds the route between the given edges using the minimum effort at the given time 108 The definition of the effort depends on the wished routing scheme */ 109 bool compute(const E* from, const E* to, const double departPos, const double arrivalPos, 110 const std::string stopID, const double speed, 111 const V* const vehicle, const SVCPermissions modeSet, const SUMOTime msTime, 112 std::vector<TripItem>& into, const double externalFactor = 0.) { 113 createNet(); 114 _IntermodalTrip trip(from, to, departPos, arrivalPos, speed, msTime, 0, vehicle, modeSet, myExternalEffort, externalFactor); 115 std::vector<const _IntermodalEdge*> intoEdges; 116 //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"; 117 const bool success = myInternalRouter->compute(myIntermodalNet->getDepartEdge(from, trip.departPos), 118 stopID != "" ? myIntermodalNet->getStopEdge(stopID) : myIntermodalNet->getArrivalEdge(to, trip.arrivalPos), 119 &trip, msTime, intoEdges); 120 if (success) { 121 std::string lastLine = ""; 122 double time = STEPS2TIME(msTime); 123 double effort = 0.; 124 double length = 0.; 125 const _IntermodalEdge* prev = nullptr; 126 for (const _IntermodalEdge* iEdge : intoEdges) { 127 if (iEdge->includeInRoute(false)) { 128 if (iEdge->getLine() == "!stop") { 129 if (into.size() > 0) { 130 // previous stage ends at stop 131 into.back().destStop = iEdge->getID(); 132 if (myExternalEffort != nullptr) { 133 into.back().description = myExternalEffort->output(iEdge->getNumericalID()); 134 } 135 if (lastLine == "!ped") { 136 lastLine = ""; // a stop always starts a new trip item 137 } 138 } else { 139 // trip starts at stop 140 lastLine = ""; 141 into.push_back(TripItem("!stop")); 142 into.back().destStop = iEdge->getID(); 143 } 144 } else { 145 if (iEdge->getLine() != lastLine) { 146 lastLine = iEdge->getLine(); 147 if (lastLine == "!car") { 148 into.push_back(TripItem(vehicle->getID())); 149 into.back().vType = vehicle->getParameter().vtypeid; 150 } else if (lastLine == "!ped") { 151 into.push_back(TripItem()); 152 } else { 153 into.push_back(TripItem(lastLine)); 154 into.back().depart = iEdge->getIntended(time, into.back().intended); 155 } 156 into.back().departPos = iEdge->getStartPos(); 157 } 158 if (into.back().edges.empty() || into.back().edges.back() != iEdge->getEdge()) { 159 into.back().edges.push_back(iEdge->getEdge()); 160 into.back().arrivalPos = iEdge->getEndPos(); 161 } 162 } 163 } 164 const double prevTime = time, prevEffort = effort, prevLength = length; 165 myInternalRouter->updateViaCost(prev, iEdge, &trip, time, effort, length); 166 prev = iEdge; 167 if (!into.empty()) { 168 into.back().traveltime += time - prevTime; 169 into.back().cost += effort - prevEffort; 170 into.back().length += length - prevLength; 171 } 172 } 173 } 174 #ifdef IntermodalRouter_DEBUG_ROUTES 175 double time = STEPS2TIME(msTime); 176 for (const _IntermodalEdge* iEdge : intoEdges) { 177 const double edgeEffort = myInternalRouter->getEffort(iEdge, &trip, time); 178 time += edgeEffort; 179 std::cout << iEdge->getID() << "(" << iEdge->getLine() << "): " << edgeEffort << std::endl; 180 } 181 std::cout << TIME2STEPS(msTime) << " trip from " << from->getID() << " to " << (to != nullptr ? to->getID() : stopID) 182 << " departPos=" << trip.departPos 183 << " arrivalPos=" << trip.arrivalPos 184 << " edges=" << toString(intoEdges) 185 // << " resultEdges=" << toString(into) 186 << " time=" << time 187 << "\n"; 188 #endif 189 return success; 190 } 191 192 /** @brief Builds the route between the given edges using the minimum effort at the given time 193 The definition of the effort depends on the wished routing scheme */ compute(const E *,const E *,const _IntermodalTrip * const,SUMOTime,std::vector<const E * > &,bool)194 bool compute(const E*, const E*, const _IntermodalTrip* const, 195 SUMOTime, std::vector<const E*>&, bool) { 196 throw ProcessError("Do not use this method"); 197 } 198 prohibit(const std::vector<E * > & toProhibit)199 void prohibit(const std::vector<E*>& toProhibit) { 200 createNet(); 201 std::vector<_IntermodalEdge*> toProhibitPE; 202 for (typename std::vector<E*>::const_iterator it = toProhibit.begin(); it != toProhibit.end(); ++it) { 203 toProhibitPE.push_back(myIntermodalNet->getBothDirections(*it).first); 204 toProhibitPE.push_back(myIntermodalNet->getBothDirections(*it).second); 205 toProhibitPE.push_back(myIntermodalNet->getCarEdge(*it)); 206 } 207 myInternalRouter->prohibit(toProhibitPE); 208 } 209 writeNetwork(OutputDevice & dev)210 void writeNetwork(OutputDevice& dev) { 211 createNet(); 212 for (_IntermodalEdge* e : myIntermodalNet->getAllEdges()) { 213 dev.openTag(SUMO_TAG_EDGE); 214 dev.writeAttr(SUMO_ATTR_ID, e->getID()); 215 dev.writeAttr(SUMO_ATTR_LINE, e->getLine()); 216 dev.writeAttr(SUMO_ATTR_LENGTH, e->getLength()); 217 dev.writeAttr("successors", toString(e->getSuccessors(SVC_IGNORING))); 218 dev.closeTag(); 219 } 220 } 221 writeWeights(OutputDevice & dev)222 void writeWeights(OutputDevice& dev) { 223 createNet(); 224 _IntermodalTrip trip(nullptr, nullptr, 0., 0., DEFAULT_PEDESTRIAN_SPEED, 0, 0, nullptr, SVC_PASSENGER | SVC_BICYCLE | SVC_BUS); 225 for (_IntermodalEdge* e : myIntermodalNet->getAllEdges()) { 226 dev.openTag(SUMO_TAG_EDGE); 227 dev.writeAttr(SUMO_ATTR_ID, e->getID()); 228 dev.writeAttr("traveltime", e->getTravelTime(&trip, 0.)); 229 dev.writeAttr("effort", e->getEffort(&trip, 0.)); 230 dev.closeTag(); 231 } 232 } 233 getNetwork()234 Network* getNetwork() const { 235 return myIntermodalNet; 236 } 237 getExternalEffort()238 EffortCalculator* getExternalEffort() const { 239 return myExternalEffort; 240 } 241 242 private: IntermodalRouter(Network * net,const int carWalkTransfer,const std::string & routingAlgorithm,const int routingMode,EffortCalculator * calc)243 IntermodalRouter(Network* net, const int carWalkTransfer, const std::string& routingAlgorithm, 244 const int routingMode, EffortCalculator* calc) : 245 SUMOAbstractRouter<E, _IntermodalTrip>("IntermodalRouterClone", true), myAmClone(true), 246 myInternalRouter(new _InternalDijkstra(net->getAllEdges(), true, 247 gWeightsRandomFactor > 1 ? & _IntermodalEdge::getTravelTimeStaticRandomized : & _IntermodalEdge::getTravelTimeStatic)), 248 myIntermodalNet(net), myCarWalkTransfer(carWalkTransfer), myRoutingAlgorithm(routingAlgorithm), myRoutingMode(routingMode), myExternalEffort(calc) {} 249 getEffortAggregated(const _IntermodalEdge * const edge,const _IntermodalTrip * const trip,double time)250 static inline double getEffortAggregated(const _IntermodalEdge* const edge, const _IntermodalTrip* const trip, double time) { 251 return edge == nullptr || !edge->hasEffort() ? 0. : edge->getEffort(trip, time); 252 } 253 getCombined(const _IntermodalEdge * const edge,const _IntermodalTrip * const trip,double time)254 static inline double getCombined(const _IntermodalEdge* const edge, const _IntermodalTrip* const trip, double time) { 255 return edge->getTravelTime(trip, time) + trip->externalFactor * trip->calc->getEffort(edge->getNumericalID()); 256 } 257 createNet()258 inline void createNet() { 259 if (myIntermodalNet == nullptr) { 260 myIntermodalNet = new Network(E::getAllEdges(), false, myCarWalkTransfer); 261 myIntermodalNet->addCarEdges(E::getAllEdges()); 262 myCallback(*this); 263 switch (myRoutingMode) { 264 case 0: 265 if (myRoutingAlgorithm == "astar") { 266 myInternalRouter = new _InternalAStar(myIntermodalNet->getAllEdges(), true, 267 gWeightsRandomFactor > 1 ? &_IntermodalEdge::getTravelTimeStaticRandomized : &_IntermodalEdge::getTravelTimeStatic); 268 } else { 269 myInternalRouter = new _InternalDijkstra(myIntermodalNet->getAllEdges(), true, 270 gWeightsRandomFactor > 1 ? &_IntermodalEdge::getTravelTimeStaticRandomized : &_IntermodalEdge::getTravelTimeStatic); 271 } 272 break; 273 case 1: 274 myInternalRouter = new _InternalDijkstra(myIntermodalNet->getAllEdges(), true, &getEffortAggregated, &_IntermodalEdge::getTravelTimeStatic); 275 break; 276 case 2: 277 myInternalRouter = new _InternalDijkstra(myIntermodalNet->getAllEdges(), true, &_IntermodalEdge::getEffortStatic, &_IntermodalEdge::getTravelTimeStatic); 278 break; 279 case 3: 280 if (myExternalEffort != nullptr) { 281 std::vector<std::string> edgeLines; 282 for (const auto e : myIntermodalNet->getAllEdges()) { 283 edgeLines.push_back(e->getLine()); 284 } 285 myExternalEffort->init(edgeLines); 286 } 287 myInternalRouter = new _InternalDijkstra(myIntermodalNet->getAllEdges(), true, &getCombined, &_IntermodalEdge::getTravelTimeStatic, false, myExternalEffort); 288 break; 289 } 290 } 291 } 292 293 private: 294 const bool myAmClone; 295 _InternalRouter* myInternalRouter; 296 Network* myIntermodalNet; 297 CreateNetCallback myCallback; 298 const int myCarWalkTransfer; 299 const std::string myRoutingAlgorithm; 300 const int myRoutingMode; 301 EffortCalculator* const myExternalEffort; 302 303 304 private: 305 /// @brief Invalidated assignment operator 306 IntermodalRouter& operator=(const IntermodalRouter& s); 307 308 }; 309 310 311 #endif 312 313 /****************************************************************************/ 314