Eclipse SUMO - Simulation of Urban MObility
RailEdge.h
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2022 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 // ===========================================================================
37 template<class E, class V>
38 class RailEdge {
39 public:
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()) {
58  myViaSuccessors.push_back(std::make_pair(turnEnd->getRailwayRoutingEdge(), nullptr));
59  }
60 
61  void update(double maxTrainLength, const std::vector<const E*>& replacementEdges) {
62  if (maxTrainLength > myMaxLength) {
63  myMaxLength = maxTrainLength;
64  myReplacementEdges = replacementEdges;
65 #ifdef RailEdge_DEBUG_INIT
66  std::cout << " update RailEdge " << getID() << " myMaxLength=" << myMaxLength << " repl=" << toString(myReplacementEdges) << "\n";
67 #endif
68  }
69  }
70 
71  void addVirtualTurns(const E* forward, const E* backward,
72  std::vector<_RailEdge*>& railEdges, int& numericalID, double dist,
73  double maxTrainLength, const std::vector<const E*>& replacementEdges) {
74  // search backwards until dist and add virtual turnaround edges with
75  // replacement edges up to the real turnaround
76 #ifdef RailEdge_DEBUG_INIT
77  std::cout << "addVirtualTurns forward=" << forward->getID() << " backward=" << backward->getID() << " dist=" << dist
78  << " maxLength=" << maxTrainLength << " repl=" << toString(replacementEdges) << "\n";
79 #endif
80  if (dist <= 0) {
81  return;
82  }
83  for (const E* prev : forward->getPredecessors()) {
84  if (prev == backward) {
85  continue;
86  }
87  const E* bidi = prev->getBidiEdge();
88  if (backward->isConnectedTo(*bidi, SVC_IGNORING)) {
89  _RailEdge* prevRailEdge = prev->getRailwayRoutingEdge();
90  if (prevRailEdge->myTurnaround == nullptr) {
91  prevRailEdge->myTurnaround = new _RailEdge(prev, bidi, numericalID++);
92  prevRailEdge->myViaSuccessors.push_back(std::make_pair(prevRailEdge->myTurnaround, nullptr));
93  railEdges.push_back(prevRailEdge->myTurnaround);
94 #ifdef RailEdge_DEBUG_INIT
95  std::cout << " RailEdge " << prevRailEdge->getID() << " virtual turnaround " << prevRailEdge->myTurnaround->getID() << "\n";
96 #endif
97  }
98  /*
99  // doesn't compile though I don't know why
100  auto itFound = std::find(replacementEdges.begin(), replacementEdges.end(), prev);
101  bool notFound = itFound == replacementEdges.end();
102  */
103  bool notFound = true;
104  for (const E* r : replacementEdges) {
105  if (r == prev) {
106  notFound = false;
107  break;
108  }
109  }
110 
111  if (notFound) {
112  // prevent loops in replacementEdges
113  prevRailEdge->myTurnaround->update(prev->getLength() + maxTrainLength - REVERSAL_SLACK, replacementEdges);
114  std::vector<const E*> replacementEdges2;
115  replacementEdges2.push_back(prev);
116  replacementEdges2.insert(replacementEdges2.end(), replacementEdges.begin(), replacementEdges.end());
117  addVirtualTurns(prev, bidi, railEdges, numericalID, dist - prev->getLength(),
118  maxTrainLength + prev->getLength(), replacementEdges2);
119  }
120  }
121  }
122  }
123 
124  void init(std::vector<_RailEdge*>& railEdges, int& numericalID, double maxTrainLength) {
125  // replace turnaround-via with an explicit RailEdge that checks length
126  for (const auto& viaPair : myOriginal->getViaSuccessors()) {
127  if (viaPair.first == myOriginal->getBidiEdge()) {
128  // direction reversal
129  if (myTurnaround == nullptr) {
130  myTurnaround = new _RailEdge(myOriginal, viaPair.first, numericalID++);
131  myViaSuccessors.push_back(std::make_pair(myTurnaround, nullptr));
132  railEdges.push_back(myTurnaround);
133 #ifdef RailEdge_DEBUG_INIT
134  std::cout << " added new turnaround " << myTurnaround->getID() << "\n";
135 #endif
136  }
137 #ifdef RailEdge_DEBUG_INIT
138  std::cout << "RailEdge " << getID() << " actual turnaround " << myTurnaround->getID() << "\n";
139 #endif
140  myTurnaround->myIsVirtual = false;
141  addVirtualTurns(myOriginal, viaPair.first, railEdges, numericalID,
142  maxTrainLength - getLength(), getLength(), std::vector<const E*> {myOriginal});
143  } else {
144  myViaSuccessors.push_back(std::make_pair(viaPair.first->getRailwayRoutingEdge(),
145  viaPair.second == nullptr ? nullptr : viaPair.second->getRailwayRoutingEdge()));
146  }
147  }
148 #ifdef RailEdge_DEBUG_SUCCESSORS
149  std::cout << "RailEdge " << getID() << " successors=" << myViaSuccessors.size() << " orig=" << myOriginal->getViaSuccessors().size() << "\n";
150  for (const auto& viaPair : myViaSuccessors) {
151  std::cout << " " << viaPair.first->getID() << "\n";
152  }
153 #endif
154  }
155 
157  inline int getNumericalID() const {
158  return myNumericalID;
159  }
160 
162  const E* getOriginal() const {
163  return myOriginal;
164  }
165 
169  const std::string& getID() const {
170  return myOriginal != nullptr ? myOriginal->getID() : myID;
171  }
172 
173  void insertOriginalEdges(double length, std::vector<const E*>& into) const {
174  if (myOriginal != nullptr) {
175  into.push_back(myOriginal);
176  } else {
177  double seen = myStartLength;
178  int nPushed = 0;
179  if (seen >= length && !myIsVirtual) {
180  return;
181  }
182  // we need to find a replacement edge that has a real turn
183  for (const E* edge : myReplacementEdges) {
184  into.push_back(edge);
185  nPushed++;
186  seen += edge->getLength();
187  if (seen >= length && edge->isConnectedTo(*edge->getBidiEdge(), SVC_IGNORING)) {
188  break;
189  }
190  //std::cout << "insertOriginalEdges length=" << length << " seen=" << seen << " into=" << toString(into) << "\n";
191  }
192  const int last = (int)into.size() - 1;
193  for (int i = 0; i < nPushed; i++) {
194  into.push_back(into[last - i]->getBidiEdge());
195  }
196  }
197  }
198 
202  double getLength() const {
203  return myOriginal == nullptr ? 0 : myOriginal->getLength();
204  }
205 
206  //const RailEdge* getBidiEdge() const {
207  // return myOriginal->getBidiEdge()->getRailwayRoutingEdge();
208  //}
209 
210  bool isInternal() const {
211  return myOriginal->isInternal();
212  }
213 
214  inline bool prohibits(const V* const vehicle) const {
215 #ifdef RailEdge_DEBUG_TURNS
216  if (myOriginal == nullptr && RailEdge_DEBUG_COND(vehicle)) {
217  std::cout << getID() << " maxLength=" << myMaxLength << " veh=" << vehicle->getID() << " length=" << vehicle->getLength() << "\n";
218  }
219 #endif
220  return vehicle->getLength() > myMaxLength || (myOriginal != nullptr && myOriginal->prohibits(vehicle));
221  }
222 
223  inline bool restricts(const V* const vehicle) const {
224  return myOriginal != nullptr && myOriginal->restricts(vehicle);
225  }
226 
228  if (vClass == SVC_IGNORING || myOriginal == nullptr || myOriginal->isTazConnector()) { // || !MSNet::getInstance()->hasPermissions()) {
229  return myViaSuccessors;
230  }
231 #ifdef HAVE_FOX
232  FXMutexLock lock(mySuccessorMutex);
233 #endif
234  auto i = myClassesViaSuccessorMap.find(vClass);
235  if (i != myClassesViaSuccessorMap.end()) {
236  // can use cached value
237  return i->second;
238  }
239  // instantiate vector
241  // this vClass is requested for the first time. rebuild all successors
242  for (const auto& viaPair : myViaSuccessors) {
243  if (viaPair.first->myOriginal == nullptr
244  || viaPair.first->myOriginal->isTazConnector()
245  || myOriginal->isConnectedTo(*viaPair.first->myOriginal, vClass)) {
246  result.push_back(viaPair);
247  }
248  }
249  return result;
250  }
251 
252  bool isVirtual() const {
253  return myIsVirtual;
254  }
255 
256 private:
257  const int myNumericalID;
258  const std::string myID;
259  const E* myOriginal;
262 
264  std::vector<const E*> myReplacementEdges;
265 
267  double myMaxLength = std::numeric_limits<double>::max();
269  double myStartLength = 0;
270 
272  mutable std::map<SUMOVehicleClass, ConstEdgePairVector> myClassesViaSuccessorMap;
273 
275 
276 #ifdef HAVE_FOX
278  mutable FXMutex mySuccessorMutex;
279 #endif
280 
281 };
#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
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
the edge type representing backward edges
Definition: RailEdge.h:38
RailEdge(const E *orig)
Definition: RailEdge.h:43
const std::string myID
Definition: RailEdge.h:258
double myStartLength
length of the edge where this turn starts
Definition: RailEdge.h:269
void insertOriginalEdges(double length, std::vector< const E * > &into) const
Definition: RailEdge.h:173
bool myIsVirtual
Definition: RailEdge.h:261
int getNumericalID() const
Returns the index (numeric id) of the edge.
Definition: RailEdge.h:157
const E * getOriginal() const
Returns the original edge.
Definition: RailEdge.h:162
ConstEdgePairVector myViaSuccessors
Definition: RailEdge.h:274
std::vector< const E * > myReplacementEdges
actual edges to return when passing this (turnaround) edge - only forward
Definition: RailEdge.h:264
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:71
bool isVirtual() const
Definition: RailEdge.h:252
double getLength() const
Returns the length of the edge.
Definition: RailEdge.h:202
const E * myOriginal
Definition: RailEdge.h:259
const int myNumericalID
Definition: RailEdge.h:257
bool isInternal() const
Definition: RailEdge.h:210
double myMaxLength
maximum train length for passing this (turnaround) edge
Definition: RailEdge.h:267
bool prohibits(const V *const vehicle) const
Definition: RailEdge.h:214
RailEdge< E, V > _RailEdge
Definition: RailEdge.h:40
bool restricts(const V *const vehicle) const
Definition: RailEdge.h:223
std::map< SUMOVehicleClass, ConstEdgePairVector > myClassesViaSuccessorMap
The successors available for a given vClass.
Definition: RailEdge.h:272
std::vector< std::pair< const _RailEdge *, const _RailEdge * > > ConstEdgePairVector
Definition: RailEdge.h:41
void init(std::vector< _RailEdge * > &railEdges, int &numericalID, double maxTrainLength)
Definition: RailEdge.h:124
const ConstEdgePairVector & getViaSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Definition: RailEdge.h:227
_RailEdge * myTurnaround
Definition: RailEdge.h:260
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:61
const std::string & getID() const
Returns the id of the edge.
Definition: RailEdge.h:169