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 175 : MSRailCrossing::MSRailCrossing(MSTLLogicControl& tlcontrol, 42 : const std::string& id, const std::string& programID, SUMOTime delay, 43 175 : const Parameterised::Map& parameters) : 44 350 : MSSimpleTrafficLightLogic(tlcontrol, id, programID, 0, TrafficLightType::RAIL_CROSSING, Phases(), 0, delay, parameters) { 45 : // dummy phase, used to avoid crashing in MSTrafficLightLogic::setTrafficLightSignals() 46 175 : myPhases.push_back(new MSPhaseDefinition(1, std::string(SUMO_MAX_CONNECTIONS, 'X'))); 47 175 : myDefaultCycleTime = 1; 48 175 : } 49 : 50 : 51 525 : MSRailCrossing::~MSRailCrossing() {} 52 : 53 : 54 : void 55 175 : MSRailCrossing::init(NLDetectorBuilder&) { 56 175 : const Parameterised::Map test = getParametersMap(); 57 175 : myTimeGap = string2time(getParameter("time-gap", "15")); 58 : //use time-gap by default 59 175 : mySpaceGap = StringUtils::toDouble(getParameter("space-gap", "-1")); 60 175 : myMinGreenTime = string2time(getParameter("min-green", "5")); 61 175 : myOpeningDelay = string2time(getParameter("opening-delay", "3")); 62 175 : myOpeningTime = string2time(getParameter("opening-time", "3")); // red-yellow while opening 63 : /// XXX compute reasonable time depending on link length 64 175 : myYellowTime = string2time(getParameter("yellow-time", "5")); 65 175 : delete myPhases.front(); 66 175 : myPhases.clear(); 67 175 : myPhases.push_back(new MSPhaseDefinition(1, std::string(myLinks.size(), LINKSTATE_TL_GREEN_MAJOR))); 68 175 : myPhases.push_back(new MSPhaseDefinition(myYellowTime, std::string(myLinks.size(), LINKSTATE_TL_YELLOW_MINOR))); 69 175 : myPhases.push_back(new MSPhaseDefinition(1, std::string(myLinks.size(), LINKSTATE_TL_RED))); 70 175 : myPhases.push_back(new MSPhaseDefinition(myOpeningTime, std::string(myLinks.size(), LINKSTATE_TL_REDYELLOW))); 71 : // init phases 72 175 : updateCurrentPhase(); 73 175 : setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep()); 74 175 : myNumLinks = (int)myLinks.size(); 75 175 : } 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 226345 : MSRailCrossing::trySwitch() { 109 226345 : const int oldStep = myStep; 110 226345 : SUMOTime nextTry = updateCurrentPhase(); 111 : //if (getID() == "cluster_1088529493_1260626727") std::cout << " myStep=" << myStep << " nextTry=" << nextTry << "\n"; 112 226345 : if (myStep != oldStep) { 113 5756 : myPhases[myStep]->myLastSwitch = MSNet::getInstance()->getCurrentTimeStep(); 114 : } 115 226345 : return nextTry; 116 : } 117 : 118 : 119 : SUMOTime 120 226520 : MSRailCrossing::updateCurrentPhase() { 121 226520 : 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 769780 : for (const MSLink* const link : myIncomingRailLinks) { 126 588418 : for (const auto& it_avi : link->getApproaching()) { 127 : const MSLink::ApproachingVehicleInformation& avi = it_avi.second; 128 45158 : if (avi.arrivalTime - myYellowTime - now < myTimeGap) { 129 3268 : stayRedUntil = MAX2(stayRedUntil, avi.leavingTime + myOpeningDelay); 130 : } 131 45158 : if (mySpaceGap >= 0 && avi.dist < mySpaceGap) { 132 : // TODO maybe check the incoming lanes because stopped vehicles do not register at the oncoming junction 133 242 : stayRedUntil = MAX2(stayRedUntil, avi.leavingTime + myOpeningDelay); 134 : } 135 : } 136 543260 : if (link->getViaLane() != nullptr && link->getViaLane()->getVehicleNumberWithPartials() > 0) { 137 : // do not open if there is still a train on the crossing 138 190 : stayRedUntil = MAX2(stayRedUntil, now + DELTA_T + myOpeningDelay); 139 : } 140 : } 141 : //if (getID() == "cluster_1088529493_1260626727") std::cout << SIMTIME << " stayRedUntil=" << stayRedUntil; 142 226520 : const SUMOTime wait = stayRedUntil - now; 143 : 144 226520 : if (myStep == 0) { 145 : // 'G': check whether the crossing can stay open 146 221494 : if (wait == 0) { 147 220116 : return DELTA_T; 148 : } else { 149 1378 : myStep++; 150 1378 : return myYellowTime; 151 : } 152 5026 : } else if (myStep == 1) { 153 : // 'y': yellow time is over. switch to red 154 1378 : myStep++; 155 1378 : return MAX2(DELTA_T, wait); 156 3648 : } else if (myStep == 2) { 157 : // 'r': check whether we may open again 158 2148 : if (wait == 0) { 159 1500 : myStep++; 160 1500 : return myOpeningTime; 161 : } else { 162 : return wait; 163 : } 164 : } else { // (myStep == 3) 165 : // 'u': opening time is over, switch to green 166 1500 : if (wait == 0) { 167 1378 : myStep = 0; 168 1378 : return myMinGreenTime; 169 : } else { 170 : // train approached during opening sequence, close again 171 122 : myStep = 2; 172 122 : 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 574 : MSRailCrossing::addLink(MSLink* link, MSLane* lane, int pos) { 197 574 : if (pos >= 0) { 198 200 : MSTrafficLightLogic::addLink(link, lane, pos); 199 : } else { 200 374 : myIncomingRailLinks.push_back(link); 201 : } 202 574 : } 203 : 204 : 205 : /****************************************************************************/