LCOV - code coverage report
Current view: top level - src/microsim/traffic_lights - MSRailSignalControl.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 59 64 92.2 %
Date: 2024-05-19 15:37:39 Functions: 11 11 100.0 %

          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             : /****************************************************************************/

Generated by: LCOV version 1.14