Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-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 MSRailCrossing.cpp
15 : /// @author Jakob Erdmann
16 : /// @author Erik Tunsch
17 : /// @date Dez 2015
18 : ///
19 : // A rail signal logic
20 : /****************************************************************************/
21 : #include <config.h>
22 :
23 : #include <cassert>
24 : #include <utility>
25 : #include <vector>
26 : #include <bitset>
27 : #include <utils/common/StringUtils.h>
28 : #include <microsim/MSEventControl.h>
29 : #include <microsim/MSNet.h>
30 : #include <microsim/MSEdge.h>
31 : #include "MSTrafficLightLogic.h"
32 : #include "MSRailCrossing.h"
33 : #include <microsim/MSLane.h>
34 : #include "MSPhaseDefinition.h"
35 : #include "MSTLLogicControl.h"
36 :
37 :
38 : // ===========================================================================
39 : // method definitions
40 : // ===========================================================================
41 133 : MSRailCrossing::MSRailCrossing(MSTLLogicControl& tlcontrol,
42 : const std::string& id, const std::string& programID, SUMOTime delay,
43 133 : const Parameterised::Map& parameters) :
44 133 : MSSimpleTrafficLightLogic(tlcontrol, id, programID, 0, TrafficLightType::RAIL_CROSSING, Phases(), 0, delay, parameters) {
45 : // dummy phase, used to avoid crashing in MSTrafficLightLogic::setTrafficLightSignals()
46 399 : myPhases.push_back(new MSPhaseDefinition(1, std::string(SUMO_MAX_CONNECTIONS, 'X')));
47 133 : myDefaultCycleTime = 1;
48 133 : }
49 :
50 :
51 266 : MSRailCrossing::~MSRailCrossing() {}
52 :
53 :
54 : void
55 133 : MSRailCrossing::init(NLDetectorBuilder&) {
56 133 : const Parameterised::Map test = getParametersMap();
57 266 : myTimeGap = string2time(getParameter("time-gap", "15"));
58 : //use time-gap by default
59 266 : mySpaceGap = StringUtils::toDouble(getParameter("space-gap", "-1"));
60 266 : myMinGreenTime = string2time(getParameter("min-green", "5"));
61 266 : myOpeningDelay = string2time(getParameter("opening-delay", "3"));
62 266 : myOpeningTime = string2time(getParameter("opening-time", "3")); // red-yellow while opening
63 : /// XXX compute reasonable time depending on link length
64 266 : myYellowTime = string2time(getParameter("yellow-time", "5"));
65 133 : delete myPhases.front();
66 : myPhases.clear();
67 399 : myPhases.push_back(new MSPhaseDefinition(1, std::string(myLinks.size(), LINKSTATE_TL_GREEN_MAJOR)));
68 399 : myPhases.push_back(new MSPhaseDefinition(myYellowTime, std::string(myLinks.size(), LINKSTATE_TL_YELLOW_MINOR)));
69 399 : myPhases.push_back(new MSPhaseDefinition(1, std::string(myLinks.size(), LINKSTATE_TL_RED)));
70 399 : myPhases.push_back(new MSPhaseDefinition(myOpeningTime, std::string(myLinks.size(), LINKSTATE_TL_REDYELLOW)));
71 : // init phases
72 133 : updateCurrentPhase();
73 133 : setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
74 133 : myNumLinks = (int)myLinks.size();
75 133 : }
76 :
77 :
78 : void
79 36 : MSRailCrossing::setParameter(const std::string& key, const std::string& value) {
80 : // some pre-defined parameters can be updated at runtime
81 36 : if (key == "time-gap") {
82 12 : myTimeGap = string2time(value);
83 24 : } else if (key == "space-gap") {
84 6 : mySpaceGap = StringUtils::toDouble(value);
85 18 : } else if (key == "min-green") {
86 0 : myMinGreenTime = string2time(value);
87 18 : } else if (key == "opening-delay") {
88 6 : myOpeningDelay = string2time(value);
89 12 : } else if (key == "opening-time") {
90 6 : myOpeningTime = string2time(value); // TODO update phases
91 6 : } else if (key == "yellow-time") {
92 6 : myYellowTime = string2time(value); // TODO update phases
93 : }
94 36 : Parameterised::setParameter(key, value);
95 36 : }
96 :
97 :
98 : // ----------- Handling of controlled links
99 : void
100 0 : MSRailCrossing::adaptLinkInformationFrom(const MSTrafficLightLogic& logic) {
101 0 : MSTrafficLightLogic::adaptLinkInformationFrom(logic);
102 0 : updateCurrentPhase();
103 0 : }
104 :
105 :
106 : // ------------ Switching and setting current rows
107 : SUMOTime
108 200190 : MSRailCrossing::trySwitch() {
109 200190 : const int oldStep = myStep;
110 200190 : SUMOTime nextTry = updateCurrentPhase();
111 : //if (getID() == "cluster_1088529493_1260626727") std::cout << " myStep=" << myStep << " nextTry=" << nextTry << "\n";
112 200190 : if (myStep != oldStep) {
113 4484 : myPhases[myStep]->myLastSwitch = MSNet::getInstance()->getCurrentTimeStep();
114 : }
115 200190 : return nextTry;
116 : }
117 :
118 :
119 : SUMOTime
120 200323 : MSRailCrossing::updateCurrentPhase() {
121 200323 : const SUMOTime now = MSNet::getInstance()->getCurrentTimeStep();
122 : SUMOTime stayRedUntil = now;
123 : // check rail links for approaching foes to determine whether and how long
124 : // the crossing must remain closed
125 586090 : for (const MSLink* const link : myIncomingRailLinks) {
126 409514 : for (const auto& it_avi : link->getApproaching()) {
127 : const MSLink::ApproachingVehicleInformation& avi = it_avi.second;
128 23747 : if (avi.arrivalTime - myYellowTime - now < myTimeGap) {
129 2333 : stayRedUntil = MAX2(stayRedUntil, avi.leavingTime + myOpeningDelay);
130 : }
131 23747 : if (mySpaceGap >= 0 && avi.dist < mySpaceGap) {
132 : // TODO maybe check the incoming lanes because stopped vehicles do not register at the oncoming junction
133 244 : stayRedUntil = MAX2(stayRedUntil, avi.leavingTime + myOpeningDelay);
134 : }
135 : }
136 385767 : if (link->getViaLane() != nullptr && link->getViaLane()->getVehicleNumberWithPartials() > 0) {
137 : // do not open if there is still a train on the crossing
138 166 : stayRedUntil = MAX2(stayRedUntil, now + DELTA_T + myOpeningDelay);
139 : }
140 : }
141 : //if (getID() == "cluster_1088529493_1260626727") std::cout << SIMTIME << " stayRedUntil=" << stayRedUntil;
142 200323 : const SUMOTime wait = stayRedUntil - now;
143 :
144 200323 : if (myStep == 0) {
145 : // 'G': check whether the crossing can stay open
146 196422 : if (wait == 0) {
147 195341 : return DELTA_T;
148 : } else {
149 1081 : myStep++;
150 1081 : return myYellowTime;
151 : }
152 3901 : } else if (myStep == 1) {
153 : // 'y': yellow time is over. switch to red
154 1081 : myStep++;
155 1081 : return MAX2(DELTA_T, wait);
156 2820 : } else if (myStep == 2) {
157 : // 'r': check whether we may open again
158 1659 : if (wait == 0) {
159 1161 : myStep++;
160 1161 : return myOpeningTime;
161 : } else {
162 : return wait;
163 : }
164 : } else { // (myStep == 3)
165 : // 'u': opening time is over, switch to green
166 1161 : if (wait == 0) {
167 1081 : myStep = 0;
168 1081 : return myMinGreenTime;
169 : } else {
170 : // train approached during opening sequence, close again
171 80 : myStep = 2;
172 80 : return wait;
173 : }
174 : }
175 : }
176 :
177 :
178 : // ------------ Conversion between time and phase
179 : SUMOTime
180 0 : MSRailCrossing::getPhaseIndexAtTime(SUMOTime) const {
181 0 : return 0;
182 : }
183 :
184 : SUMOTime
185 0 : MSRailCrossing::getOffsetFromIndex(int) const {
186 0 : return 0;
187 : }
188 :
189 : int
190 0 : MSRailCrossing::getIndexFromOffset(SUMOTime) const {
191 0 : return 0;
192 : }
193 :
194 :
195 : void
196 468 : MSRailCrossing::addLink(MSLink* link, MSLane* lane, int pos) {
197 468 : if (pos >= 0) {
198 194 : MSTrafficLightLogic::addLink(link, lane, pos);
199 : } else {
200 274 : myIncomingRailLinks.push_back(link);
201 : }
202 468 : }
203 :
204 :
205 : /****************************************************************************/
|