Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
RailEdge.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/****************************************************************************/
18// The RailEdge is a wrapper around a ROEdge or a MSEdge used for railway routing
19/****************************************************************************/
20#pragma once
21#include <config.h>
22#include <cassert>
23
24//#define RailEdge_DEBUG_TURNS
25//#define RailEdge_DEBUG_INIT
26//#define RailEdge_DEBUG_SUCCESSORS
27#define RailEdge_DEBUGID ""
28//#define RailEdge_DEBUG_COND(obj) ((obj != 0 && (obj)->getID() == RailEdge_DEBUGID))
29#define RailEdge_DEBUG_COND(obj) (true)
30
31#define REVERSAL_SLACK (POSITION_EPS + NUMERICAL_EPS)
32
33// ===========================================================================
34// class definitions
35// ===========================================================================
37template<class E, class V>
38class RailEdge {
39public:
41 typedef std::vector<std::pair<const _RailEdge*, const _RailEdge*> > ConstEdgePairVector;
42
43 RailEdge(const E* orig) :
45 myOriginal(orig),
46 myTurnaround(nullptr),
47 myIsVirtual(true)
48 { }
49
50 RailEdge(const E* turnStart, const E* turnEnd, int numericalID) :
51 myNumericalID(numericalID),
52 myID("TrainReversal!" + turnStart->getID() + "->" + turnEnd->getID()),
53 myOriginal(nullptr),
54 myTurnaround(nullptr),
55 myIsVirtual(true),
56 myMaxLength(turnStart->getLength() - REVERSAL_SLACK),
57 myStartLength(turnStart->getLength() - REVERSAL_SLACK) {
58 myViaSuccessors.push_back(std::make_pair(turnEnd->getRailwayRoutingEdge(), nullptr));
59 }
60
62 virtual ~RailEdge() {
63 delete myTurnaround;
64 }
65
66 void update(double maxTrainLength, const std::vector<const E*>& replacementEdges) {
67 if (maxTrainLength > myMaxLength) {
68 myMaxLength = maxTrainLength;
69 myReplacementEdges = replacementEdges;
70#ifdef RailEdge_DEBUG_INIT
71 std::cout << " update RailEdge " << getID() << " myMaxLength=" << myMaxLength << " repl=" << toString(myReplacementEdges) << "\n";
72#endif
73 }
74 }
75
76 void addVirtualTurns(const E* forward, const E* backward,
77 std::vector<_RailEdge*>& railEdges, int& numericalID, double dist,
78 double maxTrainLength, const std::vector<const E*>& replacementEdges) {
79 // search backwards until dist and add virtual turnaround edges with
80 // replacement edges up to the real turnaround
81#ifdef RailEdge_DEBUG_INIT
82 std::cout << "addVirtualTurns forward=" << forward->getID() << " backward=" << backward->getID() << " dist=" << dist
83 << " maxLength=" << maxTrainLength << " repl=" << toString(replacementEdges) << "\n";
84#endif
85 if (dist <= 0) {
86 return;
87 }
88 for (const E* prev : forward->getPredecessors()) {
89 if (prev == backward) {
90 continue;
91 }
92 const E* bidi = prev->getBidiEdge();
93 if (bidi != nullptr && backward->isConnectedTo(*bidi, SVC_IGNORING)) {
94 _RailEdge* prevRailEdge = prev->getRailwayRoutingEdge();
95 if (prevRailEdge->myTurnaround == nullptr) {
96 prevRailEdge->myTurnaround = new _RailEdge(prev, bidi, numericalID++);
97 prevRailEdge->myViaSuccessors.push_back(std::make_pair(prevRailEdge->myTurnaround, nullptr));
98 railEdges.push_back(prevRailEdge->myTurnaround);
99#ifdef RailEdge_DEBUG_INIT
100 std::cout << " RailEdge " << prevRailEdge->getID() << " virtual turnaround " << prevRailEdge->myTurnaround->getID() << "\n";
101#endif
102 }
103 /*
104 // doesn't compile though I don't know why
105 auto itFound = std::find(replacementEdges.begin(), replacementEdges.end(), prev);
106 bool notFound = itFound == replacementEdges.end();
107 */
108 bool notFound = true;
109 for (const E* r : replacementEdges) {
110 if (r == prev) {
111 notFound = false;
112 break;
113 }
114 }
115
116 if (notFound) {
117 // prevent loops in replacementEdges
118 prevRailEdge->myTurnaround->update(prev->getLength() + maxTrainLength - REVERSAL_SLACK, replacementEdges);
119 std::vector<const E*> replacementEdges2;
120 replacementEdges2.push_back(prev);
121 replacementEdges2.insert(replacementEdges2.end(), replacementEdges.begin(), replacementEdges.end());
122 addVirtualTurns(prev, bidi, railEdges, numericalID, dist - prev->getLength(),
123 maxTrainLength + prev->getLength(), replacementEdges2);
124 }
125 }
126 }
127 }
128
129 void init(std::vector<_RailEdge*>& railEdges, int& numericalID, double maxTrainLength, bool permitReversal) {
130 // replace turnaround-via with an explicit RailEdge that checks length
131 for (const auto& viaPair : myOriginal->getViaSuccessors()) {
132 if (viaPair.first == myOriginal->getBidiEdge()) {
133 if (!permitReversal) {
134 continue;
135 }
136 // direction reversal
137 if (myTurnaround == nullptr) {
138 myTurnaround = new _RailEdge(myOriginal, viaPair.first, numericalID++);
139 myViaSuccessors.push_back(std::make_pair(myTurnaround, nullptr));
140 railEdges.push_back(myTurnaround);
141#ifdef RailEdge_DEBUG_INIT
142 std::cout << " added new turnaround " << myTurnaround->getID() << "\n";
143#endif
144 }
145#ifdef RailEdge_DEBUG_INIT
146 std::cout << "RailEdge " << getID() << " actual turnaround " << myTurnaround->getID() << "\n";
147#endif
148 myTurnaround->myIsVirtual = false;
149 // ensure at least one virtual turnaround (at the start of the
150 // edge) to avoid driving up to the end of long edges
151 const double initialDist = MAX2(maxTrainLength - getLength(), POSITION_EPS);
152 addVirtualTurns(myOriginal, viaPair.first, railEdges, numericalID,
153 initialDist, getLength(), std::vector<const E*> {myOriginal});
154 } else {
155 myViaSuccessors.push_back(std::make_pair(viaPair.first->getRailwayRoutingEdge(),
156 viaPair.second == nullptr ? nullptr : viaPair.second->getRailwayRoutingEdge()));
157 }
158 }
159#ifdef RailEdge_DEBUG_SUCCESSORS
160 std::cout << "RailEdge " << getID() << " successors=" << myViaSuccessors.size() << " orig=" << myOriginal->getViaSuccessors().size() << "\n";
161 for (const auto& viaPair : myViaSuccessors) {
162 std::cout << " " << viaPair.first->getID() << "\n";
163 }
164#endif
165 }
166
168 inline int getNumericalID() const {
169 return myNumericalID;
170 }
171
173 const E* getOriginal() const {
174 return myOriginal;
175 }
176
180 const std::string& getID() const {
181 return myOriginal != nullptr ? myOriginal->getID() : myID;
182 }
183
184 void insertOriginalEdges(double length, std::vector<const E*>& into) const {
185 if (myOriginal != nullptr) {
186 into.push_back(myOriginal);
187 } else {
188 double seen = myStartLength;
189 int nPushed = 0;
190 //std::cout << "insertOriginalEdges e=" << getID() << " length=" << length << " seen=" << seen << " into=" << toString(into) << "\n";
191 if (seen >= length && !myIsVirtual) {
192 return;
193 }
194 // we need to find a replacement edge that has a real turn
195 for (const E* edge : myReplacementEdges) {
196 into.push_back(edge);
197 nPushed++;
198 seen += edge->getLength() - REVERSAL_SLACK;
199 //std::cout << "insertOriginalEdges e=" << getID() << " length=" << length << " seen=" << seen << " into=" << toString(into) << "\n";
200 if (seen >= length && edge->isConnectedTo(*edge->getBidiEdge(), SVC_IGNORING)) {
201 break;
202 }
203 }
204 const int last = (int)into.size() - 1;
205 for (int i = 0; i < nPushed; i++) {
206 into.push_back(into[last - i]->getBidiEdge());
207 }
208 }
209 }
210
214 double getLength() const {
215 return myOriginal == nullptr ? 0 : myOriginal->getLength();
216 }
217
218 //const RailEdge* getBidiEdge() const {
219 // return myOriginal->getBidiEdge()->getRailwayRoutingEdge();
220 //}
221
222 bool isInternal() const {
223 return myOriginal->isInternal();
224 }
225
226 inline bool prohibits(const V* const vehicle) const {
227#ifdef RailEdge_DEBUG_TURNS
228 if (myOriginal == nullptr && RailEdge_DEBUG_COND(vehicle)) {
229 std::cout << getID() << " maxLength=" << myMaxLength << " veh=" << vehicle->getID() << " length=" << vehicle->getLength() << "\n";
230 }
231#endif
232 return vehicle->getLength() > myMaxLength || (myOriginal != nullptr && myOriginal->prohibits(vehicle));
233 }
234
235 inline bool restricts(const V* const vehicle) const {
236 return myOriginal != nullptr && myOriginal->restricts(vehicle);
237 }
238
239 const ConstEdgePairVector& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING, bool ignoreTransientPermissions = false) const {
240 if (vClass == SVC_IGNORING || myOriginal == nullptr || myOriginal->isTazConnector()) { // || !MSNet::getInstance()->hasPermissions()) {
241 return myViaSuccessors;
242 }
243#ifdef HAVE_FOX
244 FXMutexLock lock(mySuccessorMutex);
245#endif
246 auto i = myClassesViaSuccessorMap.find(vClass);
247 if (i != myClassesViaSuccessorMap.end()) {
248 // can use cached value
249 return i->second;
250 }
251 // instantiate vector
253 // this vClass is requested for the first time. rebuild all successors
254 for (const auto& viaPair : myViaSuccessors) {
255 if (viaPair.first->myOriginal == nullptr
256 || viaPair.first->myOriginal->isTazConnector()
257 || myOriginal->isConnectedTo(*viaPair.first->myOriginal, vClass, ignoreTransientPermissions)) {
258 result.push_back(viaPair);
259 }
260 }
261 return result;
262 }
263
264 bool isVirtual() const {
265 return myIsVirtual;
266 }
267
268private:
269 const int myNumericalID;
270 const std::string myID;
271 const E* myOriginal;
274
276 std::vector<const E*> myReplacementEdges;
277
279 double myMaxLength = std::numeric_limits<double>::max();
281 double myStartLength = 0;
282
284 mutable std::map<SUMOVehicleClass, ConstEdgePairVector> myClassesViaSuccessorMap;
285
287
288#ifdef HAVE_FOX
290 mutable FXMutex mySuccessorMutex;
291#endif
292
293};
#define REVERSAL_SLACK
Definition RailEdge.h:31
#define RailEdge_DEBUG_COND(obj)
Definition RailEdge.h:29
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_IGNORING
vehicles ignoring classes
T MAX2(T a, T b)
Definition StdDefs.h:86
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
the edge type representing backward edges
Definition RailEdge.h:38
void init(std::vector< _RailEdge * > &railEdges, int &numericalID, double maxTrainLength, bool permitReversal)
Definition RailEdge.h:129
RailEdge(const E *orig)
Definition RailEdge.h:43
const std::string myID
Definition RailEdge.h:270
double myStartLength
length of the edge where this turn starts
Definition RailEdge.h:281
void insertOriginalEdges(double length, std::vector< const E * > &into) const
Definition RailEdge.h:184
bool myIsVirtual
Definition RailEdge.h:273
int getNumericalID() const
Returns the index (numeric id) of the edge.
Definition RailEdge.h:168
ConstEdgePairVector myViaSuccessors
Definition RailEdge.h:286
const std::string & getID() const
Returns the id of the edge.
Definition RailEdge.h:180
std::vector< const E * > myReplacementEdges
actual edges to return when passing this (turnaround) edge - only forward
Definition RailEdge.h:276
void addVirtualTurns(const E *forward, const E *backward, std::vector< _RailEdge * > &railEdges, int &numericalID, double dist, double maxTrainLength, const std::vector< const E * > &replacementEdges)
Definition RailEdge.h:76
bool isVirtual() const
Definition RailEdge.h:264
double getLength() const
Returns the length of the edge.
Definition RailEdge.h:214
virtual ~RailEdge()
Destructor.
Definition RailEdge.h:62
const E * getOriginal() const
Returns the original edge.
Definition RailEdge.h:173
const E * myOriginal
Definition RailEdge.h:271
const ConstEdgePairVector & getViaSuccessors(SUMOVehicleClass vClass=SVC_IGNORING, bool ignoreTransientPermissions=false) const
Definition RailEdge.h:239
const int myNumericalID
Definition RailEdge.h:269
bool isInternal() const
Definition RailEdge.h:222
double myMaxLength
maximum train length for passing this (turnaround) edge
Definition RailEdge.h:279
bool prohibits(const V *const vehicle) const
Definition RailEdge.h:226
RailEdge< E, V > _RailEdge
Definition RailEdge.h:40
bool restricts(const V *const vehicle) const
Definition RailEdge.h:235
std::map< SUMOVehicleClass, ConstEdgePairVector > myClassesViaSuccessorMap
The successors available for a given vClass.
Definition RailEdge.h:284
std::vector< std::pair< const _RailEdge *, const _RailEdge * > > ConstEdgePairVector
Definition RailEdge.h:41
_RailEdge * myTurnaround
Definition RailEdge.h:272
RailEdge(const E *turnStart, const E *turnEnd, int numericalID)
Definition RailEdge.h:50
void update(double maxTrainLength, const std::vector< const E * > &replacementEdges)
Definition RailEdge.h:66