Line data Source code
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 : /****************************************************************************/
14 : /// @file PedestrianRouter.h
15 : /// @author Jakob Erdmann
16 : /// @date Mon, 03 March 2014
17 : ///
18 : // The Pedestrian Router builds a special network and delegates to a SUMOAbstractRouter.
19 : /****************************************************************************/
20 : #pragma once
21 : #include <config.h>
22 :
23 : #include <string>
24 : #include <vector>
25 : #include <algorithm>
26 : #include <assert.h>
27 : #include <utils/common/MsgHandler.h>
28 : #include <utils/common/SUMOTime.h>
29 : #include <utils/common/ToString.h>
30 : #include "SUMOAbstractRouter.h"
31 : #include "DijkstraRouter.h"
32 : #include "IntermodalNetwork.h"
33 :
34 : //#define PedestrianRouter_DEBUG_ROUTES
35 :
36 :
37 : // ===========================================================================
38 : // class definitions
39 : // ===========================================================================
40 : /**
41 : * @class PedestrianRouter
42 : * The router for pedestrians (on a bidirectional network of sidewalks and crossings)
43 : */
44 : template<class E, class L, class N, class V>
45 : class PedestrianRouter : public SUMOAbstractRouter<E, IntermodalTrip<E, N, V> > {
46 : private:
47 : typedef IntermodalEdge<E, L, N, V> _IntermodalEdge;
48 : typedef IntermodalNetwork<E, L, N, V> _IntermodalNetwork;
49 : typedef IntermodalTrip<E, N, V> _IntermodalTrip;
50 : typedef DijkstraRouter<_IntermodalEdge, _IntermodalTrip> _InternalRouter;
51 :
52 : public:
53 : /// Constructor
54 8907 : PedestrianRouter():
55 8907 : SUMOAbstractRouter<E, _IntermodalTrip>("PedestrianRouter", true, nullptr, nullptr, false, false), myAmClone(false) {
56 8907 : myPedNet = new _IntermodalNetwork(E::getAllEdges(), true);
57 17814 : myInternalRouter = new _InternalRouter(myPedNet->getAllEdges(), true,
58 8907 : gWeightsRandomFactor > 1 ? &_IntermodalEdge::getTravelTimeStaticRandomized : &_IntermodalEdge::getTravelTimeStatic,
59 : nullptr, false, nullptr, true);
60 8907 : }
61 :
62 50 : PedestrianRouter(_IntermodalNetwork* net):
63 50 : SUMOAbstractRouter<E, _IntermodalTrip>("PedestrianRouterClone", true, nullptr, nullptr, false, false), myAmClone(true) {
64 50 : myPedNet = net;
65 100 : myInternalRouter = new _InternalRouter(myPedNet->getAllEdges(), true,
66 50 : gWeightsRandomFactor > 1 ? &_IntermodalEdge::getTravelTimeStaticRandomized : &_IntermodalEdge::getTravelTimeStatic,
67 : nullptr, false, nullptr, true);
68 50 : }
69 :
70 : /// Destructor
71 17914 : virtual ~PedestrianRouter() {
72 8957 : delete myInternalRouter;
73 8957 : if (!myAmClone) {
74 8907 : delete myPedNet;
75 : }
76 26871 : }
77 :
78 50 : virtual SUMOAbstractRouter<E, _IntermodalTrip>* clone() {
79 50 : return new PedestrianRouter<E, L, N, V>(myPedNet);
80 : }
81 :
82 : /** @brief Builds the route between the given edges using the minimum effort at the given time
83 : The definition of the effort depends on the wished routing scheme */
84 907886 : double compute(const E* from, const E* to, double departPos, double arrivalPos, double speed,
85 : SUMOTime msTime, const N* onlyNode, std::vector<const E*>& into, bool allEdges = false) const {
86 907886 : if (getSidewalk<E, L>(from) == 0) {
87 0 : WRITE_WARNINGF(TL("Departure edge '%' does not allow pedestrians."), from->getID());
88 0 : return false;
89 : }
90 907886 : if (getSidewalk<E, L>(to) == 0) {
91 12 : WRITE_WARNINGF(TL("Destination edge '%' does not allow pedestrians."), to->getID());
92 4 : return false;
93 : }
94 : _IntermodalTrip trip(from, to, departPos, arrivalPos, speed, msTime, onlyNode);
95 : std::vector<const _IntermodalEdge*> intoPed;
96 : const bool silent = allEdges; // no warning is needed when called from MSPModel_Striping
97 907882 : const bool success = myInternalRouter->compute(myPedNet->getDepartConnector(from),
98 907882 : myPedNet->getArrivalConnector(to),
99 : &trip, msTime, intoPed, silent);
100 : double time = 0.;
101 907882 : if (success) {
102 4843722 : for (const _IntermodalEdge* pedEdge : intoPed) {
103 3935873 : if (pedEdge->includeInRoute(allEdges)) {
104 3024368 : into.push_back(pedEdge->getEdge());
105 : }
106 3935873 : time += myInternalRouter->getEffort(pedEdge, &trip, time);
107 : }
108 : }
109 : #ifdef PedestrianRouter_DEBUG_ROUTES
110 : std::cout << TIME2STEPS(msTime) << " trip from " << from->getID() << " to " << to->getID()
111 : << " departPos=" << departPos
112 : << " arrivalPos=" << arrivalPos
113 : << " onlyNode=" << (onlyNode == 0 ? "NULL" : onlyNode->getID())
114 : << " edges=" << toString(intoPed)
115 : << " resultEdges=" << toString(into)
116 : << " time=" << time
117 : << "\n";
118 : #endif
119 : return success ? time : -1.;
120 907882 : }
121 :
122 : /** @brief Builds the route between the given edges using the minimum effort at the given time
123 : The definition of the effort depends on the wished routing scheme */
124 0 : bool compute(const E*, const E*, const _IntermodalTrip* const,
125 : SUMOTime, std::vector<const E*>&, bool) {
126 0 : throw ProcessError(TL("Do not use this method"));
127 : }
128 :
129 907902 : void prohibit(const std::vector<E*>& toProhibit) {
130 : std::vector<_IntermodalEdge*> toProhibitPE;
131 1812473 : for (typename std::vector<E*>::const_iterator it = toProhibit.begin(); it != toProhibit.end(); ++it) {
132 904571 : toProhibitPE.push_back(myPedNet->getBothDirections(*it).first);
133 904571 : toProhibitPE.push_back(myPedNet->getBothDirections(*it).second);
134 : }
135 907902 : myInternalRouter->prohibit(toProhibitPE);
136 907902 : }
137 :
138 24 : double recomputeWalkCosts(const std::vector<const E*>& edges, double speed, double fromPos, double toPos, SUMOTime msTime, double& length) const {
139 : // edges are normal edges so we need to reconstruct paths across intersection
140 24 : if (edges.size() == 0) {
141 0 : length = 0;
142 0 : return 0;
143 24 : } else if (edges.size() == 1) {
144 16 : length = fabs(toPos - fromPos);
145 16 : return length / speed;
146 : } else {
147 : double cost = 0;
148 8 : int last = (int)edges.size() - 1;
149 24 : for (int i = 0; i < last; i++) {
150 : std::vector<const E*> into;
151 8 : const E* from = edges[i];
152 8 : const E* to = edges[i + 1];
153 8 : const double fp = (i == 0 ? fromPos : from->getLength() / 2);
154 8 : const double tp = (i == (last - 1) ? toPos : to->getLength() / 2);
155 : const N* node = getCommonNode(from, to);
156 8 : if (i == 0) {
157 8 : if (node == from->getToJunction()) {
158 8 : length += from->getLength() - fromPos;
159 : } else {
160 0 : length += fromPos;
161 : }
162 : } else {
163 0 : length += from->getLength();
164 : }
165 8 : if (i == (last - 1)) {
166 8 : if (node == to->getFromJunction()) {
167 8 : length += toPos;
168 : } else {
169 0 : length += to->getLength() - toPos;
170 : }
171 : }
172 8 : double time = this->compute(from, to, fp, tp, speed, msTime, node, into, true);
173 8 : if (time >= 0) {
174 8 : cost += time;
175 42 : for (const E* edge : into) {
176 34 : if (edge->isCrossing()) {
177 6 : length += edge->getLength();
178 28 : } else if (edge->isWalkingArea()) {
179 : // this is wrong because the length is path-dependent
180 12 : length += edge->getLength();
181 : }
182 : }
183 : } else {
184 0 : throw ProcessError("Could not compute cost between edge '" + from->getID() + "' and edge '" + to->getID() + "'.");
185 : }
186 : }
187 8 : return cost;
188 : }
189 : }
190 :
191 :
192 : private:
193 : const bool myAmClone;
194 : _InternalRouter* myInternalRouter;
195 : _IntermodalNetwork* myPedNet;
196 :
197 : const N* getCommonNode(const E* from, const E* to) const {
198 8 : if (from->getToJunction() == to->getFromJunction() || from->getToJunction() == to->getToJunction()) {
199 : return from->getToJunction();
200 0 : } else if (from->getFromJunction() == to->getFromJunction() || from->getFromJunction() == to->getToJunction()) {
201 : return from->getFromJunction();
202 : } else {
203 : return nullptr;
204 : }
205 : }
206 :
207 : private:
208 : /// @brief Invalidated assignment operator
209 : PedestrianRouter& operator=(const PedestrianRouter& s);
210 :
211 : };
|