Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2026 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 4697 : MSRailSignal::MSRailSignal(MSTLLogicControl& tlcontrol,
80 : const std::string& id, const std::string& programID, SUMOTime delay,
81 4697 : const Parameterised::Map& parameters) :
82 : MSTrafficLightLogic(tlcontrol, id, programID, 0, TrafficLightType::RAIL_SIGNAL, delay, parameters),
83 4697 : myNumericalID(myRSIndex++),
84 14091 : myCurrentPhase(DELTA_T, std::string(SUMO_MAX_CONNECTIONS, 'X')), // dummy phase
85 4697 : myPhaseIndex(0),
86 4697 : myDriveWayIndex(0) {
87 4697 : myDefaultCycleTime = DELTA_T;
88 4697 : myMovingBlock = OptionsCont::getOptions().getBool("railsignal-moving-block");
89 4697 : mySwitchCommand->deschedule(this);
90 4697 : }
91 :
92 : void
93 4697 : MSRailSignal::init(NLDetectorBuilder&) {
94 4697 : if (myLanes.size() == 0) {
95 9 : WRITE_WARNINGF(TL("Rail signal at junction '%' does not control any links"), getID());
96 : }
97 : SVCPermissions outgoingPermissions = 0;
98 10671 : for (LinkVector& links : myLinks) { //for every link index
99 5974 : 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 11948 : myLinkInfos.push_back(LinkInfo(links[0]));
104 5974 : outgoingPermissions |= links[0]->getPermissions();
105 : }
106 4697 : updateCurrentPhase();
107 4697 : setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
108 4697 : myNumLinks = (int)myLinks.size();
109 4697 : MSRailSignalControl::getInstance().addSignal(this);
110 4697 : myMovingBlock |= MSRailSignalControl::isMovingBlock(outgoingPermissions);
111 4697 : }
112 :
113 :
114 9394 : MSRailSignal::~MSRailSignal() {
115 4697 : removeConstraints();
116 9394 : }
117 :
118 :
119 : // ----------- Handling of controlled links
120 : void
121 0 : MSRailSignal::adaptLinkInformationFrom(const MSTrafficLightLogic& logic) {
122 0 : MSTrafficLightLogic::adaptLinkInformationFrom(logic);
123 0 : updateCurrentPhase();
124 0 : }
125 :
126 :
127 : // ------------ Switching and setting current rows
128 : SUMOTime
129 0 : MSRailSignal::trySwitch() {
130 : // deschedule regular traffic light event,
131 : // updateCurrentPhase is instead called from MSRailSignalControl::updateSignals
132 0 : return SUMOTime_MAX;
133 : }
134 :
135 :
136 :
137 : bool
138 18091955 : MSRailSignal::updateCurrentPhase() {
139 : #ifdef DEBUG_SIGNALSTATE
140 : gDebugFlag4 = DEBUG_COND;
141 : #endif
142 : bool keepActive = false;
143 : // green by default so vehicles can be inserted at the borders of the network
144 : std::string state(myLinks.size(), 'G');
145 53127667 : for (LinkInfo& li : myLinkInfos) {
146 35035712 : if (li.myLink->getApproaching().size() > 0 && li.myControlled) {
147 : keepActive = true;
148 9042109 : Approaching closest = li.myLink->getClosest();
149 9042109 : MSDriveWay& driveway = li.getDriveWay(closest.first);
150 : //std::cout << SIMTIME << " signal=" << getTLLinkID(li.myLink) << " veh=" << closest.first->getID() << " dw:\n";
151 : //driveway.writeBlocks(*OutputDevice_COUT::getDevice());
152 9042109 : const bool mustWait = !constraintsAllow(closest.first, true);
153 : MSEdgeVector occupied;
154 9042109 : if (mustWait || !driveway.reserve(closest, occupied)) {
155 8683962 : state[li.myLink->getTLIndex()] = 'r';
156 8683962 : if (occupied.size() > 0) {
157 232696 : li.reroute(const_cast<SUMOVehicle*>(closest.first), occupied);
158 : }
159 : #ifdef DEBUG_SIGNALSTATE
160 : if (gDebugFlag4) {
161 : std::cout << SIMTIME << " rsl=" << li.getID() << " veh=" << closest.first->getID() << " notReserved\n";
162 : }
163 : #endif
164 : } else {
165 358147 : state[li.myLink->getTLIndex()] = 'G';
166 : #ifdef DEBUG_SIGNALSTATE
167 : if (gDebugFlag4) {
168 : std::cout << SIMTIME << " rsl=" << li.getID() << " veh=" << closest.first->getID() << " reserved\n";
169 : }
170 : #endif
171 : }
172 35035712 : } else if (li.myControlled) {
173 25993241 : if (li.myDriveways.empty()) {
174 : #ifdef DEBUG_SIGNALSTATE
175 : if (gDebugFlag4) {
176 : std::cout << SIMTIME << " rsl=" << li.getID() << " red for unitialized signal (no driveways yet)\n";
177 : }
178 : #endif
179 16895363 : state[li.myLink->getTLIndex()] = 'r';
180 : } else {
181 9097878 : const MSDriveWay& driveway = *li.myDriveways.front();
182 : MSEdgeVector occupied;
183 9097878 : if (driveway.foeDriveWayOccupied(true, nullptr, occupied) || driveway.foeDriveWayApproached()) {
184 : keepActive = true;
185 : #ifdef DEBUG_SIGNALSTATE
186 : if (gDebugFlag4) {
187 : std::cout << SIMTIME << " rsl=" << li.getID() << " red for default driveway " << driveway.getID() << "\n";
188 : }
189 : #endif
190 9050475 : state[li.myLink->getTLIndex()] = 'r';
191 : } else {
192 : #ifdef DEBUG_SIGNALSTATE
193 : if (gDebugFlag4) {
194 : std::cout << SIMTIME << " rsl=" << li.getID() << " green for default driveway " << driveway.getID() << "\n";
195 : }
196 : #endif
197 : }
198 9097878 : }
199 : } else {
200 362 : state[li.myLink->getTLIndex()] = 'O';
201 : }
202 : }
203 18091955 : if (myCurrentPhase.getState() != state) {
204 : myCurrentPhase.setState(state);
205 32284 : myPhaseIndex = 1 - myPhaseIndex;
206 : // set link priorities
207 32284 : setTrafficLightSignals(SIMSTEP);
208 : // execute switch actions (3D-gui)
209 : //const MSTLLogicControl::TLSLogicVariants& vars = myTLControl.get(myTLLogic->getID());
210 : //vars.executeOnSwitchActions();
211 : }
212 : #ifdef DEBUG_SIGNALSTATE
213 : gDebugFlag4 = false;
214 : #endif
215 18091955 : return keepActive;
216 : }
217 :
218 :
219 : bool
220 9068752 : MSRailSignal::constraintsAllow(const SUMOVehicle* veh, bool storeWaitRelation) const {
221 9068752 : if (myConstraints.size() == 0) {
222 : return true;
223 : } else {
224 16959126 : const std::string tripID = veh->getParameter().getParameter("tripId", veh->getID());
225 : auto it = myConstraints.find(tripID);
226 8479563 : if (it != myConstraints.end()) {
227 8495579 : for (MSRailSignalConstraint* c : it->second) {
228 : // ignore insertion constraints here
229 8473783 : if (!c->isInsertionConstraint() && !c->cleared()) {
230 : #ifdef DEBUG_SIGNALSTATE
231 : if (gDebugFlag4) {
232 : std::cout << " constraint '" << c->getDescription() << "' not cleared\n";
233 : }
234 : #endif
235 8443959 : if (storeWaitRelation && MSGlobals::gTimeToTeleportRSDeadlock > 0
236 8469693 : && veh->getWaitingTime() > veh->getVehicleType().getCarFollowModel().getStartupDelay()) {
237 13929 : const SUMOVehicle* foe = c->getFoe();
238 13929 : if (foe != nullptr) {
239 11889 : MSRailSignalControl::getInstance().addWaitRelation(veh, this, foe, c);
240 : }
241 : }
242 8452376 : if (myStoreVehicles) {
243 0 : myConstraintInfo = c->getDescription();
244 : }
245 : return false;
246 : }
247 : }
248 : }
249 27187 : return true;
250 : }
251 : }
252 :
253 :
254 : void
255 934 : MSRailSignal::addConstraint(const std::string& tripId, MSRailSignalConstraint* constraint) {
256 934 : myConstraints[tripId].push_back(constraint);
257 934 : }
258 :
259 :
260 : bool
261 216 : MSRailSignal::removeConstraint(const std::string& tripId, MSRailSignalConstraint* constraint) {
262 : if (myConstraints.count(tripId) != 0) {
263 216 : auto& constraints = myConstraints[tripId];
264 216 : auto it = std::find(constraints.begin(), constraints.end(), constraint);
265 216 : if (it != constraints.end()) {
266 216 : delete *it;
267 : constraints.erase(it);
268 : return true;
269 : }
270 : }
271 : return false;
272 : }
273 :
274 : void
275 4721 : MSRailSignal::removeConstraints() {
276 5510 : for (auto item : myConstraints) {
277 1507 : for (MSRailSignalConstraint* c : item.second) {
278 718 : delete c;
279 : }
280 : }
281 : myConstraints.clear();
282 4721 : }
283 :
284 :
285 : // ------------ Static Information Retrieval
286 : int
287 0 : MSRailSignal::getPhaseNumber() const {
288 0 : return 0;
289 : }
290 :
291 : const MSTrafficLightLogic::Phases&
292 4697 : MSRailSignal::getPhases() const {
293 4697 : return myPhases;
294 : }
295 :
296 : const MSPhaseDefinition&
297 0 : MSRailSignal::getPhase(int) const {
298 0 : return myCurrentPhase;
299 : }
300 :
301 : // ------------ Dynamic Information Retrieval
302 : int
303 29614 : MSRailSignal::getCurrentPhaseIndex() const {
304 29614 : return myPhaseIndex;
305 : }
306 :
307 : const MSPhaseDefinition&
308 18200789 : MSRailSignal::getCurrentPhaseDef() const {
309 18200789 : return myCurrentPhase;
310 : }
311 :
312 :
313 : void
314 1 : MSRailSignal::resetLastSwitch(SUMOTime t) {
315 1 : myCurrentPhase.myLastSwitch = t;
316 1 : }
317 :
318 :
319 : // ------------ Conversion between time and phase
320 : SUMOTime
321 0 : MSRailSignal::getPhaseIndexAtTime(SUMOTime) const {
322 0 : return 0;
323 : }
324 :
325 : SUMOTime
326 0 : MSRailSignal::getOffsetFromIndex(int) const {
327 0 : return 0;
328 : }
329 :
330 : int
331 0 : MSRailSignal::getIndexFromOffset(SUMOTime) const {
332 0 : return 0;
333 : }
334 :
335 :
336 : void
337 5974 : MSRailSignal::addLink(MSLink* link, MSLane* lane, int pos) {
338 5974 : if (pos >= 0) {
339 5974 : MSTrafficLightLogic::addLink(link, lane, pos);
340 : } // ignore uncontrolled link
341 5974 : }
342 :
343 :
344 : std::string
345 0 : MSRailSignal::describeLinks(std::vector<MSLink*> links) {
346 : std::string result;
347 0 : for (MSLink* link : links) {
348 0 : result += link->getDescription() + " ";
349 : }
350 0 : return result;
351 : }
352 :
353 :
354 : void
355 3990 : MSRailSignal::writeBlocks(OutputDevice& od, bool writeVehicles) const {
356 7980 : od.openTag("railSignal");
357 3990 : od.writeAttr(SUMO_ATTR_ID, getID());
358 8577 : for (const LinkInfo& li : myLinkInfos) {
359 4587 : MSLink* link = li.myLink;
360 9174 : od.openTag("link");
361 4587 : od.writeAttr(SUMO_ATTR_TLLINKINDEX, link->getTLIndex());
362 4587 : od.writeAttr(SUMO_ATTR_FROM, link->getLaneBefore()->getID());
363 4587 : od.writeAttr(SUMO_ATTR_TO, link->getViaLaneOrLane()->getID());
364 9150 : for (const MSDriveWay* dw : li.myDriveways) {
365 4563 : if (writeVehicles) {
366 371 : dw->writeBlockVehicles(od);
367 : } else {
368 4192 : dw->writeBlocks(od);
369 : }
370 : }
371 9174 : od.closeTag(); // link
372 : }
373 3990 : od.closeTag(); // railSignal
374 3990 : }
375 :
376 :
377 : void
378 3568 : MSRailSignal::initDriveWays(const SUMOVehicle* ego, bool update) {
379 3568 : const ConstMSEdgeVector& edges = ego->getRoute().getEdges();
380 3568 : int endIndex = ego->getParameter().arrivalEdge;
381 3568 : if (endIndex < 0) {
382 3565 : endIndex = (int)edges.size() - 1;
383 : }
384 3568 : int departIndex = ego->getParameter().departEdge;
385 : MSDriveWay* prev = nullptr;
386 3568 : if (update && ego->hasDeparted()) {
387 : // find last rail signal on the route and obtain the driveway
388 722 : const MSEdge* next = ego->getEdge();
389 880 : for (int i = ego->getRoutePosition() - 1; i > departIndex; i--) {
390 743 : const MSEdge* e = ego->getRoute().getEdges()[i];
391 743 : if (e->getToJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
392 587 : const MSLink* link = e->getLanes().front()->getLinkTo(next->getLanes().front());
393 : //std::cout << SIMTIME << " veh=" << ego->getID() << " rp=" << ego->getRoutePosition()
394 : // << " i=" << i << " e=" << e->getID() << " next=" << next->getID() << " link=" << (link == nullptr ? "NUL" : link->getDescription()) << "\n";
395 587 : if (link != nullptr && link->isTLSControlled()) {
396 585 : MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(link->getTLLogic()));
397 585 : LinkInfo& li = rs->myLinkInfos[link->getTLIndex()];
398 585 : prev = &li.getDriveWay(ego, i);
399 585 : departIndex = ego->getRoutePosition();
400 585 : break;
401 : }
402 : }
403 : next = e;
404 : }
405 : }
406 722 : if (prev == nullptr) {
407 2983 : prev = const_cast<MSDriveWay*>(MSDriveWay::getDepartureDriveway(ego, true));
408 : }
409 3568 : if (update && ego->hasDeparted()) {
410 722 : MSBaseVehicle* veh = dynamic_cast<MSBaseVehicle*>(const_cast<SUMOVehicle*>(ego));
411 722 : if (!prev->hasTrain(veh) && prev->notifyEnter(*veh, prev->NOTIFICATION_REROUTE, nullptr) && !veh->hasReminder(prev)) {
412 644 : veh->addReminder(prev, 1);
413 : }
414 : }
415 57877 : for (int i = departIndex; i <= endIndex - 1; i++) {
416 54309 : const MSEdge* e = edges[i];
417 54309 : if (e->isNormal() && e->getToJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
418 35670 : const MSEdge* e2 = edges[i + 1];
419 71340 : for (MSLane* lane : e->getLanes()) {
420 72287 : for (MSLink* link : lane->getLinkCont()) {
421 36617 : if (&link->getLane()->getEdge() == e2) {
422 35649 : MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(link->getTLLogic()));
423 33173 : if (rs != nullptr) {
424 33173 : LinkInfo& li = rs->myLinkInfos[link->getTLIndex()];
425 : // init driveway
426 33173 : MSDriveWay* dw = &li.getDriveWay(ego, i);
427 33173 : MSRailSignalControl::getInstance().addDrivewayFollower(prev, dw);
428 33173 : MSRailSignalControl::getInstance().addDWDeadlockChecks(rs, prev);
429 33173 : MSRailSignalControl::getInstance().notifyApproach(link);
430 : prev = dw;
431 33173 : if (update && rs->isActive()) {
432 : // vehicle may have rerouted its intial trip
433 : // after the states have been set
434 : // @note: This is a hack because it could lead to invalid tls-output
435 : // (it's still an improvement over switching based on default driveways)
436 30847 : if (!ego->hasDeparted()) {
437 8364 : rs->updateCurrentPhase();
438 8364 : rs->setTrafficLightSignals(SIMSTEP);
439 22483 : } else if (ego->hasDeparted() && i <= ego->getRoutePosition()) {
440 723 : MSBaseVehicle* veh = dynamic_cast<MSBaseVehicle*>(const_cast<SUMOVehicle*>(ego));
441 723 : if (!dw->hasTrain(veh) && dw->notifyEnter(*veh, dw->NOTIFICATION_REROUTE, nullptr) && !veh->hasReminder(dw)) {
442 47 : veh->addReminder(dw, 1);
443 63 : for (MSDriveWay* sub : dw->getSubDriveWays()) {
444 16 : if (!sub->hasTrain(veh) && sub->notifyEnter(*veh, dw->NOTIFICATION_REROUTE, nullptr) && !veh->hasReminder(sub)) {
445 0 : veh->addReminder(sub, 1);
446 : }
447 : }
448 : }
449 : }
450 : }
451 : }
452 : }
453 : }
454 : }
455 : }
456 : }
457 3568 : }
458 :
459 :
460 : bool
461 16761 : MSRailSignal::hasInsertionConstraint(MSLink* link, const MSVehicle* veh, std::string& info, bool& isInsertionOrder) {
462 16761 : if (link->getJunction() != nullptr && link->getJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
463 5125 : const MSRailSignal* rs = dynamic_cast<const MSRailSignal*>(link->getTLLogic());
464 4925 : if (rs != nullptr && rs->myConstraints.size() > 0) {
465 6912 : const std::string tripID = veh->getParameter().getParameter("tripId", veh->getID());
466 : auto it = rs->myConstraints.find(tripID);
467 3456 : if (it != rs->myConstraints.end()) {
468 3673 : for (MSRailSignalConstraint* c : it->second) {
469 3376 : if (c->isInsertionConstraint() && !c->cleared()) {
470 : #ifdef DEBUG_SIGNALSTATE
471 : if (DEBUG_HELPER(rs)) {
472 : std::cout << SIMTIME << " rsl=" << rs->getID() << " insertion constraint '" << c->getDescription() << "' for vehicle '" << veh->getID() << "' not cleared\n";
473 : }
474 : #endif
475 6216 : info = c->getDescription();
476 3108 : isInsertionOrder = c->getType() == MSRailSignalConstraint::ConstraintType::INSERTION_ORDER;
477 3108 : if (MSGlobals::gTimeToTeleportRSDeadlock > 0) {
478 3108 : const SUMOVehicle* foe = c->getFoe();
479 3108 : if (foe != nullptr) {
480 3108 : MSRailSignalControl::getInstance().addWaitRelation(veh, rs, foe, c);
481 : }
482 : }
483 : return true;
484 : }
485 : }
486 : }
487 : }
488 : }
489 : return false;
490 : }
491 :
492 : // ===========================================================================
493 : // LinkInfo method definitions
494 : // ===========================================================================
495 :
496 5974 : MSRailSignal::LinkInfo::LinkInfo(MSLink* link):
497 5974 : myLink(link) {
498 5974 : reset();
499 5974 : }
500 :
501 13501 : MSRailSignal::LinkInfo::~LinkInfo() {
502 18545 : for (MSDriveWay* dw : myDriveways) {
503 5044 : delete dw;
504 : }
505 : myDriveways.clear();
506 13501 : }
507 :
508 : void
509 5979 : MSRailSignal::LinkInfo::reset() {
510 5979 : myLastRerouteTime = -1;
511 5979 : myLastRerouteVehicle = nullptr;
512 : myDriveways.clear();
513 8742 : myControlled = isRailwayOrShared(myLink->getViaLaneOrLane()->getPermissions())
514 5979 : && isRailwayOrShared(myLink->getLane()->getPermissions());
515 5979 : }
516 :
517 :
518 : std::string
519 6 : MSRailSignal::LinkInfo::getID() const {
520 12 : return myLink->getTLLogic()->getID() + "_" + toString(myLink->getTLIndex());
521 : }
522 :
523 :
524 : MSDriveWay&
525 9119846 : MSRailSignal::LinkInfo::getDriveWay(const SUMOVehicle* veh, int searchStart) {
526 9119846 : MSEdge* first = &myLink->getLane()->getEdge();
527 9119846 : auto searchStartIt = searchStart < 0 ? veh->getCurrentRouteEdge() : veh->getRoute().begin() + searchStart;
528 9119846 : MSRouteIterator firstIt = std::find(searchStartIt, veh->getRoute().end(), first);
529 9119846 : if (firstIt == veh->getRoute().end()) {
530 : // possibly the vehicle has already gone past the first edge (i.e.
531 : // because first is short or the step-length is high)
532 : // lets look backward along the route
533 : // give some slack because the vehicle might have been braking from a higher speed and using ballistic integration
534 79 : double lookBack = SPEED2DIST(veh->getSpeed() + 10);
535 79 : int routeIndex = veh->getRoutePosition() - 1;
536 85 : while (lookBack > 0 && routeIndex > 0) {
537 85 : const MSEdge* prevEdge = veh->getRoute().getEdges()[routeIndex];
538 85 : if (prevEdge == first) {
539 79 : firstIt = veh->getRoute().begin() + routeIndex;
540 79 : break;
541 : }
542 6 : lookBack -= prevEdge->getLength();
543 6 : routeIndex--;
544 : }
545 : }
546 9119846 : MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(myLink->getTLLogic()));
547 9119846 : if (firstIt == veh->getRoute().end()) {
548 0 : WRITE_WARNING("Invalid approach information to rail signal '" + MSDriveWay::getClickableTLLinkID(myLink) + "' after rerouting for vehicle '" + veh->getID()
549 : + "' first driveway edge '" + first->getID() + "' time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
550 0 : if (myDriveways.empty()) {
551 : ConstMSEdgeVector dummyRoute;
552 0 : dummyRoute.push_back(&myLink->getLane()->getEdge());
553 0 : MSDriveWay* dw = MSDriveWay::buildDriveWay(rs->getNewDrivewayID(), myLink, dummyRoute.begin(), dummyRoute.end());
554 0 : myDriveways.push_back(dw);
555 0 : }
556 0 : return *myDriveways.front();
557 : }
558 : //std::cout << SIMTIME << " veh=" << veh->getID() << " rsl=" << getID() << " dws=" << myDriveways.size() << "\n";
559 9119846 : return getDriveWay(firstIt, veh->getRoute().end(), veh->getID());
560 : }
561 :
562 :
563 : MSDriveWay&
564 9119846 : MSRailSignal::LinkInfo::getDriveWay(MSRouteIterator firstIt, MSRouteIterator endIt, const std::string& info) {
565 9333496 : for (MSDriveWay* dw : myDriveways) {
566 9328452 : if (dw->match(firstIt, endIt)) {
567 : return *dw;
568 : }
569 : #ifdef DEBUG_SELECT_DRIVEWAY
570 : std::cout << SIMTIME << " rs=" << getID() << " veh=" << info << " other dwSignal=" << dw->foundSignal() << " dwRoute=" << toString(dw->getRoute()) << "\n";
571 : #else
572 : UNUSED_PARAMETER(info);
573 : #endif
574 : }
575 5044 : MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(myLink->getTLLogic()));
576 5044 : MSDriveWay* dw = MSDriveWay::buildDriveWay(rs->getNewDrivewayID(), myLink, firstIt, endIt);
577 : dw->setVehicle(info);
578 : #ifdef DEBUG_SELECT_DRIVEWAY
579 : std::cout << SIMTIME << " rs=" << getID() << " veh=" << info << " new dwSignal=" << dw->foundSignal() << " dwRoute=" << toString(dw->getRoute()) << "\n";
580 : #endif
581 5044 : myDriveways.push_back(dw);
582 5044 : return *myDriveways.back();
583 : }
584 :
585 :
586 : void
587 232696 : MSRailSignal::LinkInfo::reroute(SUMOVehicle* veh, const MSEdgeVector& occupied) {
588 232696 : MSDevice_Routing* rDev = static_cast<MSDevice_Routing*>(veh->getDevice(typeid(MSDevice_Routing)));
589 232696 : const SUMOTime now = MSNet::getInstance()->getCurrentTimeStep();
590 : if (rDev != nullptr
591 140130 : && rDev->mayRerouteRailSignal()
592 232855 : && (myLastRerouteVehicle != veh
593 : // reroute each vehicle only once if no periodic routing is allowed,
594 : // otherwise with the specified period
595 153 : || (rDev->getPeriod() > 0 && myLastRerouteTime + rDev->getPeriod() <= now))) {
596 6 : myLastRerouteVehicle = veh;
597 6 : myLastRerouteTime = now;
598 :
599 : #ifdef DEBUG_REROUTE
600 : ConstMSEdgeVector oldRoute = veh->getRoute().getEdges();
601 : if (DEBUG_COND_LINKINFO) {
602 : std::cout << SIMTIME << " reroute veh=" << veh->getID() << " rs=" << getID() << " occupied=" << toString(occupied) << "\n";
603 : }
604 : #endif
605 : MSRoutingEngine::Prohibitions prohibited;
606 18 : for (MSEdge* e : occupied) {
607 : // indefinite occupation because vehicles might be in deadlock on their current routes
608 12 : prohibited[e].end = std::numeric_limits<double>::max();
609 : }
610 18 : MSRoutingEngine::reroute(*veh, now, "railSignal:" + getID(), false, true, prohibited);
611 : #ifdef DEBUG_REROUTE
612 : // attention this works only if we are not parallel!
613 : if (DEBUG_COND_LINKINFO) {
614 : if (veh->getRoute().getEdges() != oldRoute) {
615 : std::cout << " rerouting successful\n";
616 : }
617 : }
618 : #endif
619 : }
620 232696 : }
621 :
622 : void
623 18352 : MSRailSignal::resetStored() {
624 : myBlockingVehicles.clear();
625 : myRivalVehicles.clear();
626 : myPriorityVehicles.clear();
627 : myConstraintInfo = "";
628 : myBlockingDriveWays.clear();
629 : myRequestedDriveWay = "";
630 18352 : }
631 :
632 :
633 : void
634 0 : MSRailSignal::storeTraCIVehicles(const MSDriveWay* dw) {
635 0 : resetStored();
636 0 : myStoreVehicles = true;
637 : MSEdgeVector occupied;
638 : // call for side effects
639 0 : dw->foeDriveWayOccupied(true, nullptr, occupied);
640 0 : myStoreVehicles = false;
641 0 : }
642 :
643 : void
644 18352 : MSRailSignal::storeTraCIVehicles(int linkIndex) {
645 18352 : resetStored();
646 18352 : myStoreVehicles = true;
647 18352 : LinkInfo& li = myLinkInfos[linkIndex];
648 18352 : if (li.myLink->getApproaching().size() > 0) {
649 1825 : Approaching closest = li.myLink->getClosest();
650 1825 : MSDriveWay& driveway = li.getDriveWay(closest.first);
651 : MSEdgeVector occupied;
652 : myRequestedDriveWay = driveway.getID();
653 : // call for side effects
654 1825 : driveway.reserve(closest, occupied);
655 1825 : constraintsAllow(closest.first);
656 18352 : } else if (li.myDriveways.size() > 0) {
657 16035 : li.myDriveways.front()->conflictLaneOccupied();
658 16035 : li.myDriveways.front()->foeDriveWayApproached();
659 : }
660 18352 : myStoreVehicles = false;
661 18352 : }
662 :
663 : MSRailSignal::VehicleVector
664 6124 : MSRailSignal::getBlockingVehicles(int linkIndex) {
665 6124 : storeTraCIVehicles(linkIndex);
666 6124 : return myBlockingVehicles;
667 : }
668 :
669 : MSRailSignal::VehicleVector
670 6114 : MSRailSignal::getRivalVehicles(int linkIndex) {
671 6114 : storeTraCIVehicles(linkIndex);
672 6114 : return myRivalVehicles;
673 : }
674 :
675 : MSRailSignal::VehicleVector
676 6114 : MSRailSignal::getPriorityVehicles(int linkIndex) {
677 6114 : storeTraCIVehicles(linkIndex);
678 6114 : return myPriorityVehicles;
679 : }
680 :
681 : std::string
682 0 : MSRailSignal::getConstraintInfo(int linkIndex) {
683 0 : storeTraCIVehicles(linkIndex);
684 0 : return myConstraintInfo;
685 : }
686 :
687 :
688 : std::string
689 0 : MSRailSignal::getRequestedDriveWay(int linkIndex) {
690 0 : storeTraCIVehicles(linkIndex);
691 0 : return myRequestedDriveWay;
692 : }
693 :
694 :
695 : std::vector<const MSDriveWay*>
696 0 : MSRailSignal::getBlockingDriveWays(int linkIndex) {
697 0 : storeTraCIVehicles(linkIndex);
698 0 : return myBlockingDriveWays;
699 : }
700 :
701 :
702 : MSRailSignal::VehicleVector
703 0 : MSRailSignal::getBlockingVehicles(const MSDriveWay* dw) {
704 0 : storeTraCIVehicles(dw);
705 0 : return myBlockingVehicles;
706 : }
707 :
708 :
709 : std::vector<const MSDriveWay*>
710 0 : MSRailSignal::getBlockingDriveWays(const MSDriveWay* dw) {
711 0 : storeTraCIVehicles(dw);
712 0 : return myBlockingDriveWays;
713 : }
714 :
715 : const MSDriveWay&
716 0 : MSRailSignal::retrieveDriveWay(int numericalID) const {
717 0 : for (const LinkInfo& li : myLinkInfos) {
718 0 : for (const MSDriveWay* dw : li.myDriveways) {
719 0 : if (dw->getNumericalID() == numericalID) {
720 0 : return *dw;
721 : }
722 : }
723 : }
724 0 : throw ProcessError("Invalid driveway id " + toString(numericalID) + " at railSignal '" + getID() + "'");
725 : }
726 :
727 : const MSDriveWay&
728 42154 : MSRailSignal::retrieveDriveWayForVeh(int tlIndex, const SUMOVehicle* veh) {
729 42154 : return myLinkInfos[tlIndex].getDriveWay(veh);
730 : }
731 :
732 : const MSDriveWay&
733 0 : MSRailSignal::retrieveDriveWayForRoute(int tlIndex, MSRouteIterator first, MSRouteIterator end) {
734 0 : return myLinkInfos[tlIndex].getDriveWay(first, end);
735 : }
736 :
737 :
738 : const std::vector<MSDriveWay*>
739 11523 : MSRailSignal::retrieveDriveWays(int tlIndex) const {
740 11523 : return myLinkInfos[tlIndex].myDriveways;
741 : }
742 :
743 :
744 : std::string
745 0 : MSRailSignal::getBlockingVehicleIDs() const {
746 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
747 0 : if (myLinkInfos.size() == 1) {
748 0 : return toString(rs->getBlockingVehicles(0));
749 : } else {
750 : std::string result;
751 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
752 0 : result += toString(i) + ": " + toString(rs->getBlockingVehicles(i)) + ";";
753 : }
754 0 : return result;
755 : }
756 : }
757 : std::string
758 0 : MSRailSignal::getRivalVehicleIDs() const {
759 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
760 0 : if (myLinkInfos.size() == 1) {
761 0 : return toString(rs->getRivalVehicles(0));
762 : } else {
763 : std::string result;
764 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
765 0 : result += toString(i) + ": " + toString(rs->getRivalVehicles(i)) + ";";
766 : }
767 0 : return result;
768 : }
769 : }
770 : std::string
771 0 : MSRailSignal::getPriorityVehicleIDs() const {
772 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
773 0 : if (myLinkInfos.size() == 1) {
774 0 : return toString(rs->getPriorityVehicles(0));
775 : } else {
776 : std::string result;
777 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
778 0 : result += toString(i) + ": " + toString(rs->getPriorityVehicles(i)) + ";";
779 : }
780 0 : return result;
781 : }
782 : }
783 : std::string
784 0 : MSRailSignal::getConstraintInfo() const {
785 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
786 0 : if (myLinkInfos.size() == 1) {
787 0 : return rs->getConstraintInfo(0);
788 : } else {
789 : std::string result;
790 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
791 0 : result += toString(i) + ": " + rs->getConstraintInfo(i);
792 : }
793 0 : return result;
794 : }
795 : }
796 : std::string
797 0 : MSRailSignal::getRequestedDriveWay() const {
798 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
799 0 : if (myLinkInfos.size() == 1) {
800 0 : return toString(rs->getRequestedDriveWay(0));
801 : } else {
802 : std::string result;
803 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
804 0 : result += toString(i) + ": " + toString(rs->getRequestedDriveWay(i)) + ";";
805 : }
806 0 : return result;
807 : }
808 : }
809 : std::string
810 0 : MSRailSignal::getBlockingDriveWayIDs() const {
811 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
812 0 : if (myLinkInfos.size() == 1) {
813 0 : return toString(rs->getBlockingDriveWays(0));
814 : } else {
815 : std::string result;
816 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
817 0 : result += toString(i) + ": " + toString(rs->getBlockingDriveWays(i)) + ";";
818 : }
819 0 : return result;
820 : }
821 : }
822 :
823 : void
824 5 : MSRailSignal::setParameter(const std::string& key, const std::string& value) {
825 : // some pre-defined parameters can be updated at runtime
826 5 : if (key == "moving-block") {
827 5 : bool movingBlock = StringUtils::toBool(value);
828 5 : if (movingBlock != myMovingBlock) {
829 : // recompute driveways
830 5 : myMovingBlock = movingBlock;
831 10 : for (LinkInfo& li : myLinkInfos) {
832 5 : li.reset();
833 : }
834 5 : updateCurrentPhase();
835 5 : setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
836 : }
837 : }
838 5 : Parameterised::setParameter(key, value);
839 5 : }
840 :
841 :
842 : std::string
843 5044 : MSRailSignal::getNewDrivewayID() {
844 10088 : return getID() + "." + toString(myDriveWayIndex++);
845 : }
846 : /****************************************************************************/
|