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 4597 : MSRailSignal::MSRailSignal(MSTLLogicControl& tlcontrol,
80 : const std::string& id, const std::string& programID, SUMOTime delay,
81 4597 : const Parameterised::Map& parameters) :
82 : MSTrafficLightLogic(tlcontrol, id, programID, 0, TrafficLightType::RAIL_SIGNAL, delay, parameters),
83 4597 : myNumericalID(myRSIndex++),
84 13791 : myCurrentPhase(DELTA_T, std::string(SUMO_MAX_CONNECTIONS, 'X')), // dummy phase
85 4597 : myPhaseIndex(0),
86 4597 : myDriveWayIndex(0) {
87 4597 : myDefaultCycleTime = DELTA_T;
88 4597 : myMovingBlock = OptionsCont::getOptions().getBool("railsignal-moving-block");
89 4597 : mySwitchCommand->deschedule(this);
90 4597 : }
91 :
92 : void
93 4597 : MSRailSignal::init(NLDetectorBuilder&) {
94 4597 : if (myLanes.size() == 0) {
95 9 : WRITE_WARNINGF(TL("Rail signal at junction '%' does not control any links"), getID());
96 : }
97 10416 : for (LinkVector& links : myLinks) { //for every link index
98 5819 : 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 11638 : myLinkInfos.push_back(LinkInfo(links[0]));
103 : }
104 4597 : updateCurrentPhase();
105 4597 : setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
106 4597 : myNumLinks = (int)myLinks.size();
107 4597 : MSRailSignalControl::getInstance().addSignal(this);
108 4597 : }
109 :
110 :
111 9182 : MSRailSignal::~MSRailSignal() {
112 4591 : removeConstraints();
113 9182 : }
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 16200332 : 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 47468154 : for (LinkInfo& li : myLinkInfos) {
143 31267822 : if (li.myLink->getApproaching().size() > 0 && li.myControlled) {
144 : keepActive = true;
145 8098059 : Approaching closest = li.myLink->getClosest();
146 8098059 : 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 8098059 : const bool mustWait = !constraintsAllow(closest.first, true);
150 : MSEdgeVector occupied;
151 8098059 : if (mustWait || !driveway.reserve(closest, occupied)) {
152 7746570 : state[li.myLink->getTLIndex()] = 'r';
153 7746570 : if (occupied.size() > 0) {
154 232457 : 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 351489 : 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 31267822 : } else if (li.myControlled) {
170 23169401 : 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 15019112 : state[li.myLink->getTLIndex()] = 'r';
177 : } else {
178 8150289 : const MSDriveWay& driveway = *li.myDriveways.front();
179 : MSEdgeVector occupied;
180 8150289 : 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 8102118 : 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 8150289 : }
196 : } else {
197 362 : state[li.myLink->getTLIndex()] = 'O';
198 : }
199 : }
200 16200332 : if (myCurrentPhase.getState() != state) {
201 : myCurrentPhase.setState(state);
202 31876 : myPhaseIndex = 1 - myPhaseIndex;
203 : // set link priorities
204 31876 : 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 16200332 : return keepActive;
213 : }
214 :
215 :
216 : bool
217 8123411 : MSRailSignal::constraintsAllow(const SUMOVehicle* veh, bool storeWaitRelation) const {
218 8123411 : if (myConstraints.size() == 0) {
219 : return true;
220 : } else {
221 15082482 : const std::string tripID = veh->getParameter().getParameter("tripId", veh->getID());
222 : auto it = myConstraints.find(tripID);
223 7541241 : if (it != myConstraints.end()) {
224 7556984 : for (MSRailSignalConstraint* c : it->second) {
225 : // ignore insertion constraints here
226 7535869 : 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 7506874 : if (storeWaitRelation && MSGlobals::gTimeToTeleportRSDeadlock > 0
233 7532322 : && 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 7515005 : if (myStoreVehicles) {
240 0 : myConstraintInfo = c->getDescription();
241 : }
242 : return false;
243 : }
244 : }
245 : }
246 26236 : 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 216 : MSRailSignal::removeConstraint(const std::string& tripId, MSRailSignalConstraint* constraint) {
259 : if (myConstraints.count(tripId) != 0) {
260 216 : auto& constraints = myConstraints[tripId];
261 216 : auto it = std::find(constraints.begin(), constraints.end(), constraint);
262 216 : if (it != constraints.end()) {
263 216 : delete *it;
264 : constraints.erase(it);
265 : return true;
266 : }
267 : }
268 : return false;
269 : }
270 :
271 : void
272 4615 : MSRailSignal::removeConstraints() {
273 5405 : for (auto item : myConstraints) {
274 1509 : for (MSRailSignalConstraint* c : item.second) {
275 719 : delete c;
276 : }
277 : }
278 : myConstraints.clear();
279 4615 : }
280 :
281 :
282 : // ------------ Static Information Retrieval
283 : int
284 0 : MSRailSignal::getPhaseNumber() const {
285 0 : return 0;
286 : }
287 :
288 : const MSTrafficLightLogic::Phases&
289 4597 : MSRailSignal::getPhases() const {
290 4597 : 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 16308344 : MSRailSignal::getCurrentPhaseDef() const {
306 16308344 : 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 5819 : MSRailSignal::addLink(MSLink* link, MSLane* lane, int pos) {
328 5819 : if (pos >= 0) {
329 5819 : MSTrafficLightLogic::addLink(link, lane, pos);
330 : } // ignore uncontrolled link
331 5819 : }
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 3529 : MSRailSignal::initDriveWays(const SUMOVehicle* ego, bool update) {
369 3529 : const ConstMSEdgeVector& edges = ego->getRoute().getEdges();
370 3529 : int endIndex = ego->getParameter().arrivalEdge;
371 3529 : if (endIndex < 0) {
372 3526 : endIndex = (int)edges.size() - 1;
373 : }
374 3529 : int departIndex = ego->getParameter().departEdge;
375 : MSDriveWay* prev = nullptr;
376 3529 : if (update && ego->hasDeparted()) {
377 : // find last rail signal on the route and obtain the driveway
378 780 : const MSEdge* next = ego->getEdge();
379 953 : for (int i = ego->getRoutePosition() - 1; i > departIndex; i--) {
380 817 : const MSEdge* e = ego->getRoute().getEdges()[i];
381 817 : if (e->getToJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
382 646 : const MSLink* link = e->getLanes().front()->getLinkTo(next->getLanes().front());
383 : //std::cout << SIMTIME << " veh=" << ego->getID() << " rp=" << ego->getRoutePosition()
384 : // << " i=" << i << " e=" << e->getID() << " next=" << next->getID() << " link=" << (link == nullptr ? "NUL" : link->getDescription()) << "\n";
385 646 : if (link != nullptr && link->isTLSControlled()) {
386 644 : MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(link->getTLLogic()));
387 644 : LinkInfo& li = rs->myLinkInfos[link->getTLIndex()];
388 644 : prev = &li.getDriveWay(ego, i);
389 644 : departIndex = ego->getRoutePosition();
390 644 : break;
391 : }
392 : }
393 : next = e;
394 : }
395 : }
396 780 : if (prev == nullptr) {
397 2885 : prev = const_cast<MSDriveWay*>(MSDriveWay::getDepartureDriveway(ego, true));
398 : }
399 3529 : if (update && ego->hasDeparted()) {
400 780 : MSBaseVehicle* veh = dynamic_cast<MSBaseVehicle*>(const_cast<SUMOVehicle*>(ego));
401 780 : if (!prev->hasTrain(veh) && prev->notifyEnter(*veh, prev->NOTIFICATION_REROUTE, nullptr) && !veh->hasReminder(prev)) {
402 57 : veh->addReminder(prev, 1);
403 : }
404 : }
405 60608 : for (int i = departIndex; i <= endIndex - 1; i++) {
406 57079 : const MSEdge* e = edges[i];
407 57079 : if (e->isNormal() && e->getToJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
408 37870 : const MSEdge* e2 = edges[i + 1];
409 75740 : for (MSLane* lane : e->getLanes()) {
410 76686 : for (MSLink* link : lane->getLinkCont()) {
411 38816 : if (&link->getLane()->getEdge() == e2) {
412 37849 : MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(link->getTLLogic()));
413 35287 : if (rs != nullptr) {
414 35287 : LinkInfo& li = rs->myLinkInfos[link->getTLIndex()];
415 : // init driveway
416 35287 : MSDriveWay* dw = &li.getDriveWay(ego, i);
417 35287 : MSRailSignalControl::getInstance().addDrivewayFollower(prev, dw);
418 35287 : MSRailSignalControl::getInstance().addDWDeadlockChecks(rs, prev);
419 35287 : MSRailSignalControl::getInstance().notifyApproach(link);
420 : prev = dw;
421 35287 : if (update && rs->isActive()) {
422 : // vehicle may have rerouted its intial trip
423 : // after the states have been set
424 : // @note: This is a hack because it could lead to invalid tls-output
425 : // (it's still an improvement over switching based on default driveways)
426 33014 : if (!ego->hasDeparted()) {
427 8306 : rs->updateCurrentPhase();
428 8306 : rs->setTrafficLightSignals(SIMSTEP);
429 24708 : } else if (ego->hasDeparted() && i <= ego->getRoutePosition()) {
430 775 : MSBaseVehicle* veh = dynamic_cast<MSBaseVehicle*>(const_cast<SUMOVehicle*>(ego));
431 775 : if (!dw->hasTrain(veh) && dw->notifyEnter(*veh, dw->NOTIFICATION_REROUTE, nullptr) && !veh->hasReminder(dw)) {
432 20 : veh->addReminder(dw, 1);
433 30 : for (MSDriveWay* sub : dw->getSubDriveWays()) {
434 10 : if (!sub->hasTrain(veh) && sub->notifyEnter(*veh, dw->NOTIFICATION_REROUTE, nullptr) && !veh->hasReminder(sub)) {
435 0 : veh->addReminder(sub, 1);
436 : }
437 : }
438 : }
439 : }
440 : }
441 : }
442 : }
443 : }
444 : }
445 : }
446 : }
447 3529 : }
448 :
449 :
450 : bool
451 16365 : MSRailSignal::hasInsertionConstraint(MSLink* link, const MSVehicle* veh, std::string& info, bool& isInsertionOrder) {
452 16365 : if (link->getJunction() != nullptr && link->getJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
453 5075 : const MSRailSignal* rs = dynamic_cast<const MSRailSignal*>(link->getTLLogic());
454 4876 : if (rs != nullptr && rs->myConstraints.size() > 0) {
455 6906 : const std::string tripID = veh->getParameter().getParameter("tripId", veh->getID());
456 : auto it = rs->myConstraints.find(tripID);
457 3453 : if (it != rs->myConstraints.end()) {
458 3670 : for (MSRailSignalConstraint* c : it->second) {
459 3375 : if (c->isInsertionConstraint() && !c->cleared()) {
460 : #ifdef DEBUG_SIGNALSTATE
461 : if (DEBUG_HELPER(rs)) {
462 : std::cout << SIMTIME << " rsl=" << rs->getID() << " insertion constraint '" << c->getDescription() << "' for vehicle '" << veh->getID() << "' not cleared\n";
463 : }
464 : #endif
465 6216 : info = c->getDescription();
466 3108 : isInsertionOrder = c->getType() == MSRailSignalConstraint::ConstraintType::INSERTION_ORDER;
467 3108 : if (MSGlobals::gTimeToTeleportRSDeadlock > 0) {
468 3108 : const SUMOVehicle* foe = c->getFoe();
469 3108 : if (foe != nullptr) {
470 3108 : MSRailSignalControl::getInstance().addWaitRelation(veh, rs, foe, c);
471 : }
472 : }
473 : return true;
474 : }
475 : }
476 : }
477 : }
478 : }
479 : return false;
480 : }
481 :
482 : // ===========================================================================
483 : // LinkInfo method definitions
484 : // ===========================================================================
485 :
486 5819 : MSRailSignal::LinkInfo::LinkInfo(MSLink* link):
487 5819 : myLink(link) {
488 5819 : reset();
489 5819 : }
490 :
491 13130 : MSRailSignal::LinkInfo::~LinkInfo() {
492 17450 : for (MSDriveWay* dw : myDriveways) {
493 4320 : delete dw;
494 : }
495 : myDriveways.clear();
496 13130 : }
497 :
498 : void
499 5824 : MSRailSignal::LinkInfo::reset() {
500 5824 : myLastRerouteTime = -1;
501 5824 : myLastRerouteVehicle = nullptr;
502 : myDriveways.clear();
503 8531 : myControlled = isRailwayOrShared(myLink->getViaLaneOrLane()->getPermissions())
504 5824 : && isRailwayOrShared(myLink->getLane()->getPermissions());
505 5824 : }
506 :
507 :
508 : std::string
509 6 : MSRailSignal::LinkInfo::getID() const {
510 12 : return myLink->getTLLogic()->getID() + "_" + toString(myLink->getTLIndex());
511 : }
512 :
513 :
514 : MSDriveWay&
515 8176042 : MSRailSignal::LinkInfo::getDriveWay(const SUMOVehicle* veh, int searchStart) {
516 8176042 : MSEdge* first = &myLink->getLane()->getEdge();
517 8176042 : auto searchStartIt = searchStart < 0 ? veh->getCurrentRouteEdge() : veh->getRoute().begin() + searchStart;
518 8176042 : MSRouteIterator firstIt = std::find(searchStartIt, veh->getRoute().end(), first);
519 8176042 : if (firstIt == veh->getRoute().end()) {
520 : // possibly the vehicle has already gone past the first edge (i.e.
521 : // because first is short or the step-length is high)
522 : // lets look backward along the route
523 : // give some slack because the vehicle might have been braking from a higher speed and using ballistic integration
524 79 : double lookBack = SPEED2DIST(veh->getSpeed() + 10);
525 79 : int routeIndex = veh->getRoutePosition() - 1;
526 85 : while (lookBack > 0 && routeIndex > 0) {
527 85 : const MSEdge* prevEdge = veh->getRoute().getEdges()[routeIndex];
528 85 : if (prevEdge == first) {
529 79 : firstIt = veh->getRoute().begin() + routeIndex;
530 79 : break;
531 : }
532 6 : lookBack -= prevEdge->getLength();
533 6 : routeIndex--;
534 : }
535 : }
536 8176042 : MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(myLink->getTLLogic()));
537 8176042 : if (firstIt == veh->getRoute().end()) {
538 0 : WRITE_WARNING("Invalid approach information to rail signal '" + MSDriveWay::getClickableTLLinkID(myLink) + "' after rerouting for vehicle '" + veh->getID()
539 : + "' first driveway edge '" + first->getID() + "' time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
540 0 : if (myDriveways.empty()) {
541 : ConstMSEdgeVector dummyRoute;
542 0 : dummyRoute.push_back(&myLink->getLane()->getEdge());
543 0 : MSDriveWay* dw = MSDriveWay::buildDriveWay(rs->getNewDrivewayID(), myLink, dummyRoute.begin(), dummyRoute.end());
544 0 : myDriveways.push_back(dw);
545 0 : }
546 0 : return *myDriveways.front();
547 : }
548 : //std::cout << SIMTIME << " veh=" << veh->getID() << " rsl=" << getID() << " dws=" << myDriveways.size() << "\n";
549 8176042 : return getDriveWay(firstIt, veh->getRoute().end(), veh->getID());
550 : }
551 :
552 :
553 : MSDriveWay&
554 8176042 : MSRailSignal::LinkInfo::getDriveWay(MSRouteIterator firstIt, MSRouteIterator endIt, const std::string& info) {
555 8212952 : for (MSDriveWay* dw : myDriveways) {
556 8208627 : if (dw->match(firstIt, endIt)) {
557 : return *dw;
558 : }
559 : #ifdef DEBUG_SELECT_DRIVEWAY
560 : std::cout << SIMTIME << " rs=" << getID() << " veh=" << info << " other dwSignal=" << dw->foundSignal() << " dwRoute=" << toString(dw->getRoute()) << "\n";
561 : #else
562 : UNUSED_PARAMETER(info);
563 : #endif
564 : }
565 4325 : MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(myLink->getTLLogic()));
566 4325 : MSDriveWay* dw = MSDriveWay::buildDriveWay(rs->getNewDrivewayID(), myLink, firstIt, endIt);
567 : dw->setVehicle(info);
568 : #ifdef DEBUG_SELECT_DRIVEWAY
569 : std::cout << SIMTIME << " rs=" << getID() << " veh=" << info << " new dwSignal=" << dw->foundSignal() << " dwRoute=" << toString(dw->getRoute()) << "\n";
570 : #endif
571 4325 : myDriveways.push_back(dw);
572 4325 : return *myDriveways.back();
573 : }
574 :
575 :
576 : void
577 232457 : MSRailSignal::LinkInfo::reroute(SUMOVehicle* veh, const MSEdgeVector& occupied) {
578 232457 : MSDevice_Routing* rDev = static_cast<MSDevice_Routing*>(veh->getDevice(typeid(MSDevice_Routing)));
579 232457 : const SUMOTime now = MSNet::getInstance()->getCurrentTimeStep();
580 : if (rDev != nullptr
581 141304 : && rDev->mayRerouteRailSignal()
582 232616 : && (myLastRerouteVehicle != veh
583 : // reroute each vehicle only once if no periodic routing is allowed,
584 : // otherwise with the specified period
585 153 : || (rDev->getPeriod() > 0 && myLastRerouteTime + rDev->getPeriod() <= now))) {
586 6 : myLastRerouteVehicle = veh;
587 6 : myLastRerouteTime = now;
588 :
589 : #ifdef DEBUG_REROUTE
590 : ConstMSEdgeVector oldRoute = veh->getRoute().getEdges();
591 : if (DEBUG_COND_LINKINFO) {
592 : std::cout << SIMTIME << " reroute veh=" << veh->getID() << " rs=" << getID() << " occupied=" << toString(occupied) << "\n";
593 : }
594 : #endif
595 : std::map<const MSEdge*, double> prohibited;
596 18 : for (MSEdge* e : occupied) {
597 : // indefinite occupation because vehicles might be in deadlock on their current routes
598 12 : prohibited[e] = -1;
599 : }
600 18 : MSRoutingEngine::reroute(*veh, now, "railSignal:" + getID(), false, true, prohibited);
601 : #ifdef DEBUG_REROUTE
602 : // attention this works only if we are not parallel!
603 : if (DEBUG_COND_LINKINFO) {
604 : if (veh->getRoute().getEdges() != oldRoute) {
605 : std::cout << " rerouting successful\n";
606 : }
607 : }
608 : #endif
609 : }
610 232457 : }
611 :
612 : void
613 18352 : MSRailSignal::resetStored() {
614 : myBlockingVehicles.clear();
615 : myRivalVehicles.clear();
616 : myPriorityVehicles.clear();
617 : myConstraintInfo = "";
618 : myBlockingDriveWays.clear();
619 : myRequestedDriveWay = "";
620 18352 : }
621 :
622 :
623 : void
624 0 : MSRailSignal::storeTraCIVehicles(const MSDriveWay* dw) {
625 0 : resetStored();
626 0 : myStoreVehicles = true;
627 : MSEdgeVector occupied;
628 : // call for side effects
629 0 : dw->foeDriveWayOccupied(true, nullptr, occupied);
630 0 : myStoreVehicles = false;
631 0 : }
632 :
633 : void
634 18352 : MSRailSignal::storeTraCIVehicles(int linkIndex) {
635 18352 : resetStored();
636 18352 : myStoreVehicles = true;
637 18352 : LinkInfo& li = myLinkInfos[linkIndex];
638 18352 : if (li.myLink->getApproaching().size() > 0) {
639 1825 : Approaching closest = li.myLink->getClosest();
640 1825 : MSDriveWay& driveway = li.getDriveWay(closest.first);
641 : MSEdgeVector occupied;
642 : myRequestedDriveWay = driveway.getID();
643 : // call for side effects
644 1825 : driveway.reserve(closest, occupied);
645 1825 : constraintsAllow(closest.first);
646 18352 : } else if (li.myDriveways.size() > 0) {
647 16035 : li.myDriveways.front()->conflictLaneOccupied();
648 16035 : li.myDriveways.front()->foeDriveWayApproached();
649 : }
650 18352 : myStoreVehicles = false;
651 18352 : }
652 :
653 : MSRailSignal::VehicleVector
654 6124 : MSRailSignal::getBlockingVehicles(int linkIndex) {
655 6124 : storeTraCIVehicles(linkIndex);
656 6124 : return myBlockingVehicles;
657 : }
658 :
659 : MSRailSignal::VehicleVector
660 6114 : MSRailSignal::getRivalVehicles(int linkIndex) {
661 6114 : storeTraCIVehicles(linkIndex);
662 6114 : return myRivalVehicles;
663 : }
664 :
665 : MSRailSignal::VehicleVector
666 6114 : MSRailSignal::getPriorityVehicles(int linkIndex) {
667 6114 : storeTraCIVehicles(linkIndex);
668 6114 : return myPriorityVehicles;
669 : }
670 :
671 : std::string
672 0 : MSRailSignal::getConstraintInfo(int linkIndex) {
673 0 : storeTraCIVehicles(linkIndex);
674 0 : return myConstraintInfo;
675 : }
676 :
677 :
678 : std::string
679 0 : MSRailSignal::getRequestedDriveWay(int linkIndex) {
680 0 : storeTraCIVehicles(linkIndex);
681 0 : return myRequestedDriveWay;
682 : }
683 :
684 :
685 : std::vector<const MSDriveWay*>
686 0 : MSRailSignal::getBlockingDriveWays(int linkIndex) {
687 0 : storeTraCIVehicles(linkIndex);
688 0 : return myBlockingDriveWays;
689 : }
690 :
691 :
692 : MSRailSignal::VehicleVector
693 0 : MSRailSignal::getBlockingVehicles(const MSDriveWay* dw) {
694 0 : storeTraCIVehicles(dw);
695 0 : return myBlockingVehicles;
696 : }
697 :
698 :
699 : std::vector<const MSDriveWay*>
700 0 : MSRailSignal::getBlockingDriveWays(const MSDriveWay* dw) {
701 0 : storeTraCIVehicles(dw);
702 0 : return myBlockingDriveWays;
703 : }
704 :
705 : const MSDriveWay&
706 0 : MSRailSignal::retrieveDriveWay(int numericalID) const {
707 0 : for (const LinkInfo& li : myLinkInfos) {
708 0 : for (const MSDriveWay* dw : li.myDriveways) {
709 0 : if (dw->getNumericalID() == numericalID) {
710 0 : return *dw;
711 : }
712 : }
713 : }
714 0 : throw ProcessError("Invalid driveway id " + toString(numericalID) + " at railSignal '" + getID() + "'");
715 : }
716 :
717 : const MSDriveWay&
718 40227 : MSRailSignal::retrieveDriveWayForVeh(int tlIndex, const SUMOVehicle* veh) {
719 40227 : return myLinkInfos[tlIndex].getDriveWay(veh);
720 : }
721 :
722 : const MSDriveWay&
723 0 : MSRailSignal::retrieveDriveWayForRoute(int tlIndex, MSRouteIterator first, MSRouteIterator end) {
724 0 : return myLinkInfos[tlIndex].getDriveWay(first, end);
725 : }
726 :
727 :
728 : const std::vector<MSDriveWay*>
729 10181 : MSRailSignal::retrieveDriveWays(int tlIndex) const {
730 10181 : return myLinkInfos[tlIndex].myDriveways;
731 : }
732 :
733 :
734 : std::string
735 0 : MSRailSignal::getBlockingVehicleIDs() const {
736 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
737 0 : if (myLinkInfos.size() == 1) {
738 0 : return toString(rs->getBlockingVehicles(0));
739 : } else {
740 : std::string result;
741 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
742 0 : result += toString(i) + ": " + toString(rs->getBlockingVehicles(i)) + ";";
743 : }
744 0 : return result;
745 : }
746 : }
747 : std::string
748 0 : MSRailSignal::getRivalVehicleIDs() const {
749 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
750 0 : if (myLinkInfos.size() == 1) {
751 0 : return toString(rs->getRivalVehicles(0));
752 : } else {
753 : std::string result;
754 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
755 0 : result += toString(i) + ": " + toString(rs->getRivalVehicles(i)) + ";";
756 : }
757 0 : return result;
758 : }
759 : }
760 : std::string
761 0 : MSRailSignal::getPriorityVehicleIDs() const {
762 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
763 0 : if (myLinkInfos.size() == 1) {
764 0 : return toString(rs->getPriorityVehicles(0));
765 : } else {
766 : std::string result;
767 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
768 0 : result += toString(i) + ": " + toString(rs->getPriorityVehicles(i)) + ";";
769 : }
770 0 : return result;
771 : }
772 : }
773 : std::string
774 0 : MSRailSignal::getConstraintInfo() const {
775 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
776 0 : if (myLinkInfos.size() == 1) {
777 0 : return rs->getConstraintInfo(0);
778 : } else {
779 : std::string result;
780 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
781 0 : result += toString(i) + ": " + rs->getConstraintInfo(i);
782 : }
783 0 : return result;
784 : }
785 : }
786 : std::string
787 0 : MSRailSignal::getRequestedDriveWay() const {
788 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
789 0 : if (myLinkInfos.size() == 1) {
790 0 : return toString(rs->getRequestedDriveWay(0));
791 : } else {
792 : std::string result;
793 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
794 0 : result += toString(i) + ": " + toString(rs->getRequestedDriveWay(i)) + ";";
795 : }
796 0 : return result;
797 : }
798 : }
799 : std::string
800 0 : MSRailSignal::getBlockingDriveWayIDs() const {
801 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
802 0 : if (myLinkInfos.size() == 1) {
803 0 : return toString(rs->getBlockingDriveWays(0));
804 : } else {
805 : std::string result;
806 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
807 0 : result += toString(i) + ": " + toString(rs->getBlockingDriveWays(i)) + ";";
808 : }
809 0 : return result;
810 : }
811 : }
812 :
813 : void
814 5 : MSRailSignal::setParameter(const std::string& key, const std::string& value) {
815 : // some pre-defined parameters can be updated at runtime
816 5 : if (key == "moving-block") {
817 5 : bool movingBlock = StringUtils::toBool(value);
818 5 : if (movingBlock != myMovingBlock) {
819 : // recompute driveways
820 5 : myMovingBlock = movingBlock;
821 10 : for (LinkInfo& li : myLinkInfos) {
822 5 : li.reset();
823 : }
824 5 : updateCurrentPhase();
825 5 : setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
826 : }
827 : }
828 5 : Parameterised::setParameter(key, value);
829 5 : }
830 :
831 :
832 : std::string
833 4325 : MSRailSignal::getNewDrivewayID() {
834 8650 : return getID() + "." + toString(myDriveWayIndex++);
835 : }
836 : /****************************************************************************/
|