Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2025 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 4601 : MSRailSignal::MSRailSignal(MSTLLogicControl& tlcontrol,
80 : const std::string& id, const std::string& programID, SUMOTime delay,
81 4601 : const Parameterised::Map& parameters) :
82 : MSTrafficLightLogic(tlcontrol, id, programID, 0, TrafficLightType::RAIL_SIGNAL, delay, parameters),
83 4601 : myNumericalID(myRSIndex++),
84 13803 : myCurrentPhase(DELTA_T, std::string(SUMO_MAX_CONNECTIONS, 'X')), // dummy phase
85 4601 : myPhaseIndex(0),
86 4601 : myDriveWayIndex(0) {
87 4601 : myDefaultCycleTime = DELTA_T;
88 4601 : myMovingBlock = OptionsCont::getOptions().getBool("railsignal-moving-block");
89 4601 : mySwitchCommand->deschedule(this);
90 4601 : }
91 :
92 : void
93 4601 : MSRailSignal::init(NLDetectorBuilder&) {
94 4601 : if (myLanes.size() == 0) {
95 9 : WRITE_WARNINGF(TL("Rail signal at junction '%' does not control any links"), getID());
96 : }
97 10424 : for (LinkVector& links : myLinks) { //for every link index
98 5823 : if (links.size() != 1) {
99 0 : throw ProcessError("At railSignal '" + getID() + "' found " + toString(links.size())
100 0 : + " links controlled by index " + toString(links[0]->getTLIndex()));
101 : }
102 11646 : myLinkInfos.push_back(LinkInfo(links[0]));
103 : }
104 4601 : updateCurrentPhase();
105 4601 : setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
106 4601 : myNumLinks = (int)myLinks.size();
107 4601 : MSRailSignalControl::getInstance().addSignal(this);
108 4601 : }
109 :
110 :
111 9202 : MSRailSignal::~MSRailSignal() {
112 4601 : removeConstraints();
113 9202 : }
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 7636718 : 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 21772586 : for (LinkInfo& li : myLinkInfos) {
143 14135868 : if (li.myLink->getApproaching().size() > 0 && li.myControlled) {
144 : keepActive = true;
145 3815404 : Approaching closest = li.myLink->getClosest();
146 3815404 : 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 3815404 : const bool mustWait = !constraintsAllow(closest.first, true);
150 : MSEdgeVector occupied;
151 3815404 : if (mustWait || !driveway.reserve(closest, occupied)) {
152 3462900 : state[li.myLink->getTLIndex()] = 'r';
153 3462900 : if (occupied.size() > 0) {
154 232694 : 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 352504 : 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 14135868 : } else if (li.myControlled) {
170 10320102 : 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 6450772 : state[li.myLink->getTLIndex()] = 'r';
177 : } else {
178 3869330 : const MSDriveWay& driveway = *li.myDriveways.front();
179 : MSEdgeVector occupied;
180 3869330 : 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 3820910 : 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 3869330 : }
196 : } else {
197 362 : state[li.myLink->getTLIndex()] = 'O';
198 : }
199 : }
200 7636718 : if (myCurrentPhase.getState() != state) {
201 : myCurrentPhase.setState(state);
202 31932 : myPhaseIndex = 1 - myPhaseIndex;
203 : // set link priorities
204 31932 : setTrafficLightSignals(SIMSTEP);
205 : // execute switch actions (3D-gui)
206 : //const MSTLLogicControl::TLSLogicVariants& vars = myTLControl.get(myTLLogic->getID());
207 : //vars.executeOnSwitchActions();
208 : }
209 : #ifdef DEBUG_SIGNALSTATE
210 : gDebugFlag4 = false;
211 : #endif
212 7636718 : return keepActive;
213 : }
214 :
215 :
216 : bool
217 3840988 : MSRailSignal::constraintsAllow(const SUMOVehicle* veh, bool storeWaitRelation) const {
218 3840988 : if (myConstraints.size() == 0) {
219 : return true;
220 : } else {
221 6516582 : const std::string tripID = veh->getParameter().getParameter("tripId", veh->getID());
222 : auto it = myConstraints.find(tripID);
223 3258291 : if (it != myConstraints.end()) {
224 3273901 : for (MSRailSignalConstraint* c : it->second) {
225 : // ignore insertion constraints here
226 3252393 : if (!c->isInsertionConstraint() && !c->cleared()) {
227 : #ifdef DEBUG_SIGNALSTATE
228 : if (gDebugFlag4) {
229 : std::cout << " constraint '" << c->getDescription() << "' not cleared\n";
230 : }
231 : #endif
232 3222967 : if (storeWaitRelation && MSGlobals::gTimeToTeleportRSDeadlock > 0
233 3248647 : && veh->getWaitingTime() > veh->getVehicleType().getCarFollowModel().getStartupDelay()) {
234 13929 : const SUMOVehicle* foe = c->getFoe();
235 13929 : if (foe != nullptr) {
236 11889 : MSRailSignalControl::getInstance().addWaitRelation(veh, this, foe, c);
237 : }
238 : }
239 3231330 : if (myStoreVehicles) {
240 0 : myConstraintInfo = c->getDescription();
241 : }
242 : return false;
243 : }
244 : }
245 : }
246 26961 : return true;
247 : }
248 : }
249 :
250 :
251 : void
252 939 : MSRailSignal::addConstraint(const std::string& tripId, MSRailSignalConstraint* constraint) {
253 939 : myConstraints[tripId].push_back(constraint);
254 939 : }
255 :
256 :
257 : bool
258 218 : MSRailSignal::removeConstraint(const std::string& tripId, MSRailSignalConstraint* constraint) {
259 : if (myConstraints.count(tripId) != 0) {
260 218 : auto& constraints = myConstraints[tripId];
261 218 : auto it = std::find(constraints.begin(), constraints.end(), constraint);
262 218 : if (it != constraints.end()) {
263 218 : delete *it;
264 : constraints.erase(it);
265 : return true;
266 : }
267 : }
268 : return false;
269 : }
270 :
271 : void
272 4625 : MSRailSignal::removeConstraints() {
273 5419 : for (auto item : myConstraints) {
274 1515 : for (MSRailSignalConstraint* c : item.second) {
275 721 : delete c;
276 : }
277 : }
278 : myConstraints.clear();
279 4625 : }
280 :
281 :
282 : // ------------ Static Information Retrieval
283 : int
284 0 : MSRailSignal::getPhaseNumber() const {
285 0 : return 0;
286 : }
287 :
288 : const MSTrafficLightLogic::Phases&
289 4601 : MSRailSignal::getPhases() const {
290 4601 : return myPhases;
291 : }
292 :
293 : const MSPhaseDefinition&
294 0 : MSRailSignal::getPhase(int) const {
295 0 : return myCurrentPhase;
296 : }
297 :
298 : // ------------ Dynamic Information Retrieval
299 : int
300 29614 : MSRailSignal::getCurrentPhaseIndex() const {
301 29614 : return myPhaseIndex;
302 : }
303 :
304 : const MSPhaseDefinition&
305 7744798 : MSRailSignal::getCurrentPhaseDef() const {
306 7744798 : return myCurrentPhase;
307 : }
308 :
309 : // ------------ Conversion between time and phase
310 : SUMOTime
311 0 : MSRailSignal::getPhaseIndexAtTime(SUMOTime) const {
312 0 : return 0;
313 : }
314 :
315 : SUMOTime
316 0 : MSRailSignal::getOffsetFromIndex(int) const {
317 0 : return 0;
318 : }
319 :
320 : int
321 0 : MSRailSignal::getIndexFromOffset(SUMOTime) const {
322 0 : return 0;
323 : }
324 :
325 :
326 : void
327 5823 : MSRailSignal::addLink(MSLink* link, MSLane* lane, int pos) {
328 5823 : if (pos >= 0) {
329 5823 : MSTrafficLightLogic::addLink(link, lane, pos);
330 : } // ignore uncontrolled link
331 5823 : }
332 :
333 :
334 : std::string
335 0 : MSRailSignal::describeLinks(std::vector<MSLink*> links) {
336 : std::string result;
337 0 : for (MSLink* link : links) {
338 0 : result += link->getDescription() + " ";
339 : }
340 0 : return result;
341 : }
342 :
343 :
344 : void
345 3890 : MSRailSignal::writeBlocks(OutputDevice& od, bool writeVehicles) const {
346 7780 : od.openTag("railSignal");
347 3890 : od.writeAttr(SUMO_ATTR_ID, getID());
348 8322 : for (const LinkInfo& li : myLinkInfos) {
349 4432 : MSLink* link = li.myLink;
350 8864 : od.openTag("link");
351 4432 : od.writeAttr(SUMO_ATTR_TLLINKINDEX, link->getTLIndex());
352 4432 : od.writeAttr(SUMO_ATTR_FROM, link->getLaneBefore()->getID());
353 4432 : od.writeAttr(SUMO_ATTR_TO, link->getViaLaneOrLane()->getID());
354 8290 : for (const MSDriveWay* dw : li.myDriveways) {
355 3858 : if (writeVehicles) {
356 368 : dw->writeBlockVehicles(od);
357 : } else {
358 3490 : dw->writeBlocks(od);
359 : }
360 : }
361 8864 : od.closeTag(); // link
362 : }
363 3890 : od.closeTag(); // railSignal
364 3890 : }
365 :
366 :
367 : void
368 3536 : MSRailSignal::initDriveWays(const SUMOVehicle* ego, bool update) {
369 3536 : const ConstMSEdgeVector& edges = ego->getRoute().getEdges();
370 3536 : int endIndex = ego->getParameter().arrivalEdge;
371 3536 : if (endIndex < 0) {
372 3533 : endIndex = (int)edges.size() - 1;
373 : }
374 3536 : const int departIndex = ego->getParameter().departEdge;
375 3536 : MSDriveWay* prev = const_cast<MSDriveWay*>(MSDriveWay::getDepartureDriveway(ego, true));
376 3536 : if (update && ego->hasDeparted()) {
377 782 : MSBaseVehicle* veh = dynamic_cast<MSBaseVehicle*>(const_cast<SUMOVehicle*>(ego));
378 782 : if (!prev->hasTrain(veh) && prev->notifyEnter(*veh, prev->NOTIFICATION_REROUTE, nullptr) && !veh->hasReminder(prev)) {
379 40 : veh->addReminder(prev, 1);
380 : }
381 : }
382 83265 : for (int i = departIndex; i <= endIndex - 1; i++) {
383 79729 : const MSEdge* e = edges[i];
384 79729 : if (e->isNormal() && e->getToJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
385 54553 : const MSEdge* e2 = edges[i + 1];
386 109106 : for (MSLane* lane : e->getLanes()) {
387 110056 : for (MSLink* link : lane->getLinkCont()) {
388 55503 : if (&link->getLane()->getEdge() == e2) {
389 54532 : MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(link->getTLLogic()));
390 51969 : if (rs != nullptr) {
391 51969 : LinkInfo& li = rs->myLinkInfos[link->getTLIndex()];
392 : // init driveway
393 51969 : MSDriveWay* dw = &li.getDriveWay(ego, i);
394 51969 : MSRailSignalControl::getInstance().addDrivewayFollower(prev, dw);
395 51969 : MSRailSignalControl::getInstance().addDWDeadlockChecks(rs, prev);
396 51969 : MSRailSignalControl::getInstance().notifyApproach(link);
397 : prev = dw;
398 51969 : if (update && rs->isActive()) {
399 : // vehicle may have rerouted its intial trip
400 : // after the states have been set
401 : // @note: This is a hack because it could lead to invalid tls-output
402 : // (it's still an improvement over switching based on default driveways)
403 49688 : if (!ego->hasDeparted()) {
404 8316 : rs->updateCurrentPhase();
405 8316 : rs->setTrafficLightSignals(SIMSTEP);
406 41372 : } else if (ego->hasDeparted() && i <= ego->getRoutePosition()) {
407 17435 : MSBaseVehicle* veh = dynamic_cast<MSBaseVehicle*>(const_cast<SUMOVehicle*>(ego));
408 17435 : if (!dw->hasTrain(veh) && dw->notifyEnter(*veh, dw->NOTIFICATION_REROUTE, nullptr) && !veh->hasReminder(dw)) {
409 39 : veh->addReminder(dw, 1);
410 57 : for (MSDriveWay* sub : dw->getSubDriveWays()) {
411 18 : if (!sub->hasTrain(veh) && sub->notifyEnter(*veh, dw->NOTIFICATION_REROUTE, nullptr) && !veh->hasReminder(sub)) {
412 0 : veh->addReminder(sub, 1);
413 : }
414 : }
415 : }
416 : }
417 : }
418 : }
419 : }
420 : }
421 : }
422 : }
423 : }
424 3536 : MSDriveWay::getDepartureDriveway(ego, true);
425 3536 : }
426 :
427 :
428 : bool
429 16371 : MSRailSignal::hasInsertionConstraint(MSLink* link, const MSVehicle* veh, std::string& info, bool& isInsertionOrder) {
430 16371 : if (link->getJunction() != nullptr && link->getJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
431 5081 : const MSRailSignal* rs = dynamic_cast<const MSRailSignal*>(link->getTLLogic());
432 4881 : if (rs != nullptr && rs->myConstraints.size() > 0) {
433 6910 : const std::string tripID = veh->getParameter().getParameter("tripId", veh->getID());
434 : auto it = rs->myConstraints.find(tripID);
435 3455 : if (it != rs->myConstraints.end()) {
436 3671 : for (MSRailSignalConstraint* c : it->second) {
437 3375 : if (c->isInsertionConstraint() && !c->cleared()) {
438 : #ifdef DEBUG_SIGNALSTATE
439 : if (DEBUG_HELPER(rs)) {
440 : std::cout << SIMTIME << " rsl=" << rs->getID() << " insertion constraint '" << c->getDescription() << "' for vehicle '" << veh->getID() << "' not cleared\n";
441 : }
442 : #endif
443 6216 : info = c->getDescription();
444 3108 : isInsertionOrder = c->getType() == MSRailSignalConstraint::ConstraintType::INSERTION_ORDER;
445 3108 : if (MSGlobals::gTimeToTeleportRSDeadlock > 0) {
446 3108 : const SUMOVehicle* foe = c->getFoe();
447 3108 : if (foe != nullptr) {
448 3108 : MSRailSignalControl::getInstance().addWaitRelation(veh, rs, foe, c);
449 : }
450 : }
451 : return true;
452 : }
453 : }
454 : }
455 : }
456 : }
457 : return false;
458 : }
459 :
460 : // ===========================================================================
461 : // LinkInfo method definitions
462 : // ===========================================================================
463 :
464 5823 : MSRailSignal::LinkInfo::LinkInfo(MSLink* link):
465 5823 : myLink(link) {
466 5823 : reset();
467 5823 : }
468 :
469 13144 : MSRailSignal::LinkInfo::~LinkInfo() {
470 17474 : for (MSDriveWay* dw : myDriveways) {
471 4330 : delete dw;
472 : }
473 : myDriveways.clear();
474 13144 : }
475 :
476 : void
477 5828 : MSRailSignal::LinkInfo::reset() {
478 5828 : myLastRerouteTime = -1;
479 5828 : myLastRerouteVehicle = nullptr;
480 : myDriveways.clear();
481 8535 : myControlled = isRailwayOrShared(myLink->getViaLaneOrLane()->getPermissions())
482 5828 : && isRailwayOrShared(myLink->getLane()->getPermissions());
483 5828 : }
484 :
485 :
486 : std::string
487 6 : MSRailSignal::LinkInfo::getID() const {
488 12 : return myLink->getTLLogic()->getID() + "_" + toString(myLink->getTLIndex());
489 : }
490 :
491 :
492 : MSDriveWay&
493 3909946 : MSRailSignal::LinkInfo::getDriveWay(const SUMOVehicle* veh, int searchStart) {
494 3909946 : MSEdge* first = &myLink->getLane()->getEdge();
495 3909946 : auto searchStartIt = searchStart < 0 ? veh->getCurrentRouteEdge() : veh->getRoute().begin() + searchStart;
496 3909946 : MSRouteIterator firstIt = std::find(searchStartIt, veh->getRoute().end(), first);
497 3909946 : if (firstIt == veh->getRoute().end()) {
498 : // possibly the vehicle has already gone past the first edge (i.e.
499 : // because first is short or the step-length is high)
500 : // lets look backward along the route
501 : // give some slack because the vehicle might have been braking from a higher speed and using ballistic integration
502 121 : double lookBack = SPEED2DIST(veh->getSpeed() + 10);
503 121 : int routeIndex = veh->getRoutePosition() - 1;
504 139 : while (lookBack > 0 && routeIndex > 0) {
505 127 : const MSEdge* prevEdge = veh->getRoute().getEdges()[routeIndex];
506 127 : if (prevEdge == first) {
507 109 : firstIt = veh->getRoute().begin() + routeIndex;
508 109 : break;
509 : }
510 18 : lookBack -= prevEdge->getLength();
511 18 : routeIndex--;
512 : }
513 : }
514 3909946 : MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(myLink->getTLLogic()));
515 3909946 : if (firstIt == veh->getRoute().end()) {
516 48 : WRITE_WARNING("Invalid approach information to rail signal '" + MSDriveWay::getClickableTLLinkID(myLink) + "' after rerouting for vehicle '" + veh->getID()
517 : + "' first driveway edge '" + first->getID() + "' time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
518 12 : if (myDriveways.empty()) {
519 : ConstMSEdgeVector dummyRoute;
520 0 : dummyRoute.push_back(&myLink->getLane()->getEdge());
521 0 : MSDriveWay* dw = MSDriveWay::buildDriveWay(rs->getNewDrivewayID(), myLink, dummyRoute.begin(), dummyRoute.end());
522 0 : myDriveways.push_back(dw);
523 0 : }
524 12 : return *myDriveways.front();
525 : }
526 : //std::cout << SIMTIME << " veh=" << veh->getID() << " rsl=" << getID() << " dws=" << myDriveways.size() << "\n";
527 3909934 : return getDriveWay(firstIt, veh->getRoute().end(), veh->getID());
528 : }
529 :
530 :
531 : MSDriveWay&
532 3909934 : MSRailSignal::LinkInfo::getDriveWay(MSRouteIterator firstIt, MSRouteIterator endIt, const std::string& info) {
533 3946979 : for (MSDriveWay* dw : myDriveways) {
534 3942649 : if (dw->match(firstIt, endIt)) {
535 : return *dw;
536 : }
537 : #ifdef DEBUG_SELECT_DRIVEWAY
538 : std::cout << SIMTIME << " rs=" << getID() << " veh=" << info << " other dwSignal=" << dw->foundSignal() << " dwRoute=" << toString(dw->getRoute()) << "\n";
539 : #else
540 : UNUSED_PARAMETER(info);
541 : #endif
542 : }
543 4330 : MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(myLink->getTLLogic()));
544 4330 : MSDriveWay* dw = MSDriveWay::buildDriveWay(rs->getNewDrivewayID(), myLink, firstIt, endIt);
545 : dw->setVehicle(info);
546 : #ifdef DEBUG_SELECT_DRIVEWAY
547 : std::cout << SIMTIME << " rs=" << getID() << " veh=" << info << " new dwSignal=" << dw->foundSignal() << " dwRoute=" << toString(dw->getRoute()) << "\n";
548 : #endif
549 4330 : myDriveways.push_back(dw);
550 4330 : return *myDriveways.back();
551 : }
552 :
553 :
554 : void
555 232694 : MSRailSignal::LinkInfo::reroute(SUMOVehicle* veh, const MSEdgeVector& occupied) {
556 232694 : MSDevice_Routing* rDev = static_cast<MSDevice_Routing*>(veh->getDevice(typeid(MSDevice_Routing)));
557 232694 : const SUMOTime now = MSNet::getInstance()->getCurrentTimeStep();
558 : if (rDev != nullptr
559 141365 : && rDev->mayRerouteRailSignal()
560 232853 : && (myLastRerouteVehicle != veh
561 : // reroute each vehicle only once if no periodic routing is allowed,
562 : // otherwise with the specified period
563 153 : || (rDev->getPeriod() > 0 && myLastRerouteTime + rDev->getPeriod() <= now))) {
564 6 : myLastRerouteVehicle = veh;
565 6 : myLastRerouteTime = now;
566 :
567 : #ifdef DEBUG_REROUTE
568 : ConstMSEdgeVector oldRoute = veh->getRoute().getEdges();
569 : if (DEBUG_COND_LINKINFO) {
570 : std::cout << SIMTIME << " reroute veh=" << veh->getID() << " rs=" << getID() << " occupied=" << toString(occupied) << "\n";
571 : }
572 : #endif
573 : std::map<const MSEdge*, double> prohibited;
574 18 : for (MSEdge* e : occupied) {
575 : // indefinite occupation because vehicles might be in deadlock on their current routes
576 12 : prohibited[e] = -1;
577 : }
578 18 : MSRoutingEngine::reroute(*veh, now, "railSignal:" + getID(), false, true, prohibited);
579 : #ifdef DEBUG_REROUTE
580 : // attention this works only if we are not parallel!
581 : if (DEBUG_COND_LINKINFO) {
582 : if (veh->getRoute().getEdges() != oldRoute) {
583 : std::cout << " rerouting successful\n";
584 : }
585 : }
586 : #endif
587 : }
588 232694 : }
589 :
590 : void
591 18352 : MSRailSignal::resetStored() {
592 : myBlockingVehicles.clear();
593 : myRivalVehicles.clear();
594 : myPriorityVehicles.clear();
595 : myConstraintInfo = "";
596 : myBlockingDriveWays.clear();
597 : myRequestedDriveWay = "";
598 18352 : }
599 :
600 :
601 : void
602 0 : MSRailSignal::storeTraCIVehicles(const MSDriveWay* dw) {
603 0 : resetStored();
604 0 : myStoreVehicles = true;
605 : MSEdgeVector occupied;
606 : // call for side effects
607 0 : dw->foeDriveWayOccupied(true, nullptr, occupied);
608 0 : myStoreVehicles = false;
609 0 : }
610 :
611 : void
612 18352 : MSRailSignal::storeTraCIVehicles(int linkIndex) {
613 18352 : resetStored();
614 18352 : myStoreVehicles = true;
615 18352 : LinkInfo& li = myLinkInfos[linkIndex];
616 18352 : if (li.myLink->getApproaching().size() > 0) {
617 1825 : Approaching closest = li.myLink->getClosest();
618 1825 : MSDriveWay& driveway = li.getDriveWay(closest.first);
619 : MSEdgeVector occupied;
620 : myRequestedDriveWay = driveway.getID();
621 : // call for side effects
622 1825 : driveway.reserve(closest, occupied);
623 1825 : constraintsAllow(closest.first);
624 18352 : } else if (li.myDriveways.size() > 0) {
625 16035 : li.myDriveways.front()->conflictLaneOccupied();
626 16035 : li.myDriveways.front()->foeDriveWayApproached();
627 : }
628 18352 : myStoreVehicles = false;
629 18352 : }
630 :
631 : MSRailSignal::VehicleVector
632 6124 : MSRailSignal::getBlockingVehicles(int linkIndex) {
633 6124 : storeTraCIVehicles(linkIndex);
634 6124 : return myBlockingVehicles;
635 : }
636 :
637 : MSRailSignal::VehicleVector
638 6114 : MSRailSignal::getRivalVehicles(int linkIndex) {
639 6114 : storeTraCIVehicles(linkIndex);
640 6114 : return myRivalVehicles;
641 : }
642 :
643 : MSRailSignal::VehicleVector
644 6114 : MSRailSignal::getPriorityVehicles(int linkIndex) {
645 6114 : storeTraCIVehicles(linkIndex);
646 6114 : return myPriorityVehicles;
647 : }
648 :
649 : std::string
650 0 : MSRailSignal::getConstraintInfo(int linkIndex) {
651 0 : storeTraCIVehicles(linkIndex);
652 0 : return myConstraintInfo;
653 : }
654 :
655 :
656 : std::string
657 0 : MSRailSignal::getRequestedDriveWay(int linkIndex) {
658 0 : storeTraCIVehicles(linkIndex);
659 0 : return myRequestedDriveWay;
660 : }
661 :
662 :
663 : std::vector<const MSDriveWay*>
664 0 : MSRailSignal::getBlockingDriveWays(int linkIndex) {
665 0 : storeTraCIVehicles(linkIndex);
666 0 : return myBlockingDriveWays;
667 : }
668 :
669 :
670 : MSRailSignal::VehicleVector
671 0 : MSRailSignal::getBlockingVehicles(const MSDriveWay* dw) {
672 0 : storeTraCIVehicles(dw);
673 0 : return myBlockingVehicles;
674 : }
675 :
676 :
677 : std::vector<const MSDriveWay*>
678 0 : MSRailSignal::getBlockingDriveWays(const MSDriveWay* dw) {
679 0 : storeTraCIVehicles(dw);
680 0 : return myBlockingDriveWays;
681 : }
682 :
683 : const MSDriveWay&
684 0 : MSRailSignal::retrieveDriveWay(int numericalID) const {
685 0 : for (const LinkInfo& li : myLinkInfos) {
686 0 : for (const MSDriveWay* dw : li.myDriveways) {
687 0 : if (dw->getNumericalID() == numericalID) {
688 0 : return *dw;
689 : }
690 : }
691 : }
692 0 : throw ProcessError("Invalid driveway id " + toString(numericalID) + " at railSignal '" + getID() + "'");
693 : }
694 :
695 : const MSDriveWay&
696 40748 : MSRailSignal::retrieveDriveWayForVeh(int tlIndex, const SUMOVehicle* veh) {
697 40748 : return myLinkInfos[tlIndex].getDriveWay(veh);
698 : }
699 :
700 : const MSDriveWay&
701 0 : MSRailSignal::retrieveDriveWayForRoute(int tlIndex, MSRouteIterator first, MSRouteIterator end) {
702 0 : return myLinkInfos[tlIndex].getDriveWay(first, end);
703 : }
704 :
705 :
706 : const std::vector<MSDriveWay*>
707 10186 : MSRailSignal::retrieveDriveWays(int tlIndex) const {
708 10186 : return myLinkInfos[tlIndex].myDriveways;
709 : }
710 :
711 :
712 : std::string
713 0 : MSRailSignal::getBlockingVehicleIDs() const {
714 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
715 0 : if (myLinkInfos.size() == 1) {
716 0 : return toString(rs->getBlockingVehicles(0));
717 : } else {
718 : std::string result;
719 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
720 0 : result += toString(i) + ": " + toString(rs->getBlockingVehicles(i)) + ";";
721 : }
722 0 : return result;
723 : }
724 : }
725 : std::string
726 0 : MSRailSignal::getRivalVehicleIDs() const {
727 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
728 0 : if (myLinkInfos.size() == 1) {
729 0 : return toString(rs->getRivalVehicles(0));
730 : } else {
731 : std::string result;
732 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
733 0 : result += toString(i) + ": " + toString(rs->getRivalVehicles(i)) + ";";
734 : }
735 0 : return result;
736 : }
737 : }
738 : std::string
739 0 : MSRailSignal::getPriorityVehicleIDs() const {
740 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
741 0 : if (myLinkInfos.size() == 1) {
742 0 : return toString(rs->getPriorityVehicles(0));
743 : } else {
744 : std::string result;
745 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
746 0 : result += toString(i) + ": " + toString(rs->getPriorityVehicles(i)) + ";";
747 : }
748 0 : return result;
749 : }
750 : }
751 : std::string
752 0 : MSRailSignal::getConstraintInfo() const {
753 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
754 0 : if (myLinkInfos.size() == 1) {
755 0 : return rs->getConstraintInfo(0);
756 : } else {
757 : std::string result;
758 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
759 0 : result += toString(i) + ": " + rs->getConstraintInfo(i);
760 : }
761 0 : return result;
762 : }
763 : }
764 : std::string
765 0 : MSRailSignal::getRequestedDriveWay() const {
766 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
767 0 : if (myLinkInfos.size() == 1) {
768 0 : return toString(rs->getRequestedDriveWay(0));
769 : } else {
770 : std::string result;
771 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
772 0 : result += toString(i) + ": " + toString(rs->getRequestedDriveWay(i)) + ";";
773 : }
774 0 : return result;
775 : }
776 : }
777 : std::string
778 0 : MSRailSignal::getBlockingDriveWayIDs() const {
779 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
780 0 : if (myLinkInfos.size() == 1) {
781 0 : return toString(rs->getBlockingDriveWays(0));
782 : } else {
783 : std::string result;
784 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
785 0 : result += toString(i) + ": " + toString(rs->getBlockingDriveWays(i)) + ";";
786 : }
787 0 : return result;
788 : }
789 : }
790 :
791 : void
792 5 : MSRailSignal::setParameter(const std::string& key, const std::string& value) {
793 : // some pre-defined parameters can be updated at runtime
794 5 : if (key == "moving-block") {
795 5 : bool movingBlock = StringUtils::toBool(value);
796 5 : if (movingBlock != myMovingBlock) {
797 : // recompute driveways
798 5 : myMovingBlock = movingBlock;
799 10 : for (LinkInfo& li : myLinkInfos) {
800 5 : li.reset();
801 : }
802 5 : updateCurrentPhase();
803 5 : setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
804 : }
805 : }
806 5 : Parameterised::setParameter(key, value);
807 5 : }
808 :
809 :
810 : std::string
811 4330 : MSRailSignal::getNewDrivewayID() {
812 8660 : return getID() + "." + toString(myDriveWayIndex++);
813 : }
814 : /****************************************************************************/
|