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 MSRailSignalControl.cpp 15 : /// @author Jakob Erdmann 16 : /// @date Sept 2020 17 : /// 18 : // Centralized services for rail signal control (Singleton) 19 : /****************************************************************************/ 20 : #include <config.h> 21 : 22 : #include <cassert> 23 : #include <utility> 24 : #include <vector> 25 : #include <bitset> 26 : #include <microsim/MSNet.h> 27 : #include <microsim/MSRoute.h> 28 : #include <microsim/MSEdge.h> 29 : #include "MSRailSignal.h" 30 : #include "MSRailSignalControl.h" 31 : 32 : 33 : //#define DEBUG_REGISTER_DRIVEWAY 34 : //#define DEBUG_SIGNALSTATE 35 : //#define DEBUG_RECHECKGREEN 36 : 37 : // =========================================================================== 38 : // static value definitions 39 : // =========================================================================== 40 : MSRailSignalControl* MSRailSignalControl::myInstance(nullptr); 41 : 42 : // =========================================================================== 43 : // method definitions 44 : // =========================================================================== 45 685 : MSRailSignalControl::MSRailSignalControl() 46 685 : {} 47 : 48 : MSRailSignalControl& 49 6617433 : MSRailSignalControl::getInstance() { 50 6617433 : if (myInstance == nullptr) { 51 685 : myInstance = new MSRailSignalControl(); 52 685 : MSNet::getInstance()->addVehicleStateListener(myInstance); 53 : } 54 6617433 : return *myInstance; 55 : } 56 : 57 : void 58 35243 : MSRailSignalControl::cleanup() { 59 35243 : delete myInstance; 60 35243 : myInstance = nullptr; 61 35243 : } 62 : 63 : void 64 227 : MSRailSignalControl::clearState() { 65 227 : if (myInstance != nullptr) { 66 : myInstance->myUsedEdges.clear(); 67 12 : myInstance->myProtectedDriveways.clear(); 68 12 : myInstance->myDriveWayCompatibility.clear(); 69 : } 70 227 : } 71 : 72 : 73 1370 : MSRailSignalControl::~MSRailSignalControl() { 74 1370 : } 75 : 76 : void 77 15145 : MSRailSignalControl::vehicleStateChanged(const SUMOVehicle* const vehicle, MSNet::VehicleState to, const std::string& /*info*/) { 78 15145 : if (isRailway(vehicle->getVClass())) { 79 10937 : if (to == MSNet::VehicleState::NEWROUTE || to == MSNet::VehicleState::DEPARTED) { 80 92462 : for (const MSEdge* edge : vehicle->getRoute().getEdges()) { 81 : myUsedEdges.insert(edge); 82 : if (myProtectedDriveways.count(edge) != 0) { 83 53 : updateDriveways(edge); 84 : } 85 : } 86 : } 87 10937 : if (to == MSNet::VehicleState::BUILT || (!vehicle->hasDeparted() && to == MSNet::VehicleState::NEWROUTE)) { 88 : // @note we could delay initialization until the departure time 89 3326 : MSRailSignal::initDriveWays(vehicle, to == MSNet::VehicleState::NEWROUTE); 90 : } 91 : } 92 15145 : } 93 : 94 : 95 : void 96 283 : MSRailSignalControl::registerProtectedDriveway(MSRailSignal* rs, int driveWayID, const MSEdge* protectedBidi) { 97 283 : myProtectedDriveways[protectedBidi].push_back(std::make_pair(rs, driveWayID)); 98 : #ifdef DEBUG_REGISTER_DRIVEWAY 99 : std::cout << "MSRailSignalControl edge=" << protectedBidi->getID() << " assumed secure by driveway " << driveWayID << " at signal " << rs->getID() << "\n"; 100 : #endif 101 283 : } 102 : 103 : void 104 53 : MSRailSignalControl::updateDriveways(const MSEdge* used) { 105 112 : for (auto item : myProtectedDriveways[used]) { 106 59 : item.first->updateDriveway(item.second); 107 : } 108 : myProtectedDriveways.erase(used); 109 53 : } 110 : 111 : 112 : void 113 2725 : MSRailSignalControl::addSignal(MSRailSignal* signal) { 114 2725 : mySignals.push_back(signal); 115 2725 : } 116 : 117 : 118 : void 119 6612219 : MSRailSignalControl::recheckGreen() { 120 6612219 : if (mySwitchedGreenFlanks.size() > 0) { 121 2790 : for (const auto& item : mySwitchedGreenFlanks) { 122 2838 : for (const auto& item2 : mySwitchedGreenFlanks) { 123 1435 : if (item.second < item2.second) { 124 : bool conflict = false; 125 : std::pair<int, int> code(item.second, item2.second); 126 : auto it = myDriveWayCompatibility.find(code); 127 16 : if (it != myDriveWayCompatibility.end()) { 128 0 : conflict = it->second; 129 : } else { 130 : // new driveway pair 131 16 : const MSRailSignal* rs = static_cast<const MSRailSignal*>(item.first->getTLLogic()); 132 16 : const MSRailSignal* rs2 = static_cast<const MSRailSignal*>(item2.first->getTLLogic()); 133 16 : const MSRailSignal::DriveWay& dw = rs->retrieveDriveWay(item.second); 134 16 : const MSRailSignal::DriveWay& dw2 = rs2->retrieveDriveWay(item2.second); 135 : // overlap may return true if the driveways are consecutive forward sections 136 16 : conflict = dw.flankConflict(dw2) || dw2.flankConflict(dw); 137 16 : myDriveWayCompatibility[code] = conflict; 138 : #ifdef DEBUG_RECHECKGREEN 139 : std::cout << SIMTIME << " new code " << code.first << "," << code.second << " conflict=" << conflict << " dw=" << toString(dw.myRoute) << " dw2=" << toString(dw2.myRoute) << "\n"; 140 : #endif 141 : } 142 16 : if (conflict) { 143 3 : MSRailSignal* rs = const_cast<MSRailSignal*>(static_cast<const MSRailSignal*>(item.first->getTLLogic())); 144 3 : MSRailSignal* rs2 = const_cast<MSRailSignal*>(static_cast<const MSRailSignal*>(item2.first->getTLLogic())); 145 3 : const MSRailSignal::Approaching& veh = rs->getClosest(item.first); 146 3 : const MSRailSignal::Approaching& veh2 = rs2->getClosest(item2.first); 147 3 : if (MSRailSignal::DriveWay::mustYield(veh, veh2)) { 148 0 : std::string state = rs->getCurrentPhaseDef().getState(); 149 0 : state[item.first->getTLIndex()] = 'r'; 150 0 : const_cast<MSPhaseDefinition&>(rs->getCurrentPhaseDef()).setState(state); 151 0 : rs->setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep()); 152 : #ifdef DEBUG_RECHECKGREEN 153 : std::cout << SIMTIME << " reset to red " << getClickableTLLinkID(item.first) 154 : << " (" << veh.first->getID() << " yields to " << veh2.first->getID() << "\n"; 155 : #endif 156 : #ifdef DEBUG_SIGNALSTATE 157 : if (DEBUG_HELPER(rs)) { 158 : std::cout << SIMTIME << " reset to red " << getClickableTLLinkID(item.first) 159 : << " (" << veh.first->getID() << " yields to " << veh2.first->getID() << "\n"; 160 : } 161 : #endif 162 : } else { 163 3 : std::string state = rs2->getCurrentPhaseDef().getState(); 164 3 : state[item2.first->getTLIndex()] = 'r'; 165 3 : const_cast<MSPhaseDefinition&>(rs2->getCurrentPhaseDef()).setState(state); 166 3 : rs2->setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep()); 167 : #ifdef DEBUG_RECHECKGREEN 168 : std::cout << SIMTIME << " reset to red " << getClickableTLLinkID(item2.first) 169 : << " (" << veh2.first->getID() << " yields to " << veh.first->getID() << "\n"; 170 : #endif 171 : #ifdef DEBUG_SIGNALSTATE 172 : if (DEBUG_HELPER(rs2)) { 173 : std::cout << SIMTIME << " reset to red " << getClickableTLLinkID(item2.first) 174 : << " (" << veh2.first->getID() << " yields to " << veh.first->getID() << "\n"; 175 : } 176 : #endif 177 : } 178 : } 179 : } 180 : } 181 : } 182 : mySwitchedGreenFlanks.clear(); 183 : } 184 6612219 : } 185 : 186 : 187 : /****************************************************************************/