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