LCOV - code coverage report
Current view: top level - src/microsim/traffic_lights - MSRailSignalConstraint.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 94.6 % 149 141
Test Date: 2024-11-22 15:46:21 Functions: 100.0 % 23 23

            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*, ComparatorNumericalIdLess> MSRailSignalConstraint_Predecessor::myTrackerLookup;
      42              : std::map<std::string, std::string> MSRailSignalConstraint::myTripIdLookup;
      43              : 
      44              : // ===========================================================================
      45              : // MSRailSignalConstraint method definitions
      46              : // ===========================================================================
      47              : void
      48        40275 : MSRailSignalConstraint::cleanup() {
      49        40275 :     MSRailSignalConstraint_Predecessor::cleanup();
      50        40275 : }
      51              : 
      52              : void
      53          425 : MSRailSignalConstraint::saveState(OutputDevice& out) {
      54          850 :     if (OptionsCont::getOptions().getBool("save-state.constraints")) {
      55           31 :         for (MSRailSignal* s : MSRailSignalControl::getInstance().getSignals()) {
      56           24 :             if (s->getConstraints().size() > 0) {
      57           17 :                 out.openTag(SUMO_TAG_RAILSIGNAL_CONSTRAINTS);
      58              :                 out.writeAttr(SUMO_ATTR_ID, s->getID());
      59           42 :                 for (auto item : s->getConstraints()) {
      60           50 :                     for (MSRailSignalConstraint* c : item.second) {
      61           25 :                         c->write(out, item.first);
      62              :                     }
      63              :                 }
      64           34 :                 out.closeTag();
      65              :             }
      66              :         }
      67              :     }
      68          425 :     MSRailSignalConstraint_Predecessor::saveState(out);
      69          425 : }
      70              : 
      71              : void
      72          177 : MSRailSignalConstraint::clearState() {
      73          177 :     MSRailSignalConstraint_Predecessor::clearState();
      74              :     myTripIdLookup.clear();
      75          177 : }
      76              : 
      77              : void
      78            6 : MSRailSignalConstraint::clearAll() {
      79           28 :     for (MSRailSignal* s : MSRailSignalControl::getInstance().getSignals()) {
      80           22 :         s->removeConstraints();
      81              :     }
      82              :     myTripIdLookup.clear();
      83            6 : }
      84              : 
      85              : 
      86              : const SUMOVehicle*
      87        17977 : MSRailSignalConstraint::getVeh(const std::string& tripID, bool checkID) {
      88        17977 :     MSVehicleControl& c = MSNet::getInstance()->getVehicleControl();
      89        17977 :     const std::string& vehID = lookupVehId(tripID);
      90        17977 :     if (vehID != "") {
      91         3750 :         SUMOVehicle* veh = c.getVehicle(vehID);
      92         3750 :         if (veh != nullptr) {
      93              :             return veh;
      94              :         }
      95              :     }
      96        27385 :     for (MSVehicleControl::constVehIt i = c.loadedVehBegin(); i != c.loadedVehEnd(); ++i) {
      97        23512 :         SUMOVehicle* veh = i->second;
      98        47024 :         if (veh->getParameter().getParameter("tripId") == tripID || (checkID && veh->getID() == tripID)) {
      99              :             return veh;
     100              :         }
     101              :     }
     102              :     return nullptr;
     103              : }
     104              : 
     105              : // ===========================================================================
     106              : // MSRailSignalConstraint_Predecessor method definitions
     107              : // ===========================================================================
     108          882 : MSRailSignalConstraint_Predecessor::MSRailSignalConstraint_Predecessor(ConstraintType type, const MSRailSignal* signal, const std::string& tripId, int limit, bool active) :
     109              :     MSRailSignalConstraint(type),
     110          882 :     myTripId(tripId),
     111          882 :     myLimit(limit),
     112          882 :     myAmActive(active),
     113         1764 :     myFoeSignal(signal) {
     114         1824 :     for (const auto& lv : signal->getLinks()) {
     115         1884 :         for (const MSLink* link : lv) {
     116          942 :             MSLane* lane = link->getViaLaneOrLane();
     117          942 :             PassedTracker* pt = nullptr;
     118              :             if (myTrackerLookup.count(lane) == 0) {
     119          610 :                 pt = new PassedTracker(lane);
     120          610 :                 myTrackerLookup[lane] = pt;
     121              :             } else {
     122          332 :                 pt = myTrackerLookup[lane];
     123              :             }
     124          942 :             pt->raiseLimit(limit);
     125          942 :             myTrackers.push_back(pt);
     126              :         }
     127              :     }
     128              : 
     129          882 : }
     130              : 
     131              : void
     132        40275 : MSRailSignalConstraint_Predecessor::cleanup() {
     133        40885 :     for (auto item : myTrackerLookup) {
     134          610 :         delete item.second;
     135              :     }
     136              :     myTrackerLookup.clear();
     137        40275 : }
     138              : 
     139              : void
     140          425 : MSRailSignalConstraint_Predecessor::saveState(OutputDevice& out) {
     141          448 :     for (auto item : myTrackerLookup) {
     142           23 :         item.second->saveState(out);
     143              :     }
     144          425 : }
     145              : 
     146              : void
     147            4 : MSRailSignalConstraint_Predecessor::loadState(const SUMOSAXAttributes& attrs) {
     148              :     bool ok;
     149            4 :     const std::string laneID = attrs.getString(SUMO_ATTR_LANE);
     150            4 :     const int index = attrs.get<int>(SUMO_ATTR_INDEX, nullptr, ok);
     151            4 :     const std::vector<std::string>& tripIDs = attrs.get<std::vector<std::string> >(SUMO_ATTR_STATE, nullptr, ok);
     152            4 :     MSLane* lane = MSLane::dictionary(laneID);
     153            4 :     if (lane == nullptr) {
     154            0 :         throw ProcessError(TLF("Unknown lane '%' in loaded state.", laneID));
     155              :     }
     156              :     if (myTrackerLookup.count(lane) == 0) {
     157            0 :         WRITE_WARNINGF(TL("Unknown tracker lane '%' in loaded state."), laneID);
     158              :         return;
     159              :     }
     160            4 :     PassedTracker* tracker = myTrackerLookup[lane];
     161            4 :     tracker->loadState(index, tripIDs);
     162            4 : }
     163              : 
     164              : 
     165              : void
     166          177 : MSRailSignalConstraint_Predecessor::clearState() {
     167          197 :     for (auto item : myTrackerLookup) {
     168           20 :         item.second->clearState();
     169              :     }
     170          177 : }
     171              : 
     172              : 
     173              : bool
     174      7747850 : MSRailSignalConstraint_Predecessor::cleared() const {
     175      7747850 :     if (!myAmActive) {
     176              :         return true;
     177              :     }
     178     23164709 :     for (PassedTracker* pt : myTrackers) {
     179     15434118 :         if (pt->hasPassed(myTripId, myLimit)) {
     180              :             return true;
     181              :         }
     182              :     }
     183              :     return false;
     184              : }
     185              : 
     186              : std::string
     187         3108 : MSRailSignalConstraint_Predecessor::getDescription() const {
     188              :     // try to retrieve vehicle id that belongs to myTripId
     189              :     // this may be slow so it should only be used for debugging
     190         3108 :     const SUMOVehicle* veh = getVeh(myTripId);
     191              :     std::string vehID;
     192         3108 :     if (veh != nullptr) {
     193         3825 :         vehID = " (" + veh->getID() + ")";
     194              :     }
     195              :     std::vector<std::string> passedIDs;
     196         6216 :     for (const std::string& passedTripID : myTrackers.front()->myPassed) {
     197         3108 :         if (passedTripID == "") {
     198         3108 :             continue;
     199              :         }
     200            0 :         const SUMOVehicle* passedVeh = getVeh(passedTripID);
     201            0 :         if (passedVeh != nullptr) {
     202            0 :             passedIDs.push_back(passedVeh->getID());
     203              :         }
     204              :     }
     205         3108 :     std::string passedIDs2 = "";
     206         3108 :     if (passedIDs.size() > 0) {
     207            0 :         passedIDs2 = " (" + toString(passedIDs) + ")";
     208              :     }
     209         3108 :     std::string params = "";
     210         3108 :     for (auto item : getParametersMap()) {
     211            0 :         params += ("\n  key=" + item.first + " value=" + item.second);
     212              :     }
     213         6216 :     return (toString(getTag()) + "  " + myTripId + vehID + " at signal " + myTrackers.front()->getLane()->getEdge().getFromJunction()->getID()
     214        15540 :             + " passed=" + StringUtils::prune(toString(myTrackers.front()->myPassed)) + passedIDs2 + params);
     215         3108 : }
     216              : 
     217              : const SUMOVehicle*
     218        14869 : MSRailSignalConstraint_Predecessor::getFoe() const {
     219        14869 :     return getVeh(myTripId, true);
     220              : }
     221              : 
     222              : void
     223         2500 : MSRailSignalConstraint::storeTripId(const std::string& tripId, const std::string& vehID) {
     224         2500 :     myTripIdLookup[tripId] = vehID;
     225         2500 : }
     226              : 
     227              : const std::string&
     228        17977 : MSRailSignalConstraint::lookupVehId(const std::string& tripId) {
     229        17977 :     return myTripIdLookup[tripId];
     230              : }
     231              : 
     232              : // ===========================================================================
     233              : // MSRailSignalConstraint_Predecessor::PassedTracker method definitions
     234              : // ===========================================================================
     235              : 
     236          610 : MSRailSignalConstraint_Predecessor::PassedTracker::PassedTracker(MSLane* lane) :
     237          610 :     MSMoveReminder("PassedTracker_" + lane->getID(), lane, true),
     238          610 :     myPassed(1, ""),
     239         1220 :     myLastIndex(-1)
     240          610 : { }
     241              : 
     242              : bool
     243          458 : MSRailSignalConstraint_Predecessor::PassedTracker::notifyEnter(SUMOTrafficObject& veh, MSMoveReminder::Notification /*reason*/, const MSLane* /*enteredLane*/) {
     244          458 :     myLastIndex = (myLastIndex + 1) % myPassed.size();
     245          916 :     myPassed[myLastIndex] = veh.getParameter().getParameter("tripId", veh.getID());
     246              : #ifdef DEBUG_PASSED
     247              :     if (myLane->getID() == DEBUG_LANE) {
     248              :         std::cout << SIMTIME << " hasPassed " << veh.getID() << " tripId=" << veh.getParameter().getParameter("tripId", veh.getID()) << " index=" << myLastIndex << "\n";
     249              :     }
     250              : #endif
     251          458 :     return true;
     252              : }
     253              : 
     254              : void
     255          946 : MSRailSignalConstraint_Predecessor::PassedTracker::raiseLimit(int limit) {
     256         1989 :     while (limit > (int)myPassed.size()) {
     257         1043 :         myPassed.insert(myPassed.begin() + (myLastIndex + 1), "");
     258              :     }
     259              : #ifdef DEBUG_PASSED
     260              :     if (myLane->getID() == DEBUG_LANE) {
     261              :         std::cout << " raiseLimit=" << limit << "\n";
     262              :     }
     263              : #endif
     264          946 : }
     265              : 
     266              : bool
     267     15434118 : MSRailSignalConstraint_Predecessor::PassedTracker::hasPassed(const std::string& tripId, int limit) const {
     268     15434118 :     if (myLastIndex < 0) {
     269              :         return false;
     270              :     }
     271              :     int i = myLastIndex;
     272        42967 :     while (limit > 0) {
     273        37507 :         if (myPassed[i] == tripId) {
     274              :             return true;
     275              :         }
     276        20461 :         if (i == 0) {
     277         5460 :             i = (int)myPassed.size() - 1;
     278              :         } else {
     279        15001 :             i--;
     280              :         }
     281        20461 :         limit--;
     282              :     }
     283              :     return false;
     284              : }
     285              : 
     286              : void
     287           20 : MSRailSignalConstraint_Predecessor::PassedTracker::clearState() {
     288           20 :     myPassed = std::vector<std::string>(myPassed.size());
     289           20 :     myLastIndex = 0;
     290           20 : }
     291              : 
     292              : void
     293           23 : MSRailSignalConstraint_Predecessor::PassedTracker::saveState(OutputDevice& out) {
     294           23 :     const std::string state = toString(myPassed.back() == ""
     295           46 :                                        ? std::vector<std::string>(myPassed.begin(), myPassed.begin() + (myLastIndex + 1))
     296              :                                        // wrapped around
     297            0 :                                        : myPassed);
     298              :     // no need to save state if no vehicles have passed this tracker
     299           23 :     if (state != "") {
     300            5 :         out.openTag(SUMO_TAG_RAILSIGNAL_CONSTRAINT_TRACKER);
     301              :         out.writeAttr(SUMO_ATTR_LANE, getLane()->getID());
     302            5 :         out.writeAttr(SUMO_ATTR_INDEX, myLastIndex);
     303              :         out.writeAttr(SUMO_ATTR_STATE, state);
     304           10 :         out.closeTag();
     305              :     }
     306           23 : }
     307              : 
     308              : void
     309            4 : MSRailSignalConstraint_Predecessor::PassedTracker::loadState(int index, const std::vector<std::string>& tripIDs) {
     310            4 :     raiseLimit((int)tripIDs.size());
     311           11 :     for (int i = 0; i < (int)tripIDs.size(); i++) {
     312            7 :         myPassed[i] = tripIDs[i];
     313              :     }
     314              : #ifdef DEBUG_PASSED
     315              :     if (myLane->getID() == DEBUG_LANE) {
     316              :         std::cout << " loadState limit=" << tripIDs.size() << " index=" << index << "\n";
     317              :         for (int i = 0; i < (int)myPassed.size(); i++) {
     318              :             std::cout << " i=" << i << " passed=" << myPassed[i] << "\n";
     319              :         }
     320              :     }
     321              : #endif
     322            4 :     myLastIndex = index;
     323            4 : }
     324              : 
     325              : 
     326              : void
     327           43 : MSRailSignalConstraint_Predecessor::write(OutputDevice& out, const std::string& tripId) const {
     328           43 :     out.openTag(getTag());
     329              :     out.writeAttr(SUMO_ATTR_TRIP_ID, tripId);
     330           43 :     out.writeAttr(SUMO_ATTR_TLID, myFoeSignal->getID());
     331           43 :     out.writeAttr(SUMO_ATTR_FOES, myTripId);
     332           43 :     if (myLimit > 1) {
     333           19 :         out.writeAttr(SUMO_ATTR_LIMIT, myLimit);
     334              :     }
     335           43 :     if (!myAmActive) {
     336           20 :         out.writeAttr(SUMO_ATTR_ACTIVE, myAmActive);
     337              :     }
     338           43 :     writeParams(out);
     339           43 :     out.closeTag();
     340           43 : }
     341              : 
     342              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1