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 MSRailSignal.cpp
15 : /// @author Melanie Weber
16 : /// @author Andreas Kendziorra
17 : /// @author Jakob Erdmann
18 : /// @date Jan 2015
19 : ///
20 : // A rail signal logic
21 : /****************************************************************************/
22 : #include <config.h>
23 :
24 : #include <cassert>
25 : #include <utility>
26 : #include <vector>
27 : #include <bitset>
28 : #ifdef HAVE_FOX
29 : #include <utils/foxtools/MFXWorkerThread.h>
30 : #endif
31 : #include <utils/iodevices/OutputDevice_COUT.h>
32 : #include <microsim/MSEventControl.h>
33 : #include <microsim/MSNet.h>
34 : #include <microsim/MSEdge.h>
35 : #include <microsim/MSEdgeControl.h>
36 : #include <microsim/MSLane.h>
37 : #include <microsim/MSLink.h>
38 : #include <microsim/MSVehicle.h>
39 : #include <microsim/devices/MSDevice_Routing.h>
40 : #include <microsim/devices/MSRoutingEngine.h>
41 : #include <microsim/MSLane.h>
42 :
43 : #include "MSTLLogicControl.h"
44 : #include "MSTrafficLightLogic.h"
45 : #include "MSPhaseDefinition.h"
46 : #include "MSTLLogicControl.h"
47 : #include "MSRailSignalConstraint.h"
48 : #include "MSRailSignalControl.h"
49 : #include "MSDriveWay.h"
50 : #include "MSRailSignal.h"
51 :
52 : //#define DEBUG_SELECT_DRIVEWAY
53 : //#define DEBUG_DRIVEWAY_UPDATE
54 : //#define DEBUG_SIGNALSTATE
55 : //#define DEBUG_REROUTE
56 :
57 : #define DEBUG_COND DEBUG_HELPER(this)
58 : #define DEBUG_COND_LINKINFO DEBUG_HELPER(myLink->getTLLogic())
59 : #define DEBUG_HELPER(obj) ((obj)->isSelected())
60 : //#define DEBUG_HELPER(obj) ((obj)->getID() == "")
61 : //#define DEBUG_HELPER(obj) (true)
62 :
63 : // ===========================================================================
64 : // static value definitions
65 : // ===========================================================================
66 :
67 : bool MSRailSignal::myStoreVehicles(false);
68 : MSRailSignal::VehicleVector MSRailSignal::myBlockingVehicles;
69 : MSRailSignal::VehicleVector MSRailSignal::myRivalVehicles;
70 : MSRailSignal::VehicleVector MSRailSignal::myPriorityVehicles;
71 : std::string MSRailSignal::myConstraintInfo;
72 : int MSRailSignal::myRSIndex(0);
73 : std::vector<const MSDriveWay*> MSRailSignal::myBlockingDriveWays;
74 : std::string MSRailSignal::myRequestedDriveWay;
75 :
76 : // ===========================================================================
77 : // method definitions
78 : // ===========================================================================
79 3485 : MSRailSignal::MSRailSignal(MSTLLogicControl& tlcontrol,
80 : const std::string& id, const std::string& programID, SUMOTime delay,
81 3485 : const Parameterised::Map& parameters) :
82 : MSTrafficLightLogic(tlcontrol, id, programID, 0, TrafficLightType::RAIL_SIGNAL, delay, parameters),
83 3485 : myNumericalID(myRSIndex++),
84 10455 : myCurrentPhase(DELTA_T, std::string(SUMO_MAX_CONNECTIONS, 'X')), // dummy phase
85 3485 : myPhaseIndex(0),
86 3485 : myDriveWayIndex(0) {
87 3485 : myDefaultCycleTime = DELTA_T;
88 3485 : myMovingBlock = OptionsCont::getOptions().getBool("railsignal-moving-block");
89 3485 : MSRailSignalControl::getInstance().addSignal(this);
90 3485 : mySwitchCommand->deschedule(this);
91 3485 : }
92 :
93 : void
94 3485 : MSRailSignal::init(NLDetectorBuilder&) {
95 3485 : if (myLanes.size() == 0) {
96 9 : WRITE_WARNINGF(TL("Rail signal at junction '%' does not control any links"), getID());
97 : }
98 8078 : for (LinkVector& links : myLinks) { //for every link index
99 4593 : if (links.size() != 1) {
100 0 : throw ProcessError("At railSignal '" + getID() + "' found " + toString(links.size())
101 0 : + " links controlled by index " + toString(links[0]->getTLIndex()));
102 : }
103 9186 : myLinkInfos.push_back(LinkInfo(links[0]));
104 : }
105 3485 : updateCurrentPhase();
106 3485 : setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
107 3485 : myNumLinks = (int)myLinks.size();
108 3485 : }
109 :
110 :
111 6970 : MSRailSignal::~MSRailSignal() {
112 3485 : removeConstraints();
113 6970 : }
114 :
115 :
116 : // ----------- Handling of controlled links
117 : void
118 0 : MSRailSignal::adaptLinkInformationFrom(const MSTrafficLightLogic& logic) {
119 0 : MSTrafficLightLogic::adaptLinkInformationFrom(logic);
120 0 : updateCurrentPhase();
121 0 : }
122 :
123 :
124 : // ------------ Switching and setting current rows
125 : SUMOTime
126 0 : MSRailSignal::trySwitch() {
127 : // deschedule regular traffic light event,
128 : // updateCurrentPhase is instead called from MSRailSignalControl::updateSignals
129 0 : return SUMOTime_MAX;
130 : }
131 :
132 :
133 :
134 : bool
135 16300396 : MSRailSignal::updateCurrentPhase() {
136 : #ifdef DEBUG_SIGNALSTATE
137 : gDebugFlag4 = DEBUG_COND;
138 : #endif
139 : bool keepActive = false;
140 : // green by default so vehicles can be inserted at the borders of the network
141 : std::string state(myLinks.size(), 'G');
142 48086028 : for (LinkInfo& li : myLinkInfos) {
143 31785632 : if (li.myLink->getApproaching().size() > 0) {
144 : keepActive = true;
145 8163980 : Approaching closest = li.myLink->getClosest();
146 8163980 : MSDriveWay& driveway = li.getDriveWay(closest.first);
147 : //std::cout << SIMTIME << " signal=" << getTLLinkID(li.myLink) << " veh=" << closest.first->getID() << " dw:\n";
148 : //driveway.writeBlocks(*OutputDevice_COUT::getDevice());
149 8163980 : const bool mustWait = !constraintsAllow(closest.first, true);
150 : MSEdgeVector occupied;
151 8163980 : if (mustWait || !driveway.reserve(closest, occupied)) {
152 7881820 : state[li.myLink->getTLIndex()] = 'r';
153 7881820 : if (occupied.size() > 0) {
154 157299 : li.reroute(const_cast<SUMOVehicle*>(closest.first), occupied);
155 : }
156 : #ifdef DEBUG_SIGNALSTATE
157 : if (gDebugFlag4) {
158 : std::cout << SIMTIME << " rsl=" << li.getID() << " veh=" << closest.first->getID() << " notReserved\n";
159 : }
160 : #endif
161 : } else {
162 282160 : state[li.myLink->getTLIndex()] = 'G';
163 : #ifdef DEBUG_SIGNALSTATE
164 : if (gDebugFlag4) {
165 : std::cout << SIMTIME << " rsl=" << li.getID() << " veh=" << closest.first->getID() << " reserved\n";
166 : }
167 : #endif
168 : }
169 8163980 : } else {
170 23621652 : if (li.myDriveways.empty()) {
171 : #ifdef DEBUG_SIGNALSTATE
172 : if (gDebugFlag4) {
173 : std::cout << SIMTIME << " rsl=" << li.getID() << " red for unitialized signal (no driveways yet)\n";
174 : }
175 : #endif
176 15437190 : state[li.myLink->getTLIndex()] = 'r';
177 : } else {
178 8184462 : const MSDriveWay& driveway = *li.myDriveways.front();
179 : MSEdgeVector occupied;
180 8184462 : if (driveway.foeDriveWayOccupied(true, nullptr, occupied) || driveway.foeDriveWayApproached()) {
181 : keepActive = true;
182 : #ifdef DEBUG_SIGNALSTATE
183 : if (gDebugFlag4) {
184 : std::cout << SIMTIME << " rsl=" << li.getID() << " red for default driveway " << driveway.getID() << "\n";
185 : }
186 : #endif
187 8140289 : state[li.myLink->getTLIndex()] = 'r';
188 : } else {
189 : #ifdef DEBUG_SIGNALSTATE
190 : if (gDebugFlag4) {
191 : std::cout << SIMTIME << " rsl=" << li.getID() << " green for default driveway " << driveway.getID() << "\n";
192 : }
193 : #endif
194 : }
195 8184462 : }
196 : }
197 : }
198 16300396 : if (myCurrentPhase.getState() != state) {
199 : myCurrentPhase.setState(state);
200 27128 : myPhaseIndex = 1 - myPhaseIndex;
201 : // set link priorities
202 27128 : setTrafficLightSignals(SIMSTEP);
203 : // execute switch actions (3D-gui)
204 : //const MSTLLogicControl::TLSLogicVariants& vars = myTLControl.get(myTLLogic->getID());
205 : //vars.executeOnSwitchActions();
206 : }
207 : #ifdef DEBUG_SIGNALSTATE
208 : gDebugFlag4 = false;
209 : #endif
210 16300396 : return keepActive;
211 : }
212 :
213 :
214 : bool
215 8185358 : MSRailSignal::constraintsAllow(const SUMOVehicle* veh, bool storeWaitRelation) const {
216 8185358 : if (myConstraints.size() == 0) {
217 : return true;
218 : } else {
219 15499716 : const std::string tripID = veh->getParameter().getParameter("tripId", veh->getID());
220 : auto it = myConstraints.find(tripID);
221 7749858 : if (it != myConstraints.end()) {
222 7763359 : for (MSRailSignalConstraint* c : it->second) {
223 : // ignore insertion constraints here
224 7744291 : if (!c->isInsertionConstraint() && !c->cleared()) {
225 : #ifdef DEBUG_SIGNALSTATE
226 : if (gDebugFlag4) {
227 : std::cout << " constraint '" << c->getDescription() << "' not cleared\n";
228 : }
229 : #endif
230 7718434 : if (storeWaitRelation && MSGlobals::gTimeToTeleportRSDeadlock > 0
231 7739029 : && veh->getWaitingTime() > veh->getVehicleType().getCarFollowModel().getStartupDelay()) {
232 11761 : const SUMOVehicle* foe = c->getFoe();
233 11761 : if (foe != nullptr) {
234 9721 : MSRailSignalControl::getInstance().addWaitRelation(veh, this, foe, c);
235 : }
236 : }
237 7725392 : if (myStoreVehicles) {
238 0 : myConstraintInfo = c->getDescription();
239 : }
240 : return false;
241 : }
242 : }
243 : }
244 24466 : return true;
245 : }
246 : }
247 :
248 :
249 : void
250 882 : MSRailSignal::addConstraint(const std::string& tripId, MSRailSignalConstraint* constraint) {
251 882 : myConstraints[tripId].push_back(constraint);
252 882 : }
253 :
254 :
255 : bool
256 213 : MSRailSignal::removeConstraint(const std::string& tripId, MSRailSignalConstraint* constraint) {
257 : if (myConstraints.count(tripId) != 0) {
258 213 : auto& constraints = myConstraints[tripId];
259 213 : auto it = std::find(constraints.begin(), constraints.end(), constraint);
260 213 : if (it != constraints.end()) {
261 213 : delete *it;
262 : constraints.erase(it);
263 : return true;
264 : }
265 : }
266 : return false;
267 : }
268 :
269 : void
270 3507 : MSRailSignal::removeConstraints() {
271 4244 : for (auto item : myConstraints) {
272 1406 : for (MSRailSignalConstraint* c : item.second) {
273 669 : delete c;
274 : }
275 : }
276 : myConstraints.clear();
277 3507 : }
278 :
279 :
280 : // ------------ Static Information Retrieval
281 : int
282 0 : MSRailSignal::getPhaseNumber() const {
283 0 : return 0;
284 : }
285 :
286 : const MSTrafficLightLogic::Phases&
287 3485 : MSRailSignal::getPhases() const {
288 3485 : return myPhases;
289 : }
290 :
291 : const MSPhaseDefinition&
292 0 : MSRailSignal::getPhase(int) const {
293 0 : return myCurrentPhase;
294 : }
295 :
296 : // ------------ Dynamic Information Retrieval
297 : int
298 29614 : MSRailSignal::getCurrentPhaseIndex() const {
299 29614 : return myPhaseIndex;
300 : }
301 :
302 : const MSPhaseDefinition&
303 16400096 : MSRailSignal::getCurrentPhaseDef() const {
304 16400096 : return myCurrentPhase;
305 : }
306 :
307 : // ------------ Conversion between time and phase
308 : SUMOTime
309 0 : MSRailSignal::getPhaseIndexAtTime(SUMOTime) const {
310 0 : return 0;
311 : }
312 :
313 : SUMOTime
314 0 : MSRailSignal::getOffsetFromIndex(int) const {
315 0 : return 0;
316 : }
317 :
318 : int
319 0 : MSRailSignal::getIndexFromOffset(SUMOTime) const {
320 0 : return 0;
321 : }
322 :
323 :
324 : void
325 4593 : MSRailSignal::addLink(MSLink* link, MSLane* lane, int pos) {
326 4593 : if (pos >= 0) {
327 4593 : MSTrafficLightLogic::addLink(link, lane, pos);
328 : } // ignore uncontrolled link
329 4593 : }
330 :
331 :
332 : std::string
333 0 : MSRailSignal::describeLinks(std::vector<MSLink*> links) {
334 : std::string result;
335 0 : for (MSLink* link : links) {
336 0 : result += link->getDescription() + " ";
337 : }
338 0 : return result;
339 : }
340 :
341 :
342 : void
343 2775 : MSRailSignal::writeBlocks(OutputDevice& od, bool writeVehicles) const {
344 5550 : od.openTag("railSignal");
345 : od.writeAttr(SUMO_ATTR_ID, getID());
346 5973 : for (const LinkInfo& li : myLinkInfos) {
347 3198 : MSLink* link = li.myLink;
348 6396 : od.openTag("link");
349 6396 : od.writeAttr(SUMO_ATTR_TLLINKINDEX, link->getTLIndex());
350 : od.writeAttr(SUMO_ATTR_FROM, link->getLaneBefore()->getID());
351 : od.writeAttr(SUMO_ATTR_TO, link->getViaLaneOrLane()->getID());
352 6100 : for (const MSDriveWay* dw : li.myDriveways) {
353 2902 : if (writeVehicles) {
354 287 : dw->writeBlockVehicles(od);
355 : } else {
356 2615 : dw->writeBlocks(od);
357 : }
358 : }
359 6396 : od.closeTag(); // link
360 : }
361 2775 : od.closeTag(); // railSignal
362 2775 : }
363 :
364 :
365 : void
366 2345 : MSRailSignal::initDriveWays(const SUMOVehicle* ego, bool update) {
367 2345 : const ConstMSEdgeVector& edges = ego->getRoute().getEdges();
368 2345 : int endIndex = ego->getParameter().arrivalEdge;
369 2345 : if (endIndex < 0) {
370 2345 : endIndex = (int)edges.size() - 1;
371 : }
372 2345 : const int departIndex = ego->getParameter().departEdge;
373 2345 : MSDriveWay* prev = const_cast<MSDriveWay*>(MSDriveWay::getDepartureDriveway(ego));
374 21413 : for (int i = departIndex; i <= endIndex - 1; i++) {
375 19068 : const MSEdge* e = edges[i];
376 19068 : if (e->isNormal() && e->getToJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
377 10695 : const MSEdge* e2 = edges[i + 1];
378 21390 : for (MSLane* lane : e->getLanes()) {
379 21970 : for (MSLink* link : lane->getLinkCont()) {
380 11275 : if (&link->getLane()->getEdge() == e2) {
381 10690 : MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(link->getTLLogic()));
382 9272 : if (rs != nullptr) {
383 9272 : LinkInfo& li = rs->myLinkInfos[link->getTLIndex()];
384 : // init driveway
385 9272 : MSDriveWay* dw = &li.getDriveWay(ego);
386 9272 : MSRailSignalControl::getInstance().addDrivewayFollower(prev, dw);
387 9272 : MSRailSignalControl::getInstance().addDWDeadlockChecks(rs, prev);
388 9272 : MSRailSignalControl::getInstance().notifyApproach(link);
389 : prev = dw;
390 9272 : if (update && rs->isActive()) {
391 : // vehicle may have rerouted its intial trip
392 : // after the states have been set
393 : // @note: This is a hack because it could lead to invalid tls-output
394 : // (it's still an improvement over switching based on default driveways)
395 8030 : rs->updateCurrentPhase();
396 8030 : rs->setTrafficLightSignals(SIMSTEP);
397 : }
398 : }
399 : }
400 : }
401 : }
402 : }
403 : }
404 2345 : MSDriveWay::getDepartureDriveway(ego);
405 2345 : }
406 :
407 :
408 : bool
409 14310 : MSRailSignal::hasInsertionConstraint(MSLink* link, const MSVehicle* veh, std::string& info, bool& isInsertionOrder) {
410 14310 : if (link->getJunction() != nullptr && link->getJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
411 4953 : const MSRailSignal* rs = dynamic_cast<const MSRailSignal*>(link->getTLLogic());
412 4761 : if (rs != nullptr && rs->myConstraints.size() > 0) {
413 6874 : const std::string tripID = veh->getParameter().getParameter("tripId", veh->getID());
414 : auto it = rs->myConstraints.find(tripID);
415 3437 : if (it != rs->myConstraints.end()) {
416 3646 : for (MSRailSignalConstraint* c : it->second) {
417 3367 : if (c->isInsertionConstraint() && !c->cleared()) {
418 : #ifdef DEBUG_SIGNALSTATE
419 : if (DEBUG_HELPER(rs)) {
420 : std::cout << SIMTIME << " rsl=" << rs->getID() << " insertion constraint '" << c->getDescription() << "' for vehicle '" << veh->getID() << "' not cleared\n";
421 : }
422 : #endif
423 6216 : info = c->getDescription();
424 3108 : isInsertionOrder = c->getType() == MSRailSignalConstraint::ConstraintType::INSERTION_ORDER;
425 3108 : if (MSGlobals::gTimeToTeleportRSDeadlock > 0) {
426 3108 : const SUMOVehicle* foe = c->getFoe();
427 3108 : if (foe != nullptr) {
428 3108 : MSRailSignalControl::getInstance().addWaitRelation(veh, rs, foe, c);
429 : }
430 : }
431 : return true;
432 : }
433 : }
434 : }
435 : }
436 : }
437 : return false;
438 : }
439 :
440 : // ===========================================================================
441 : // LinkInfo method definitions
442 : // ===========================================================================
443 :
444 4593 : MSRailSignal::LinkInfo::LinkInfo(MSLink* link):
445 4593 : myLink(link) {
446 4593 : reset();
447 4593 : }
448 :
449 10566 : MSRailSignal::LinkInfo::~LinkInfo() {
450 13909 : for (MSDriveWay* dw : myDriveways) {
451 3343 : delete dw;
452 : }
453 : myDriveways.clear();
454 10566 : }
455 :
456 : void
457 4598 : MSRailSignal::LinkInfo::reset() {
458 4598 : myLastRerouteTime = -1;
459 4598 : myLastRerouteVehicle = nullptr;
460 : myDriveways.clear();
461 4598 : }
462 :
463 :
464 : std::string
465 6 : MSRailSignal::LinkInfo::getID() const {
466 12 : return myLink->getTLLogic()->getID() + "_" + toString(myLink->getTLIndex());
467 : }
468 :
469 :
470 : MSDriveWay&
471 8211121 : MSRailSignal::LinkInfo::getDriveWay(const SUMOVehicle* veh) {
472 8211121 : MSEdge* first = &myLink->getLane()->getEdge();
473 8211121 : MSRouteIterator firstIt = std::find(veh->getCurrentRouteEdge(), veh->getRoute().end(), first);
474 8211121 : if (firstIt == veh->getRoute().end()) {
475 : // possibly the vehicle has already gone past the first edge (i.e.
476 : // because first is short or the step-length is high)
477 : // lets look backward along the route
478 : // give some slack because the vehicle might have been braking from a higher speed and using ballistic integration
479 50 : double lookBack = SPEED2DIST(veh->getSpeed() + 10);
480 50 : int routeIndex = veh->getRoutePosition() - 1;
481 60 : while (lookBack > 0 && routeIndex > 0) {
482 50 : const MSEdge* prevEdge = veh->getRoute().getEdges()[routeIndex];
483 50 : if (prevEdge == first) {
484 40 : firstIt = veh->getRoute().begin() + routeIndex;
485 40 : break;
486 : }
487 10 : lookBack -= prevEdge->getLength();
488 10 : routeIndex--;
489 : }
490 : }
491 8211121 : MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(myLink->getTLLogic()));
492 8211121 : if (firstIt == veh->getRoute().end()) {
493 40 : WRITE_WARNING("Invalid approach information to rail signal '" + MSDriveWay::getClickableTLLinkID(myLink) + "' after rerouting for vehicle '" + veh->getID()
494 : + "' first driveway edge '" + first->getID() + "' time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
495 10 : if (myDriveways.empty()) {
496 : ConstMSEdgeVector dummyRoute;
497 0 : dummyRoute.push_back(&myLink->getLane()->getEdge());
498 0 : MSDriveWay* dw = MSDriveWay::buildDriveWay(rs->getNewDrivewayID(), myLink, dummyRoute.begin(), dummyRoute.end());
499 0 : myDriveways.push_back(dw);
500 0 : }
501 10 : return *myDriveways.front();
502 : }
503 : //std::cout << SIMTIME << " veh=" << veh->getID() << " rsl=" << getID() << " dws=" << myDriveways.size() << "\n";
504 8211111 : return getDriveWay(firstIt, veh->getRoute().end(), veh->getID());
505 : }
506 :
507 :
508 : MSDriveWay&
509 8211111 : MSRailSignal::LinkInfo::getDriveWay(MSRouteIterator firstIt, MSRouteIterator endIt, const std::string& info) {
510 8244519 : for (MSDriveWay* dw : myDriveways) {
511 8241176 : if (dw->match(firstIt, endIt)) {
512 : return *dw;
513 : }
514 : #ifdef DEBUG_SELECT_DRIVEWAY
515 : std::cout << SIMTIME << " rs=" << getID() << " veh=" << info << " other dwSignal=" << dw->foundSignal() << " dwRoute=" << toString(dw->getRoute()) << "\n";
516 : #else
517 : UNUSED_PARAMETER(info);
518 : #endif
519 : }
520 3343 : MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(myLink->getTLLogic()));
521 3343 : MSDriveWay* dw = MSDriveWay::buildDriveWay(rs->getNewDrivewayID(), myLink, firstIt, endIt);
522 : dw->setVehicle(info);
523 : #ifdef DEBUG_SELECT_DRIVEWAY
524 : std::cout << SIMTIME << " rs=" << getID() << " veh=" << info << " new dwSignal=" << dw->foundSignal() << " dwRoute=" << toString(dw->getRoute()) << "\n";
525 : #endif
526 3343 : myDriveways.push_back(dw);
527 3343 : return *myDriveways.back();
528 : }
529 :
530 :
531 : void
532 157299 : MSRailSignal::LinkInfo::reroute(SUMOVehicle* veh, const MSEdgeVector& occupied) {
533 157299 : MSDevice_Routing* rDev = static_cast<MSDevice_Routing*>(veh->getDevice(typeid(MSDevice_Routing)));
534 157299 : const SUMOTime now = MSNet::getInstance()->getCurrentTimeStep();
535 : if (rDev != nullptr
536 131601 : && rDev->mayRerouteRailSignal()
537 157458 : && (myLastRerouteVehicle != veh
538 : // reroute each vehicle only once if no periodic routing is allowed,
539 : // otherwise with the specified period
540 153 : || (rDev->getPeriod() > 0 && myLastRerouteTime + rDev->getPeriod() <= now))) {
541 6 : myLastRerouteVehicle = veh;
542 6 : myLastRerouteTime = now;
543 :
544 : #ifdef DEBUG_REROUTE
545 : ConstMSEdgeVector oldRoute = veh->getRoute().getEdges();
546 : if (DEBUG_COND_LINKINFO) {
547 : std::cout << SIMTIME << " reroute veh=" << veh->getID() << " rs=" << getID() << " occupied=" << toString(occupied) << "\n";
548 : }
549 : #endif
550 18 : MSRoutingEngine::reroute(*veh, now, "railSignal:" + getID(), false, true, occupied);
551 : #ifdef DEBUG_REROUTE
552 : // attention this works only if we are not parallel!
553 : if (DEBUG_COND_LINKINFO) {
554 : if (veh->getRoute().getEdges() != oldRoute) {
555 : std::cout << " rerouting successful\n";
556 : }
557 : }
558 : #endif
559 : }
560 157299 : }
561 :
562 :
563 : void
564 18352 : MSRailSignal::storeTraCIVehicles(int linkIndex) {
565 : myBlockingVehicles.clear();
566 : myRivalVehicles.clear();
567 : myPriorityVehicles.clear();
568 : myConstraintInfo = "";
569 : myBlockingDriveWays.clear();
570 : myRequestedDriveWay = "";
571 18352 : myStoreVehicles = true;
572 18352 : LinkInfo& li = myLinkInfos[linkIndex];
573 18352 : if (li.myLink->getApproaching().size() > 0) {
574 1825 : Approaching closest = li.myLink->getClosest();
575 1825 : MSDriveWay& driveway = li.getDriveWay(closest.first);
576 : MSEdgeVector occupied;
577 : myRequestedDriveWay = driveway.getID();
578 : // call for side effects
579 1825 : driveway.reserve(closest, occupied);
580 1825 : constraintsAllow(closest.first);
581 18352 : } else if (li.myDriveways.size() > 0) {
582 16035 : li.myDriveways.front()->conflictLaneOccupied();
583 16035 : li.myDriveways.front()->foeDriveWayApproached();
584 : }
585 18352 : myStoreVehicles = false;
586 18352 : }
587 :
588 : MSRailSignal::VehicleVector
589 6124 : MSRailSignal::getBlockingVehicles(int linkIndex) {
590 6124 : storeTraCIVehicles(linkIndex);
591 6124 : return myBlockingVehicles;
592 : }
593 :
594 : MSRailSignal::VehicleVector
595 6114 : MSRailSignal::getRivalVehicles(int linkIndex) {
596 6114 : storeTraCIVehicles(linkIndex);
597 6114 : return myRivalVehicles;
598 : }
599 :
600 : MSRailSignal::VehicleVector
601 6114 : MSRailSignal::getPriorityVehicles(int linkIndex) {
602 6114 : storeTraCIVehicles(linkIndex);
603 6114 : return myPriorityVehicles;
604 : }
605 :
606 : std::string
607 0 : MSRailSignal::getConstraintInfo(int linkIndex) {
608 0 : storeTraCIVehicles(linkIndex);
609 0 : return myConstraintInfo;
610 : }
611 :
612 :
613 : std::string
614 0 : MSRailSignal::getRequestedDriveWay(int linkIndex) {
615 0 : storeTraCIVehicles(linkIndex);
616 0 : return myRequestedDriveWay;
617 : }
618 :
619 :
620 : std::vector<const MSDriveWay*>
621 0 : MSRailSignal::getBlockingDriveWays(int linkIndex) {
622 0 : storeTraCIVehicles(linkIndex);
623 0 : return myBlockingDriveWays;
624 : }
625 :
626 : const MSDriveWay&
627 0 : MSRailSignal::retrieveDriveWay(int numericalID) const {
628 0 : for (const LinkInfo& li : myLinkInfos) {
629 0 : for (const MSDriveWay* dw : li.myDriveways) {
630 0 : if (dw->getNumericalID() == numericalID) {
631 0 : return *dw;
632 : }
633 : }
634 : }
635 0 : throw ProcessError("Invalid driveway id " + toString(numericalID) + " at railSignal '" + getID() + "'");
636 : }
637 :
638 : const MSDriveWay&
639 36044 : MSRailSignal::retrieveDriveWayForVeh(int tlIndex, const SUMOVehicle* veh) {
640 36044 : return myLinkInfos[tlIndex].getDriveWay(veh);
641 : }
642 :
643 : const MSDriveWay&
644 0 : MSRailSignal::retrieveDriveWayForRoute(int tlIndex, MSRouteIterator first, MSRouteIterator end) {
645 0 : return myLinkInfos[tlIndex].getDriveWay(first, end);
646 : }
647 :
648 :
649 : const std::vector<MSDriveWay*>
650 8837 : MSRailSignal::retrieveDriveWays(int tlIndex) const {
651 8837 : return myLinkInfos[tlIndex].myDriveways;
652 : }
653 :
654 :
655 : std::string
656 0 : MSRailSignal::getBlockingVehicleIDs() const {
657 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
658 0 : if (myLinkInfos.size() == 1) {
659 0 : return toString(rs->getBlockingVehicles(0));
660 : } else {
661 : std::string result;
662 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
663 0 : result += toString(i) + ": " + toString(rs->getBlockingVehicles(i)) + ";";
664 : }
665 0 : return result;
666 : }
667 : }
668 : std::string
669 0 : MSRailSignal::getRivalVehicleIDs() const {
670 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
671 0 : if (myLinkInfos.size() == 1) {
672 0 : return toString(rs->getRivalVehicles(0));
673 : } else {
674 : std::string result;
675 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
676 0 : result += toString(i) + ": " + toString(rs->getRivalVehicles(i)) + ";";
677 : }
678 0 : return result;
679 : }
680 : }
681 : std::string
682 0 : MSRailSignal::getPriorityVehicleIDs() const {
683 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
684 0 : if (myLinkInfos.size() == 1) {
685 0 : return toString(rs->getPriorityVehicles(0));
686 : } else {
687 : std::string result;
688 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
689 0 : result += toString(i) + ": " + toString(rs->getPriorityVehicles(i)) + ";";
690 : }
691 0 : return result;
692 : }
693 : }
694 : std::string
695 0 : MSRailSignal::getConstraintInfo() const {
696 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
697 0 : if (myLinkInfos.size() == 1) {
698 0 : return rs->getConstraintInfo(0);
699 : } else {
700 : std::string result;
701 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
702 0 : result += toString(i) + ": " + rs->getConstraintInfo(i);
703 : }
704 0 : return result;
705 : }
706 : }
707 : std::string
708 0 : MSRailSignal::getRequestedDriveWay() const {
709 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
710 0 : if (myLinkInfos.size() == 1) {
711 0 : return toString(rs->getRequestedDriveWay(0));
712 : } else {
713 : std::string result;
714 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
715 0 : result += toString(i) + ": " + toString(rs->getRequestedDriveWay(i)) + ";";
716 : }
717 0 : return result;
718 : }
719 : }
720 : std::string
721 0 : MSRailSignal::getBlockingDriveWayIDs() const {
722 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
723 0 : if (myLinkInfos.size() == 1) {
724 0 : return toString(rs->getBlockingDriveWays(0));
725 : } else {
726 : std::string result;
727 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
728 0 : result += toString(i) + ": " + toString(rs->getBlockingDriveWays(i)) + ";";
729 : }
730 0 : return result;
731 : }
732 : }
733 :
734 : void
735 5 : MSRailSignal::setParameter(const std::string& key, const std::string& value) {
736 : // some pre-defined parameters can be updated at runtime
737 5 : if (key == "moving-block") {
738 5 : bool movingBlock = StringUtils::toBool(value);
739 5 : if (movingBlock != myMovingBlock) {
740 : // recompute driveways
741 5 : myMovingBlock = movingBlock;
742 10 : for (LinkInfo& li : myLinkInfos) {
743 5 : li.reset();
744 : }
745 5 : updateCurrentPhase();
746 5 : setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
747 : }
748 : }
749 5 : Parameterised::setParameter(key, value);
750 5 : }
751 :
752 :
753 : std::string
754 3343 : MSRailSignal::getNewDrivewayID() {
755 6686 : return getID() + "." + toString(myDriveWayIndex++);
756 : }
757 : /****************************************************************************/
|