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