Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2002-2024 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 MSRailSignal.h
15 : /// @author Melanie Weber
16 : /// @author Andreas Kendziorra
17 : /// @author Jakob Erdmann
18 : /// @date Jan 2015
19 : ///
20 : // A rail signal logic
21 : /****************************************************************************/
22 : #pragma once
23 : #include <config.h>
24 :
25 : #include <vector>
26 : #include <microsim/MSRoute.h>
27 : #include <microsim/traffic_lights/MSTrafficLightLogic.h>
28 : #include <microsim/traffic_lights/MSTLLogicControl.h>
29 :
30 :
31 : // ===========================================================================
32 : // class declarations
33 : // ===========================================================================
34 : class MSLink;
35 : class MSPhaseDefinition;
36 : class MSRailSignalConstraint;
37 :
38 :
39 : // ===========================================================================
40 : // class definitions
41 : // ===========================================================================
42 : /**
43 : * @class MSRailSignal
44 : * @brief A signal for rails
45 : */
46 : class MSRailSignal : public MSTrafficLightLogic {
47 : public:
48 : /** @brief Constructor
49 : * @param[in] tlcontrol The tls control responsible for this tls
50 : * @param[in] id This tls' id
51 : * @param[in] programID This tls' sub-id (program id)
52 : * @param[in] parameters This tls' parameters
53 : * @param[in] delay The time to wait before the first switch
54 : */
55 : MSRailSignal(MSTLLogicControl& tlcontrol,
56 : const std::string& id, const std::string& programID, SUMOTime delay,
57 : const Parameterised::Map& parameters);
58 :
59 :
60 : /** @brief Initialises the rail signal with information about adjacent rail signals
61 : * @param[in] nb The detector builder
62 : * @exception ProcessError If something fails on initialisation
63 : */
64 : void init(NLDetectorBuilder& nb) override;
65 :
66 :
67 : /// @brief Destructor
68 : ~MSRailSignal();
69 :
70 : /**@brief Sets a parameter and updates internal constants */
71 : void setParameter(const std::string& key, const std::string& value) override;
72 :
73 : /** @brief Adds a link on building
74 : * @param[in] link The controlled link
75 : * @param[in] lane The lane this link starts at
76 : * @param[in] pos The link's index (signal group) within this program
77 : */
78 : void addLink(MSLink* link, MSLane* lane, int pos) override;
79 :
80 : /// @name Handling of controlled links
81 : /// @{
82 :
83 : /** @brief Applies information about controlled links and lanes from the given logic
84 : * @param[in] logic The logic to use the information about controlled links/lanes from
85 : * @see MSTrafficLightLogic::adaptLinkInformationFrom
86 : */
87 : void adaptLinkInformationFrom(const MSTrafficLightLogic& logic) override;
88 : /// @}
89 :
90 :
91 : /// @name Switching and setting current rows
92 : /// @{
93 :
94 :
95 : /** @brief returns the state of the signal that actually required
96 : *
97 : * Returns the state of the rail signal that is actually required based on the
98 : * occupation of the adjoining blocks.
99 : *
100 : * @return The state actually required for this signal.
101 : */
102 :
103 : /// @brief updates the current phase of the signal
104 : void updateCurrentPhase();
105 :
106 : /** @brief Switches to the next phase
107 : * @return The time of the next switch (always the next step)
108 : * @see MSTrafficLightLogic::trySwitch
109 : */
110 : SUMOTime trySwitch() override;
111 :
112 : /// @}
113 :
114 :
115 : /// @name Static Information Retrieval
116 : /// @{
117 :
118 : /** @brief Returns the number of phases
119 : * @return The number of this tls program's phases (always zero)
120 : * @see MSTrafficLightLogic::getPhaseNumber
121 : */
122 : int getPhaseNumber() const override;
123 :
124 : /** @brief Returns the phases of this tls program
125 : * @return The phases of this tls program
126 : * @see MSTrafficLightLogic::getPhases
127 : */
128 : const Phases& getPhases() const override;
129 :
130 : /** @brief Returns the definition of the phase from the given position within the plan
131 : *
132 : * Returns the current phase as there does not exist a plan of the phases.
133 : *
134 : * @param[in] givenstep The index of the phase within the plan
135 : * @return The definition of the phase at the given position
136 : * @see MSTrafficLightLogic::getPhase
137 : */
138 : const MSPhaseDefinition& getPhase(int givenstep) const override;
139 :
140 : /// @brief whether the given link index ever turns 'G'
141 684 : bool getsMajorGreen(int /*linkIndex*/) const override {
142 684 : return true;
143 : }
144 : /// @}
145 :
146 :
147 : /// @name Dynamic Information Retrieval
148 : /// @{
149 :
150 : /** @brief Returns the current index within the program
151 : * @return The index of the current phase within the tls (here, always zero will be returned)
152 : * @see MSTrafficLightLogic::getCurrentPhaseIndex
153 : */
154 : int getCurrentPhaseIndex() const override;
155 :
156 : /** @brief Returns the definition of the current phase
157 : * @return The current phase
158 : */
159 : const MSPhaseDefinition& getCurrentPhaseDef() const override;
160 : /// @}
161 :
162 :
163 : /// @name Conversion between time and phase
164 : /// @{
165 :
166 : /** @brief Returns the index of the logic at the given simulation step
167 : * @return The (estimated) index of the tls at the given simulation time step (here, always zero will be returned)
168 : * @see MSTrafficLightLogic::getPhaseIndexAtTime
169 : */
170 : SUMOTime getPhaseIndexAtTime(SUMOTime simStep) const override;
171 :
172 : /** @brief Returns the position (start of a phase during a cycle) from of a given step
173 : * @param[in] index The index of the phase to return the begin of
174 : * @return The begin time of the phase (here, always zero will be returned)
175 : * @see MSTrafficLightLogic::getOffsetFromIndex
176 : */
177 : SUMOTime getOffsetFromIndex(int index) const override;
178 :
179 : /** @brief Returns the step (the phasenumber) of a given position of the cycle
180 : * @param[in] offset The offset (time) for which the according phase shall be returned
181 : * @return The according phase (here, always zero will be returned)
182 : * @see MSTrafficLightLogic::getIndexFromOffset
183 : */
184 : int getIndexFromOffset(SUMOTime offset) const override;
185 : /// @}
186 :
187 :
188 : /// @name Changing phases and phase durations
189 : /// @{
190 :
191 : /** @brief Changes the current phase and her duration
192 : * @param[in] tlcontrol The responsible traffic lights control
193 : * @param[in] simStep The current simulation step
194 : * @param[in] step Index of the phase to use
195 : * @param[in] stepDuration The left duration of the phase
196 : * @see MSTrafficLightLogic::changeStepAndDuration
197 : */
198 0 : void changeStepAndDuration(MSTLLogicControl& tlcontrol, SUMOTime simStep, int step, SUMOTime stepDuration) override {
199 : UNUSED_PARAMETER(tlcontrol);
200 : UNUSED_PARAMETER(simStep);
201 : UNUSED_PARAMETER(step);
202 : UNUSED_PARAMETER(stepDuration);
203 0 : }
204 : /// @}
205 :
206 : /// @brief return vehicles that block the intersection/rail signal for vehicles that wish to pass the given linkIndex
207 : VehicleVector getBlockingVehicles(int linkIndex) override;
208 : std::string getBlockingVehicleIDs() const;
209 :
210 : /// @brief return vehicles that approach the intersection/rail signal and are in conflict with vehicles that wish to pass the given linkIndex
211 : VehicleVector getRivalVehicles(int linkIndex) override;
212 : std::string getRivalVehicleIDs() const;
213 :
214 : /// @brief return vehicles that approach the intersection/rail signal and have priority over vehicles that wish to pass the given linkIndex
215 : VehicleVector getPriorityVehicles(int linkIndex) override;
216 : std::string getPriorityVehicleIDs() const;
217 :
218 : /// @brief return information regarding active rail signal constraints for the closest approaching vehicle
219 : std::string getConstraintInfo(int linkIndex);
220 : std::string getConstraintInfo() const;
221 :
222 : /// @brief write rail signal block output for all links and driveways
223 : void writeBlocks(OutputDevice& od) const;
224 :
225 : /// @brief register constraint for signal switching
226 : void addConstraint(const std::string& tripId, MSRailSignalConstraint* constraint);
227 :
228 : /// @name TraCI access to constraints
229 : /// @{
230 : const std::map<std::string, std::vector<MSRailSignalConstraint*> >& getConstraints() const {
231 : return myConstraints;
232 : }
233 :
234 : /// @brief remove constraint for signal switching
235 : bool removeConstraint(const std::string& tripId, MSRailSignalConstraint* constraint);
236 : void removeConstraints();
237 : /// @}
238 :
239 : /// update driveway for extended deadlock protection
240 : void updateDriveway(int numericalID);
241 :
242 : /* @brief return whether vehicle insertion must be delayed for an oncoming train
243 : * @param[in] link The rail signal link before which the vehicle is being inserted
244 : * @param[in] veh The vehicle being inserted
245 : * @param[in] brakeBeforeSignal Whether the vehicle may brake before the signal,
246 : * Returns true if the vehicle has to brake before the signal
247 : */
248 : static bool hasOncomingRailTraffic(MSLink* link, const MSVehicle* ego, bool& brakeBeforeSignal);
249 :
250 : static bool hasInsertionConstraint(MSLink* link, const MSVehicle* veh, std::string& info, bool& isInsertionOrder);
251 :
252 : static void initDriveWays(const SUMOVehicle* ego, bool update);
253 :
254 : typedef std::pair<const SUMOVehicle* const, const MSLink::ApproachingVehicleInformation> Approaching;
255 : typedef std::set<const MSLane*, ComparatorNumericalIdLess> LaneSet;
256 : typedef std::map<const MSLane*, int, ComparatorNumericalIdLess> LaneVisitedMap;
257 :
258 : /* The driveways (Fahrstrassen) for each link index
259 : * Each link index has at least one driveway
260 : * A driveway describes one possible route that passes the signal up
261 : * the next secure point
262 : * When a signal guards a switch (indirect guard) that signal stores two
263 : * or more driveways
264 : */
265 : struct DriveWay {
266 :
267 : /// @brief Constructor
268 6569 : DriveWay(bool temporary = false) :
269 6569 : myNumericalID(temporary ? -1 : myDriveWayIndex++),
270 6569 : myMaxFlankLength(0),
271 6569 : myActive(nullptr),
272 6569 : myProtectedBidi(nullptr),
273 6569 : myCoreSize(0),
274 6569 : myFoundSignal(false),
275 6569 : myFoundReversal(false)
276 6569 : {}
277 :
278 : /// @brief global driveway index
279 : int myNumericalID;
280 :
281 : /// @brief the maximum flank length searched while building this driveway
282 : double myMaxFlankLength;
283 :
284 : /// @brief whether the current signal is switched green for a train approaching this block
285 : const SUMOVehicle* myActive;
286 :
287 : /// @brief switch assumed safe from bidi-traffic
288 : const MSEdge* myProtectedBidi;
289 :
290 : /// @brief list of edges for matching against train routes
291 : std::vector<const MSEdge*> myRoute;
292 :
293 : /// @brief number of edges in myRoute where overlap with other driveways is forbidden
294 : int myCoreSize;
295 :
296 : /// @brief whether this driveway ends its forward section with a rail signal (and thus comprises a full block)
297 : bool myFoundSignal;
298 : bool myFoundReversal;
299 :
300 : /* @brief the actual driveway part up to the next railsignal (halting position)
301 : * This must be free of other trains */
302 : std::vector<const MSLane*> myForward;
303 :
304 : /* @brief the list of bidirectional edges that can enter the forward
305 : * section and which must also be free of traffic
306 : * (up to the first element that could give protection) */
307 : std::vector<const MSLane*> myBidi;
308 :
309 : /* @brief the list of bidirectional edges that can enter the forward
310 : * section and which might contain deadlock-relevant traffic */
311 : std::vector<const MSLane*> myBidiExtended;
312 :
313 : /* @brief the list of edges that merge with the forward section
314 : * (found via backward search, up to the first element that could give protection) */
315 : std::vector<const MSLane*> myFlank;
316 :
317 : /// @brief the lanes that must be clear of trains before this signal can switch to green
318 : std::vector<const MSLane*> myConflictLanes;
319 :
320 : /* @brief the list of switches that threaten the driveway and for which protection must be found
321 : */
322 : std::vector<MSLink*> myFlankSwitches;
323 :
324 : /* @brief the list of (first) switches that could give protection from oncoming/flanking vehicles
325 : * if any of them fails to do so, upstream search must be performed
326 : * until protection or conflict is found
327 : */
328 : std::vector<MSLink*> myProtectingSwitches;
329 : /// @brief subset of myProtectingSwitches that protects from oncoming trains
330 : std::vector<MSLink*> myProtectingSwitchesBidi;
331 :
332 : /* The conflict links for this block
333 : * Conflict resolution must be performed if vehicles are approaching the
334 : * current link and any of the conflict links */
335 : std::vector<MSLink*> myConflictLinks;
336 :
337 : /// @brief whether any of myConflictLanes is occupied (vehicles that are the target of a join must be ignored)
338 : bool conflictLaneOccupied(const std::string& joinVehicle = "", bool store = true, const SUMOVehicle* ego = nullptr) const;
339 :
340 : /// @brief whether any of myBidiExtended is occupied by a vehicle that targets myBidi
341 : bool deadlockLaneOccupied(bool store = true) const;
342 :
343 : /// @brief attempt reserve this driveway for the given vehicle
344 : bool reserve(const Approaching& closest, MSEdgeVector& occupied);
345 :
346 : /// @brief Whether the approaching vehicle is prevent from driving by another vehicle approaching the given link
347 : bool hasLinkConflict(const Approaching& closest, MSLink* foeLink) const;
348 :
349 : /// @brief Whether veh must yield to the foe train
350 : static bool mustYield(const Approaching& veh, const Approaching& foe);
351 :
352 : /// @brief Whether any of the conflict links have approaching vehicles
353 : bool conflictLinkApproached() const;
354 :
355 : /// @brief find protection for the given vehicle starting at a switch
356 : bool findProtection(const Approaching& veh, MSLink* link) const;
357 :
358 : /// @brief Wether this driveway (route) overlaps with the given one
359 : bool overlap(const DriveWay& other) const;
360 :
361 : /// @brief Wether there is a flank conflict with the given driveway
362 : bool flankConflict(const DriveWay& other) const;
363 :
364 : /// @brief Write block items for this driveway
365 : void writeBlocks(OutputDevice& od) const;
366 :
367 : /* @brief determine route that identifies this driveway (a subset of the
368 : * vehicle route)
369 : * collects:
370 : * myRoute
371 : * myForward
372 : * myBidi
373 : * myProtectedBidi
374 : *
375 : * returns edge that is assumed to safe from oncoming-deadlock or nullptr
376 : */
377 : void buildRoute(MSLink* origin, double length, MSRouteIterator next, MSRouteIterator end, LaneVisitedMap& visited);
378 :
379 : /* @brief find switches that threaten this driveway
380 : * @param[out] flankSwitches collect the switches
381 : */
382 : void checkFlanks(const MSLink* originLink, const std::vector<const MSLane*>& lanes, const LaneVisitedMap& visited, bool allFoes, std::vector<MSLink*>& flankSwitches) const;
383 :
384 : /* @brief find links that cross the driveway without entering it
385 : * @param[out] flankSwitches collect the switches
386 : */
387 : void checkCrossingFlanks(MSLink* dwLink, const LaneVisitedMap& visited, std::vector<MSLink*>& flankSwitches) const;
388 :
389 : /* @brief find upstream protection from the given link
390 : * @param[out] flank: the stored flank lanes
391 : */
392 : void findFlankProtection(MSLink* link, double length, LaneVisitedMap& visited, MSLink* origLink, std::vector<const MSLane*>& flank);
393 : };
394 :
395 : /* @brief retrieve driveway with the given numerical id
396 : * @note: throws exception if the driveway does not exist at this rail signal */
397 : const DriveWay& retrieveDriveWay(int numericalID) const;
398 :
399 : /// @brief get the closest vehicle approaching the given link
400 : static Approaching getClosest(MSLink* link);
401 :
402 : protected:
403 : /// @brief whether the given vehicle is free to drive
404 : bool constraintsAllow(const SUMOVehicle* veh) const;
405 :
406 : protected:
407 :
408 : /* The driveways for each link
409 : */
410 13319 : struct LinkInfo {
411 : /// @brief constructor
412 : LinkInfo(MSLink* link);
413 :
414 : MSLink* myLink;
415 :
416 : /// @brief all driveways immediately following this link
417 : std::vector<DriveWay> myDriveways;
418 :
419 : /// @brief return id for this railsignal-link
420 : std::string getID() const;
421 :
422 : /// @brief retrieve an existing Driveway or construct a new driveway based on the vehicles route
423 : DriveWay& getDriveWay(const SUMOVehicle*);
424 :
425 : /// @brief construct a new driveway by searching along the given route until all block structures are found
426 : DriveWay buildDriveWay(MSRouteIterator first, MSRouteIterator end);
427 :
428 : /// @brief try rerouting vehicle if reservation failed
429 : void reroute(SUMOVehicle* veh, const MSEdgeVector& occupied);
430 :
431 : /// @brief init LinkInfo
432 : void reset();
433 :
434 : SUMOTime myLastRerouteTime;
435 : SUMOVehicle* myLastRerouteVehicle;
436 : };
437 :
438 : /// @brief data storage for every link at this node (more than one when directly guarding a switch)
439 : std::vector<LinkInfo> myLinkInfos;
440 :
441 : /// @brief return logicID_linkIndex
442 : static std::string getTLLinkID(MSLink* link);
443 :
444 : /// @brief return junctionID_junctionLinkIndex
445 : static std::string getJunctionLinkID(MSLink* link);
446 :
447 : /// @brief return logicID_linkIndex in a way that allows clicking in sumo-gui
448 : static std::string getClickableTLLinkID(MSLink* link);
449 :
450 : /// @brief print link descriptions
451 : static std::string describeLinks(std::vector<MSLink*> links);
452 :
453 : /// @brief print link descriptions
454 : static std::string formatVisitedMap(const LaneVisitedMap& visited);
455 :
456 : /// @brief append to map by map index and avoid undefined behavior
457 : static void appendMapIndex(LaneVisitedMap& map, const MSLane* lane);
458 :
459 : protected:
460 :
461 : /** @brief The list of phases this logic uses
462 : *
463 : * This vector is always empty and only constructed because the superclass MSTrafficLightLogic requires it.
464 : */
465 : Phases myPhases;
466 :
467 : /// @brief The current phase
468 : MSPhaseDefinition myCurrentPhase;
469 :
470 : /// @brief MSTrafficLightLogic requires that the phase index changes whenever signals change their state
471 : int myPhaseIndex;
472 :
473 : /// @brief whether the signal is in moving block mode (only protects from oncoming and flanking trains)
474 : bool myMovingBlock;
475 :
476 : /// @brief map from tripId to constraint list
477 : std::map<std::string, std::vector<MSRailSignalConstraint*> > myConstraints;
478 :
479 : static int myNumWarnings;
480 :
481 : static int myDriveWayIndex;
482 :
483 : protected:
484 : /// @brief update vehicle lists for traci calls
485 : void storeTraCIVehicles(int linkIndex);
486 :
487 : /// @name traci result storage
488 : //@{
489 : static bool myStoreVehicles;
490 : static VehicleVector myBlockingVehicles;
491 : static VehicleVector myRivalVehicles;
492 : static VehicleVector myPriorityVehicles;
493 : static std::string myConstraintInfo;
494 : //@}
495 :
496 :
497 : };
|