LCOV - code coverage report
Current view: top level - src/microsim/traffic_lights - MSRailSignalConstraint.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 131 140 93.6 %
Date: 2024-05-19 15:37:39 Functions: 20 20 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    MSRailSignalConstraint.cpp
      15             : /// @author  Jakob Erdmann
      16             : /// @date    August 2020
      17             : ///
      18             : // A constraint on rail signal switching
      19             : /****************************************************************************/
      20             : #include <config.h>
      21             : #include <cassert>
      22             : #include <utility>
      23             : 
      24             : #include <utils/xml/SUMOSAXAttributes.h>
      25             : #include <utils/common/StringUtils.h>
      26             : #include <microsim/MSLane.h>
      27             : #include <microsim/MSEdge.h>
      28             : #include <microsim/MSLink.h>
      29             : #include <microsim/MSNet.h>
      30             : #include <microsim/MSVehicleControl.h>
      31             : #include "MSRailSignal.h"
      32             : #include "MSRailSignalConstraint.h"
      33             : #include "MSRailSignalControl.h"
      34             : 
      35             : //#define DEBUG_PASSED
      36             : //#define DEBUG_LANE
      37             : 
      38             : // ===========================================================================
      39             : // static value definitions
      40             : // ===========================================================================
      41             : std::map<const MSLane*, MSRailSignalConstraint_Predecessor::PassedTracker*> MSRailSignalConstraint_Predecessor::myTrackerLookup;
      42             : 
      43             : // ===========================================================================
      44             : // MSRailSignalConstraint method definitions
      45             : // ===========================================================================
      46             : void
      47       35243 : MSRailSignalConstraint::cleanup() {
      48       35243 :     MSRailSignalConstraint_Predecessor::cleanup();
      49       35243 : }
      50             : 
      51             : void
      52         505 : MSRailSignalConstraint::saveState(OutputDevice& out) {
      53        1010 :     if (OptionsCont::getOptions().getBool("save-state.constraints")) {
      54          48 :         for (MSRailSignal* s : MSRailSignalControl::getInstance().getSignals()) {
      55          36 :             if (s->getConstraints().size() > 0) {
      56          24 :                 out.openTag(SUMO_TAG_RAILSIGNAL_CONSTRAINTS);
      57             :                 out.writeAttr(SUMO_ATTR_ID, s->getID());
      58          72 :                 for (auto item : s->getConstraints()) {
      59          96 :                     for (MSRailSignalConstraint* c : item.second) {
      60          48 :                         c->write(out, item.first);
      61             :                     }
      62          48 :                 }
      63          48 :                 out.closeTag();
      64             :             }
      65             :         }
      66             :     }
      67         505 :     MSRailSignalConstraint_Predecessor::saveState(out);
      68         505 : }
      69             : 
      70             : void
      71         227 : MSRailSignalConstraint::clearState() {
      72         227 :     MSRailSignalConstraint_Predecessor::clearState();
      73         227 : }
      74             : 
      75             : void
      76           9 : MSRailSignalConstraint::clearAll() {
      77          39 :     for (MSRailSignal* s : MSRailSignalControl::getInstance().getSignals()) {
      78          30 :         s->removeConstraints();
      79             :     }
      80           9 : }
      81             : 
      82             : 
      83             : std::string
      84        1802 : MSRailSignalConstraint::getVehID(const std::string& tripID) {
      85        1802 :     MSVehicleControl& c = MSNet::getInstance()->getVehicleControl();
      86        5036 :     for (MSVehicleControl::constVehIt i = c.loadedVehBegin(); i != c.loadedVehEnd(); ++i) {
      87        3589 :         SUMOVehicle* veh = i->second;
      88        3589 :         if (veh->getParameter().getParameter("tripId") == tripID) {
      89             :             return veh->getID();
      90             :         }
      91             :     }
      92        1447 :     return "";
      93             : }
      94             : 
      95             : // ===========================================================================
      96             : // MSRailSignalConstraint_Predecessor method definitions
      97             : // ===========================================================================
      98         945 : MSRailSignalConstraint_Predecessor::MSRailSignalConstraint_Predecessor(ConstraintType type, const MSRailSignal* signal, const std::string& tripId, int limit, bool active) :
      99             :     MSRailSignalConstraint(type),
     100         945 :     myTripId(tripId),
     101         945 :     myLimit(limit),
     102         945 :     myAmActive(active),
     103        1890 :     myFoeSignal(signal) {
     104        1961 :     for (const auto& lv : signal->getLinks()) {
     105        2032 :         for (const MSLink* link : lv) {
     106        1016 :             MSLane* lane = link->getViaLaneOrLane();
     107        1016 :             PassedTracker* pt = nullptr;
     108             :             if (myTrackerLookup.count(lane) == 0) {
     109         608 :                 pt = new PassedTracker(lane);
     110         608 :                 myTrackerLookup[lane] = pt;
     111             :             } else {
     112         408 :                 pt = myTrackerLookup[lane];
     113             :             }
     114        1016 :             pt->raiseLimit(limit);
     115        1016 :             myTrackers.push_back(pt);
     116             :         }
     117             :     }
     118             : 
     119         945 : }
     120             : 
     121             : void
     122       35243 : MSRailSignalConstraint_Predecessor::cleanup() {
     123       35851 :     for (auto item : myTrackerLookup) {
     124         608 :         delete item.second;
     125             :     }
     126             :     myTrackerLookup.clear();
     127       35243 : }
     128             : 
     129             : void
     130         505 : MSRailSignalConstraint_Predecessor::saveState(OutputDevice& out) {
     131         535 :     for (auto item : myTrackerLookup) {
     132          30 :         item.second->saveState(out);
     133             :     }
     134         505 : }
     135             : 
     136             : void
     137           4 : MSRailSignalConstraint_Predecessor::loadState(const SUMOSAXAttributes& attrs) {
     138             :     bool ok;
     139           4 :     const std::string laneID = attrs.getString(SUMO_ATTR_LANE);
     140           4 :     const int index = attrs.get<int>(SUMO_ATTR_INDEX, nullptr, ok);
     141           4 :     const std::vector<std::string>& tripIDs = attrs.get<std::vector<std::string> >(SUMO_ATTR_STATE, nullptr, ok);
     142           4 :     MSLane* lane = MSLane::dictionary(laneID);
     143           4 :     if (lane == nullptr) {
     144           0 :         throw ProcessError(TLF("Unknown lane '%' in loaded state.", laneID));
     145             :     }
     146             :     if (myTrackerLookup.count(lane) == 0) {
     147           0 :         WRITE_WARNINGF(TL("Unknown tracker lane '%' in loaded state."), laneID);
     148             :         return;
     149             :     }
     150           4 :     PassedTracker* tracker = myTrackerLookup[lane];
     151           4 :     tracker->loadState(index, tripIDs);
     152           4 : }
     153             : 
     154             : 
     155             : void
     156         227 : MSRailSignalConstraint_Predecessor::clearState() {
     157         251 :     for (auto item : myTrackerLookup) {
     158          24 :         item.second->clearState();
     159             :     }
     160         227 : }
     161             : 
     162             : 
     163             : bool
     164     6486277 : MSRailSignalConstraint_Predecessor::cleared() const {
     165     6486277 :     if (!myAmActive) {
     166             :         return true;
     167             :     }
     168    19366306 :     for (PassedTracker* pt : myTrackers) {
     169    12902523 :         if (pt->hasPassed(myTripId, myLimit)) {
     170             :             return true;
     171             :         }
     172             :     }
     173             :     return false;
     174             : }
     175             : 
     176             : std::string
     177        1802 : MSRailSignalConstraint_Predecessor::getDescription() const {
     178             :     // try to retrieve vehicle id that belongs to myTripId
     179             :     // this may be slow so it should only be used for debugging
     180        1802 :     std::string vehID = getVehID(myTripId);
     181        1802 :     if (vehID != "") {
     182         710 :         vehID = " (" + vehID + ")";
     183             :     }
     184             :     std::vector<std::string> passedIDs;
     185        5024 :     for (const std::string& passedTripID : myTrackers.front()->myPassed) {
     186        3222 :         if (passedTripID == "") {
     187        3222 :             continue;
     188             :         }
     189           0 :         const std::string passedID = getVehID(passedTripID);
     190           0 :         if (passedID != "") {
     191           0 :             passedIDs.push_back(passedID);
     192             :         }
     193             :     }
     194        1802 :     std::string passedIDs2 = "";
     195        1802 :     if (passedIDs.size() > 0) {
     196           0 :         passedIDs2 = " (" + toString(passedIDs) + ")";
     197             :     }
     198        1802 :     std::string params = "";
     199        1802 :     for (auto item : getParametersMap()) {
     200           0 :         params += ("\n  key=" + item.first + " value=" + item.second);
     201           0 :     }
     202        5406 :     return (toString(getTag()) + "  " + myTripId + vehID + " at signal " + myTrackers.front()->getLane()->getEdge().getFromJunction()->getID()
     203        9010 :             + " passed=" + StringUtils::prune(toString(myTrackers.front()->myPassed)) + passedIDs2 + params);
     204        1802 : }
     205             : 
     206             : // ===========================================================================
     207             : // MSRailSignalConstraint_Predecessor::PassedTracker method definitions
     208             : // ===========================================================================
     209             : 
     210         608 : MSRailSignalConstraint_Predecessor::PassedTracker::PassedTracker(MSLane* lane) :
     211         608 :     MSMoveReminder("PassedTracker_" + lane->getID(), lane, true),
     212         608 :     myPassed(1, ""),
     213        1216 :     myLastIndex(-1)
     214         608 : { }
     215             : 
     216             : bool
     217         517 : MSRailSignalConstraint_Predecessor::PassedTracker::notifyEnter(SUMOTrafficObject& veh, MSMoveReminder::Notification /*reason*/, const MSLane* /*enteredLane*/) {
     218         517 :     myLastIndex = (myLastIndex + 1) % myPassed.size();
     219        1034 :     myPassed[myLastIndex] = veh.getParameter().getParameter("tripId", veh.getID());
     220             : #ifdef DEBUG_PASSED
     221             :     if (myLane->getID() == DEBUG_LANE) {
     222             :         std::cout << SIMTIME << " hasPassed " << veh.getID() << " tripId=" << veh.getParameter().getParameter("tripId", veh.getID()) << " index=" << myLastIndex << "\n";
     223             :     }
     224             : #endif
     225         517 :     return true;
     226             : }
     227             : 
     228             : void
     229        1020 : MSRailSignalConstraint_Predecessor::PassedTracker::raiseLimit(int limit) {
     230        2265 :     while (limit > (int)myPassed.size()) {
     231        1245 :         myPassed.insert(myPassed.begin() + (myLastIndex + 1), "");
     232             :     }
     233             : #ifdef DEBUG_PASSED
     234             :     if (myLane->getID() == DEBUG_LANE) {
     235             :         std::cout << " raiseLimit=" << limit << "\n";
     236             :     }
     237             : #endif
     238        1020 : }
     239             : 
     240             : bool
     241    12902523 : MSRailSignalConstraint_Predecessor::PassedTracker::hasPassed(const std::string& tripId, int limit) const {
     242    12902523 :     if (myLastIndex < 0) {
     243             :         return false;
     244             :     }
     245             :     int i = myLastIndex;
     246       55080 :     while (limit > 0) {
     247       48275 :         if (myPassed[i] == tripId) {
     248             :             return true;
     249             :         }
     250       25937 :         if (i == 0) {
     251        6805 :             i = (int)myPassed.size() - 1;
     252             :         } else {
     253       19132 :             i--;
     254             :         }
     255       25937 :         limit--;
     256             :     }
     257             :     return false;
     258             : }
     259             : 
     260             : void
     261          24 : MSRailSignalConstraint_Predecessor::PassedTracker::clearState() {
     262          24 :     myPassed = std::vector<std::string>(myPassed.size());
     263          24 :     myLastIndex = 0;
     264          24 : }
     265             : 
     266             : void
     267          30 : MSRailSignalConstraint_Predecessor::PassedTracker::saveState(OutputDevice& out) {
     268             :     const std::string state = toString(myPassed.back() == ""
     269          60 :                                        ? std::vector<std::string>(myPassed.begin(), myPassed.begin() + (myLastIndex + 1))
     270             :                                        // wrapped around
     271           0 :                                        : myPassed);
     272             :     // no need to save state if no vehicles have passed this tracker
     273          30 :     if (state != "") {
     274           6 :         out.openTag(SUMO_TAG_RAILSIGNAL_CONSTRAINT_TRACKER);
     275             :         out.writeAttr(SUMO_ATTR_LANE, getLane()->getID());
     276           6 :         out.writeAttr(SUMO_ATTR_INDEX, myLastIndex);
     277             :         out.writeAttr(SUMO_ATTR_STATE, state);
     278          12 :         out.closeTag();
     279             :     }
     280          30 : }
     281             : 
     282             : void
     283           4 : MSRailSignalConstraint_Predecessor::PassedTracker::loadState(int index, const std::vector<std::string>& tripIDs) {
     284           4 :     raiseLimit((int)tripIDs.size());
     285          12 :     for (int i = 0; i < (int)tripIDs.size(); i++) {
     286           8 :         myPassed[i] = tripIDs[i];
     287             :     }
     288             : #ifdef DEBUG_PASSED
     289             :     if (myLane->getID() == DEBUG_LANE) {
     290             :         std::cout << " loadState limit=" << tripIDs.size() << " index=" << index << "\n";
     291             :         for (int i = 0; i < (int)myPassed.size(); i++) {
     292             :             std::cout << " i=" << i << " passed=" << myPassed[i] << "\n";
     293             :         }
     294             :     }
     295             : #endif
     296           4 :     myLastIndex = index;
     297           4 : }
     298             : 
     299             : 
     300             : void
     301          48 : MSRailSignalConstraint_Predecessor::write(OutputDevice& out, const std::string& tripId) const {
     302          48 :     out.openTag(getTag());
     303             :     out.writeAttr(SUMO_ATTR_TRIP_ID, tripId);
     304          48 :     out.writeAttr(SUMO_ATTR_TLID, myFoeSignal->getID());
     305          48 :     out.writeAttr(SUMO_ATTR_FOES, myTripId);
     306          48 :     if (myLimit > 1) {
     307          30 :         out.writeAttr(SUMO_ATTR_LIMIT, myLimit);
     308             :     }
     309          48 :     if (!myAmActive) {
     310           6 :         out.writeAttr(SUMO_ATTR_ACTIVE, myAmActive);
     311             :     }
     312          48 :     writeParams(out);
     313          48 :     out.closeTag();
     314          48 : }
     315             : 
     316             : /****************************************************************************/

Generated by: LCOV version 1.14