Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file NBTrafficLightDefinition.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @date Sept 2002
19 : ///
20 : // The base class for traffic light logic definitions
21 : /****************************************************************************/
22 : #include <config.h>
23 :
24 : #include <vector>
25 : #include <string>
26 : #include <algorithm>
27 : #include <cassert>
28 : #include <iterator>
29 : #include <utils/common/MsgHandler.h>
30 : #include <utils/common/ToString.h>
31 : #include "NBTrafficLightDefinition.h"
32 : #include <utils/options/OptionsCont.h>
33 : #include "NBLinkPossibilityMatrix.h"
34 : #include "NBTrafficLightLogic.h"
35 : #include "NBOwnTLDef.h"
36 : #include "NBContHelper.h"
37 :
38 : //#define DEBUG_RIGHT_OF_WAY
39 : #define DEBUGCOND true
40 :
41 : // ===========================================================================
42 : // static members
43 : // ===========================================================================
44 : const std::string NBTrafficLightDefinition::DefaultProgramID = "0";
45 : const std::string NBTrafficLightDefinition::DummyID = "dummy";
46 : const SUMOTime NBTrafficLightDefinition::UNSPECIFIED_DURATION(-1);
47 : const int NBTrafficLightDefinition::MIN_YELLOW_SECONDS(3);
48 : const std::string NBTrafficLightDefinition::OSM_DIRECTION("osm:direction");
49 : const std::string NBTrafficLightDefinition::OSM_SIGNAL_DIRECTION("railway:signal:direction");
50 :
51 :
52 : // ===========================================================================
53 : // method definitions
54 : // ===========================================================================
55 184 : NBTrafficLightDefinition::NBTrafficLightDefinition(const std::string& id,
56 : const std::vector<NBNode*>& junctions, const std::string& programID,
57 184 : SUMOTime offset, TrafficLightType type) :
58 : Named(id),
59 184 : myControlledNodes(junctions),
60 184 : mySubID(programID), myOffset(offset),
61 184 : myType(type),
62 184 : myNeedsContRelationReady(false),
63 368 : myRightOnRedConflictsReady(false) {
64 : std::vector<NBNode*>::iterator i = myControlledNodes.begin();
65 684 : while (i != myControlledNodes.end()) {
66 1543 : for (std::vector<NBNode*>::iterator j = i + 1; j != myControlledNodes.end();) {
67 1043 : if (*i == *j) {
68 : j = myControlledNodes.erase(j);
69 : } else {
70 : j++;
71 : }
72 : }
73 : i++;
74 : }
75 184 : std::sort(myControlledNodes.begin(), myControlledNodes.end(), NBNode::nodes_by_id_sorter());
76 925 : for (NBNode* const node : junctions) {
77 741 : node->addTrafficLight(this);
78 : }
79 184 : }
80 :
81 :
82 7268 : NBTrafficLightDefinition::NBTrafficLightDefinition(const std::string& id,
83 7268 : NBNode* junction, const std::string& programID, SUMOTime offset, TrafficLightType type) :
84 : Named(id),
85 7268 : mySubID(programID),
86 7268 : myOffset(offset),
87 7268 : myType(type),
88 7268 : myNeedsContRelationReady(false),
89 7268 : myRightOnRedConflictsReady(false) {
90 7268 : addNode(junction);
91 7268 : }
92 :
93 :
94 925 : NBTrafficLightDefinition::NBTrafficLightDefinition(const std::string& id, const std::string& programID,
95 925 : SUMOTime offset, TrafficLightType type) :
96 : Named(id),
97 925 : mySubID(programID),
98 925 : myOffset(offset),
99 925 : myType(type),
100 925 : myNeedsContRelationReady(false),
101 925 : myRightOnRedConflictsReady(false) {
102 925 : }
103 :
104 :
105 25131 : NBTrafficLightDefinition::~NBTrafficLightDefinition() {}
106 :
107 :
108 : NBTrafficLightLogic*
109 3707 : NBTrafficLightDefinition::compute(const OptionsCont& oc) {
110 : // it is not really a traffic light if no incoming edge exists
111 3707 : if (amInvalid()) {
112 : // make a copy of myControlledNodes because it will be modified;
113 69 : std::vector<NBNode*> nodes = myControlledNodes;
114 138 : for (auto it : nodes) {
115 69 : it->removeTrafficLight(this);
116 : }
117 213 : WRITE_WARNINGF(TL("The traffic light '%' does not control any links; it will not be build."), getID());
118 : return nullptr;
119 : }
120 : // compute the time needed to brake
121 3638 : int brakingTime = computeBrakingTime(oc.getFloat("tls.yellow.min-decel"));
122 : // perform the computation depending on whether the traffic light
123 : // definition was loaded or shall be computed new completely
124 7276 : if (!oc.isDefault("tls.yellow.time")) {
125 0 : brakingTime = oc.getInt("tls.yellow.time");
126 : }
127 3638 : NBTrafficLightLogic* ret = myCompute(brakingTime);
128 3638 : ret->updateParameters(getParametersMap());
129 3638 : return ret;
130 : }
131 :
132 :
133 : bool
134 2733 : NBTrafficLightDefinition::amInvalid() const {
135 2733 : return myControlledLinks.size() == 0;
136 : }
137 :
138 :
139 : int
140 3650 : NBTrafficLightDefinition::computeBrakingTime(double minDecel) const {
141 3650 : if (myIncomingEdges.empty()) {
142 : // don't crash
143 : return MIN_YELLOW_SECONDS;
144 : }
145 3650 : const double vmax = NBContHelper::maxSpeed(myIncomingEdges);
146 3650 : if (vmax < 71 / 3.6) {
147 : // up to 50kmh: 3 seconds , 60km/h: 4, 70kmh: 5
148 : // @note: these are German regulations, other countries may differ
149 6559 : return MIN_YELLOW_SECONDS + (int)MAX2(0.0, (floor((vmax - 50 / 3.6) * 0.37)));
150 : } else {
151 : // above 70km/h we use a function that grows according to the "natural"
152 : // formula (vmax / 2 * minDecel) but continues smoothly where the german
153 : // rules leave of
154 199 : return (int)(1.8 + vmax / 2 / minDecel);
155 : }
156 : }
157 :
158 :
159 : void
160 6628 : NBTrafficLightDefinition::setParticipantsInformation() {
161 : // collect the information about participating edges and links
162 6628 : collectEdges();
163 6628 : collectLinks();
164 6628 : }
165 :
166 : std::set<NBEdge*>
167 11616 : NBTrafficLightDefinition::collectReachable(EdgeVector outer, const EdgeVector& within, bool checkControlled) {
168 : std::set<NBEdge*> reachable;
169 38634 : while (outer.size() > 0) {
170 27018 : NBEdge* from = outer.back();
171 : outer.pop_back();
172 : std::vector<NBEdge::Connection>& cons = from->getConnections();
173 91252 : for (std::vector<NBEdge::Connection>::iterator k = cons.begin(); k != cons.end(); k++) {
174 64234 : NBEdge* to = (*k).toEdge;
175 62688 : if (reachable.count(to) == 0 &&
176 64566 : (find(within.begin(), within.end(), to) != within.end()) &&
177 332 : (!checkControlled || from->mayBeTLSControlled((*k).fromLane, to, (*k).toLane))) {
178 : reachable.insert(to);
179 664 : outer.push_back(to);
180 : }
181 : }
182 : }
183 11616 : return reachable;
184 : }
185 :
186 :
187 : void
188 5808 : NBTrafficLightDefinition::collectEdges() {
189 5808 : myIncomingEdges.clear();
190 5808 : myEdgesWithin.clear();
191 : EdgeVector myOutgoing;
192 : // collect the edges from the participating nodes
193 11132 : for (std::vector<NBNode*>::iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
194 5324 : const EdgeVector& incoming = (*i)->getIncomingEdges();
195 : copy(incoming.begin(), incoming.end(), back_inserter(myIncomingEdges));
196 5324 : const EdgeVector& outgoing = (*i)->getOutgoingEdges();
197 : copy(outgoing.begin(), outgoing.end(), back_inserter(myOutgoing));
198 : }
199 : EdgeVector outer;
200 : // check which of the edges are completely within the junction
201 : // add them to the list of edges lying within the node
202 19371 : for (NBEdge* edge : myIncomingEdges) {
203 : edge->setInsideTLS(false); // reset
204 : // an edge lies within the logic if it is outgoing as well as incoming
205 13563 : EdgeVector::iterator k = std::find(myOutgoing.begin(), myOutgoing.end(), edge);
206 13563 : if (k != myOutgoing.end()) {
207 386 : myEdgesWithin.push_back(edge);
208 : } else {
209 13177 : outer.push_back(edge);
210 : }
211 : }
212 : // collect edges that are reachable from the outside via controlled connections
213 5808 : std::set<NBEdge*> reachable = collectReachable(outer, myEdgesWithin, true);
214 : // collect edges that are reachable from the outside regardless of controllability
215 5808 : std::set<NBEdge*> reachable2 = collectReachable(outer, myEdgesWithin, false);
216 :
217 11616 : const bool uncontrolledWithin = OptionsCont::getOptions().getBool("tls.uncontrolled-within");
218 6194 : for (EdgeVector::iterator j = myEdgesWithin.begin(); j != myEdgesWithin.end(); ++j) {
219 386 : NBEdge* edge = *j;
220 : // edges that are marked as 'inner' will not get their own phase when
221 : // computing traffic light logics (unless they cannot be reached from the outside at all)
222 : if (reachable.count(edge) == 1) {
223 : edge->setInsideTLS(true);
224 : // legacy behavior
225 340 : if (uncontrolledWithin && myControlledInnerEdges.count(edge->getID()) == 0) {
226 23 : myIncomingEdges.erase(find(myIncomingEdges.begin(), myIncomingEdges.end(), edge));
227 : }
228 : }
229 46 : if (reachable2.count(edge) == 0 && edge->getFirstNonPedestrianLaneIndex(NBNode::FORWARD, true) >= 0
230 5 : && getID() != DummyID) {
231 25 : WRITE_WARNINGF(TL("Unreachable edge '%' within tlLogic '%'"), edge->getID(), getID());
232 : }
233 : }
234 5808 : }
235 :
236 :
237 : bool
238 0 : NBTrafficLightDefinition::mustBrake(const NBEdge* const from, const NBEdge* const to) const {
239 : std::vector<NBNode*>::const_iterator i =
240 0 : find_if(myControlledNodes.begin(), myControlledNodes.end(),
241 : NBContHelper::node_with_incoming_finder(from));
242 : assert(i != myControlledNodes.end());
243 0 : NBNode* node = *i;
244 0 : if (!node->hasOutgoing(to)) {
245 : return true; // !!!
246 : }
247 : // @todo recheck relevance of lane indices
248 0 : return node->mustBrake(from, to, -1, -1, true);
249 : }
250 :
251 :
252 : bool
253 0 : NBTrafficLightDefinition::mustBrake(const NBEdge* const possProhibitedFrom,
254 : const NBEdge* const possProhibitedTo,
255 : const NBEdge* const possProhibitorFrom,
256 : const NBEdge* const possProhibitorTo,
257 : bool regardNonSignalisedLowerPriority) const {
258 0 : return forbids(possProhibitorFrom, possProhibitorTo,
259 : possProhibitedFrom, possProhibitedTo,
260 0 : regardNonSignalisedLowerPriority);
261 : }
262 :
263 :
264 : bool
265 1778 : NBTrafficLightDefinition::mustBrake(const NBConnection& possProhibited,
266 : const NBConnection& possProhibitor,
267 : bool regardNonSignalisedLowerPriority) const {
268 1778 : return forbids(possProhibitor.getFrom(), possProhibitor.getTo(),
269 1778 : possProhibited.getFrom(), possProhibited.getTo(),
270 1778 : regardNonSignalisedLowerPriority);
271 : }
272 :
273 :
274 : bool
275 899420 : NBTrafficLightDefinition::forbids(const NBEdge* const possProhibitorFrom,
276 : const NBEdge* const possProhibitorTo,
277 : const NBEdge* const possProhibitedFrom,
278 : const NBEdge* const possProhibitedTo,
279 : bool regardNonSignalisedLowerPriority,
280 : bool sameNodeOnly) const {
281 899420 : if (possProhibitorFrom == nullptr || possProhibitorTo == nullptr || possProhibitedFrom == nullptr || possProhibitedTo == nullptr) {
282 : return false;
283 : }
284 : // retrieve both nodes
285 : std::vector<NBNode*>::const_iterator incoming =
286 899420 : find_if(myControlledNodes.begin(), myControlledNodes.end(), NBContHelper::node_with_incoming_finder(possProhibitorFrom));
287 : std::vector<NBNode*>::const_iterator outgoing =
288 899420 : find_if(myControlledNodes.begin(), myControlledNodes.end(), NBContHelper::node_with_outgoing_finder(possProhibitedTo));
289 : assert(incoming != myControlledNodes.end());
290 899420 : NBNode* incnode = *incoming;
291 899420 : NBNode* outnode = *outgoing;
292 : EdgeVector::const_iterator i;
293 :
294 : #ifdef DEBUG_RIGHT_OF_WAY
295 : if (DEBUGCOND) {
296 : std::cout << "foribds tls=" << getID() << " from=" << possProhibitedFrom->getID() << " to=" << possProhibitedTo->getID() << " foeFrom=" << possProhibitorFrom->getID() << " foeTo=" << possProhibitorTo->getID() << " rnslp=" << regardNonSignalisedLowerPriority << " sameNodeOnly=" << sameNodeOnly;
297 : }
298 : #endif
299 899420 : if (incnode != outnode) {
300 140932 : if (sameNodeOnly) {
301 : #ifdef DEBUG_RIGHT_OF_WAY
302 : if (DEBUGCOND) {
303 : std::cout << " differentNodes: allows (no check)\n";
304 : }
305 : #endif
306 : return false;
307 : }
308 : // the links are located at different nodes
309 80159 : const EdgeVector& ev1 = possProhibitedTo->getConnectedEdges();
310 : // go through the following edge,
311 : // check whether one of these connections is prohibited
312 190615 : for (i = ev1.begin(); i != ev1.end(); ++i) {
313 : std::vector<NBNode*>::const_iterator outgoing2 =
314 111110 : find_if(myControlledNodes.begin(), myControlledNodes.end(), NBContHelper::node_with_outgoing_finder(*i));
315 111110 : if (outgoing2 == myControlledNodes.end()) {
316 73028 : continue;
317 : }
318 38082 : NBNode* outnode2 = *outgoing2;
319 38082 : if (incnode != outnode2) {
320 26774 : continue;
321 : }
322 11308 : if (incnode->getDirection(possProhibitedTo, *i) != LinkDirection::STRAIGHT) {
323 6539 : continue;
324 : }
325 4769 : bool ret1 = incnode->foes(possProhibitorFrom, possProhibitorTo,
326 : possProhibitedTo, *i);
327 4769 : bool ret2 = incnode->forbids(possProhibitorFrom, possProhibitorTo,
328 : possProhibitedTo, *i,
329 : regardNonSignalisedLowerPriority);
330 4769 : bool ret = ret1 || ret2;
331 4769 : if (ret) {
332 : #ifdef DEBUG_RIGHT_OF_WAY
333 : if (DEBUGCOND) {
334 : std::cout << " differentNodes: forbids\n";
335 : }
336 : #endif
337 : return true;
338 : }
339 : }
340 :
341 79505 : const EdgeVector& ev2 = possProhibitorTo->getConnectedEdges();
342 : // go through the following edge,
343 : // check whether one of these connections is prohibited
344 188826 : for (i = ev2.begin(); i != ev2.end(); ++i) {
345 : std::vector<NBNode*>::const_iterator incoming2 =
346 110371 : find_if(myControlledNodes.begin(), myControlledNodes.end(), NBContHelper::node_with_incoming_finder(possProhibitorTo));
347 110371 : if (incoming2 == myControlledNodes.end()) {
348 71855 : continue;
349 : }
350 38516 : NBNode* incnode2 = *incoming2;
351 38516 : if (incnode2 != outnode) {
352 26593 : continue;
353 : }
354 11923 : if (incnode2->getDirection(possProhibitorTo, *i) != LinkDirection::STRAIGHT) {
355 6761 : continue;
356 : }
357 5162 : bool ret1 = incnode2->foes(possProhibitorTo, *i,
358 : possProhibitedFrom, possProhibitedTo);
359 5162 : bool ret2 = incnode2->forbids(possProhibitorTo, *i,
360 : possProhibitedFrom, possProhibitedTo,
361 : regardNonSignalisedLowerPriority);
362 5162 : bool ret = ret1 || ret2;
363 5162 : if (ret) {
364 : #ifdef DEBUG_RIGHT_OF_WAY
365 : if (DEBUGCOND) {
366 : std::cout << " differentNodes: forbids (2)\n";
367 : }
368 : #endif
369 : return true;
370 : }
371 : }
372 : #ifdef DEBUG_RIGHT_OF_WAY
373 : if (DEBUGCOND) {
374 : std::cout << " differentNodes: allows\n";
375 : }
376 : #endif
377 : return false;
378 : }
379 : // both links are located at the same node
380 : // check using this node's information
381 758488 : const bool result = incnode->forbids(possProhibitorFrom, possProhibitorTo,
382 : possProhibitedFrom, possProhibitedTo,
383 : regardNonSignalisedLowerPriority);
384 : #ifdef DEBUG_RIGHT_OF_WAY
385 : if (DEBUGCOND) {
386 : std::cout << " sameNodes: " << (result ? "forbids" : "allows") << "\n";
387 : }
388 : #endif
389 : return result;
390 : }
391 :
392 :
393 : bool
394 177378 : NBTrafficLightDefinition::foes(const NBEdge* const from1, const NBEdge* const to1,
395 : const NBEdge* const from2, const NBEdge* const to2) const {
396 177378 : if (to1 == nullptr || to2 == nullptr) {
397 : return false;
398 : }
399 : // retrieve both nodes (it is possible that a connection
400 : std::vector<NBNode*>::const_iterator incoming =
401 177378 : find_if(myControlledNodes.begin(), myControlledNodes.end(),
402 : NBContHelper::node_with_incoming_finder(from1));
403 : std::vector<NBNode*>::const_iterator outgoing =
404 177378 : find_if(myControlledNodes.begin(), myControlledNodes.end(),
405 : NBContHelper::node_with_outgoing_finder(to1));
406 : assert(incoming != myControlledNodes.end());
407 177378 : NBNode* incnode = *incoming;
408 177378 : NBNode* outnode = *outgoing;
409 177378 : if (incnode != outnode) {
410 : return false;
411 : }
412 177378 : return incnode->foes(from1, to1, from2, to2);
413 : }
414 :
415 :
416 : void
417 24855 : NBTrafficLightDefinition::addNode(NBNode* node) {
418 24855 : if (std::find(myControlledNodes.begin(), myControlledNodes.end(), node) == myControlledNodes.end()) {
419 8480 : myControlledNodes.push_back(node);
420 8480 : std::sort(myControlledNodes.begin(), myControlledNodes.end(), NBNode::nodes_by_id_sorter());
421 : }
422 24855 : node->addTrafficLight(this);
423 24855 : }
424 :
425 :
426 : void
427 6093 : NBTrafficLightDefinition::removeNode(NBNode* node) {
428 6093 : std::vector<NBNode*>::iterator i = std::find(myControlledNodes.begin(), myControlledNodes.end(), node);
429 6093 : if (i != myControlledNodes.end()) {
430 5852 : myControlledNodes.erase(i);
431 : }
432 : // !!! remove in node?
433 6093 : }
434 :
435 :
436 : void
437 43 : NBTrafficLightDefinition::addControlledInnerEdges(const std::vector<std::string>& edges) {
438 : myControlledInnerEdges.insert(edges.begin(), edges.end());
439 43 : }
440 :
441 :
442 : std::vector<std::string>
443 157 : NBTrafficLightDefinition::getControlledInnerEdges() const {
444 157 : return std::vector<std::string>(myControlledInnerEdges.begin(), myControlledInnerEdges.end());
445 : }
446 :
447 :
448 : const EdgeVector&
449 3468 : NBTrafficLightDefinition::getIncomingEdges() const {
450 3468 : return myIncomingEdges;
451 : }
452 :
453 :
454 : void
455 5766 : NBTrafficLightDefinition::collectAllLinks(NBConnectionVector& into) {
456 : int tlIndex = 0;
457 : // build the list of links which are controlled by the traffic light
458 : std::vector<int> indirectLeft;
459 18229 : for (EdgeVector::iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
460 12463 : NBEdge* incoming = *i;
461 : int noLanes = incoming->getNumLanes();
462 32917 : for (int j = 0; j < noLanes; j++) {
463 20454 : std::vector<NBEdge::Connection> connected = incoming->getConnectionsFromLane(j);
464 49699 : for (std::vector<NBEdge::Connection>::iterator k = connected.begin(); k != connected.end(); k++) {
465 : const NBEdge::Connection& el = *k;
466 29245 : if (incoming->mayBeTLSControlled(el.fromLane, el.toEdge, el.toLane)) {
467 29228 : if (el.toEdge != nullptr && el.toLane >= (int) el.toEdge->getNumLanes()) {
468 0 : throw ProcessError("Connection '" + incoming->getID() + "_" + toString(j) + "->" + el.toEdge->getID() + "_" + toString(el.toLane) + "' yields in a not existing lane.");
469 : }
470 : if (incoming->getToNode()->getType() == SumoXMLNodeType::RAIL_CROSSING
471 29228 : && isRailway(incoming->getPermissions())) {
472 : // railways stay uncontrolled at rail crossing but they
473 : // must be registered in MSRailCrossing
474 994 : into.push_back(NBConnection(incoming, el.fromLane, el.toEdge, el.toLane, -1));
475 : } else if (incoming->getToNode()->getType() == SumoXMLNodeType::RAIL_SIGNAL
476 2454 : && incoming->getToNode()->getDirection(incoming, el.toEdge) == LinkDirection::TURN
477 : // assume explicit connections at sharp turn-arounds are either for reversal or due to a geometry glitch
478 : // (the might also be due to faulty connection
479 : // input but they would not come from guessing)
480 28762 : && (incoming->getBidiEdge() == el.toEdge)
481 : ) {
482 : // turnarounds stay uncontrolled at rail signal
483 28700 : } else if (incoming->getToNode()->getType() == SumoXMLNodeType::RAIL_SIGNAL && railSignalUncontrolled(incoming, el.toEdge)) {
484 : // rail signals may stay uncontrolled in a particular direction
485 : } else {
486 56226 : into.push_back(NBConnection(incoming, el.fromLane, el.toEdge, el.toLane, tlIndex++));
487 28113 : if (el.indirectLeft) {
488 4 : indirectLeft.push_back((int)into.size() - 1);
489 : }
490 : }
491 : }
492 : }
493 20454 : }
494 : }
495 5766 : if (indirectLeft.size() > 0) {
496 : // assign linkIndex2 to indirect left turns
497 5 : for (int i : indirectLeft) {
498 4 : NBConnection& c = into[i];
499 : // find straight connection with the same toEdge
500 50 : for (const NBConnection& c2 : into) {
501 50 : if (c2.getTo() == c.getTo() && c2.getFrom() != c.getFrom()) {
502 10 : LinkDirection dir = c.getFrom()->getToNode()->getDirection(c2.getFrom(), c2.getTo());
503 10 : if (dir == LinkDirection::STRAIGHT) {
504 : c.setTLIndex2(c2.getTLIndex());
505 : break;
506 : }
507 : }
508 : }
509 : }
510 : }
511 :
512 5766 : if (into.size() > 0 && tlIndex == 0) {
513 956 : WRITE_WARNINGF(TL("The rail crossing '%' does not have any roads."), getID());
514 : }
515 5766 : }
516 :
517 : bool
518 2423 : NBTrafficLightDefinition::railSignalUncontrolled(const NBEdge* in, const NBEdge* out) {
519 : const NBNode* n = in->getToNode();
520 2423 : if (n->hasParameter(OSM_SIGNAL_DIRECTION) && in->hasParameter(OSM_DIRECTION) && out->hasParameter(OSM_DIRECTION)) {
521 1633 : if (in->getParameter(OSM_DIRECTION) == out->getParameter(OSM_DIRECTION)) {
522 3266 : if (n->getParameter(OSM_SIGNAL_DIRECTION) != in->getParameter(OSM_DIRECTION)) {
523 587 : return true;
524 : }
525 : } else {
526 0 : WRITE_WARNINGF(TL("Could not interpret rail signal direction at junction '%' due to inconsistent directions of edge '%' (%) and edge '%' (%)"),
527 : n->getID(),
528 : in->getID(), in->getParameter(OSM_DIRECTION),
529 : out->getID(), out->getParameter(OSM_DIRECTION));
530 : }
531 : }
532 : return false;
533 : }
534 :
535 : bool
536 80671 : NBTrafficLightDefinition::needsCont(const NBEdge* fromE, const NBEdge* toE, const NBEdge* otherFromE, const NBEdge* otherToE) const {
537 80671 : if (!myNeedsContRelationReady) {
538 448 : initNeedsContRelation();
539 : assert(myNeedsContRelationReady);
540 : }
541 80671 : return std::find(myNeedsContRelation.begin(), myNeedsContRelation.end(),
542 80671 : StreamPair(fromE, toE, otherFromE, otherToE)) != myNeedsContRelation.end();
543 : }
544 :
545 :
546 : void
547 3 : NBTrafficLightDefinition::initNeedsContRelation() const {
548 3 : if (!amInvalid()) {
549 3 : NBOwnTLDef dummy(DummyID, myControlledNodes, 0, TrafficLightType::STATIC);
550 3 : dummy.initNeedsContRelation();
551 : myNeedsContRelation = dummy.myNeedsContRelation;
552 6 : for (std::vector<NBNode*>::const_iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
553 3 : (*i)->removeTrafficLight(&dummy);
554 : }
555 3 : }
556 3 : myNeedsContRelationReady = true;
557 3 : }
558 :
559 :
560 : void
561 211118 : NBTrafficLightDefinition::initRightOnRedConflicts() const {
562 211118 : if (!myRightOnRedConflictsReady) {
563 26 : NBOwnTLDef dummy(DummyID, myControlledNodes, 0, TrafficLightType::STATIC);
564 26 : dummy.setParticipantsInformation();
565 26 : NBTrafficLightLogic* tllDummy = dummy.computeLogicAndConts(0, true);
566 26 : delete tllDummy;
567 : myRightOnRedConflicts = dummy.myRightOnRedConflicts;
568 303 : for (std::vector<NBNode*>::const_iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
569 277 : (*i)->removeTrafficLight(&dummy);
570 : }
571 26 : myRightOnRedConflictsReady = true;
572 : //std::cout << " rightOnRedConflicts tls=" << getID() << " pro=" << getProgramID() << "\n";
573 : //for (RightOnRedConflicts::const_iterator it = myRightOnRedConflicts.begin(); it != myRightOnRedConflicts.end(); ++it) {
574 : // std::cout << " " << it->first << ", " << it->second << "\n";
575 : //}
576 26 : }
577 211118 : }
578 :
579 :
580 : bool
581 211115 : NBTrafficLightDefinition::rightOnRedConflict(int index, int foeIndex) const {
582 211115 : initRightOnRedConflicts();
583 211115 : return std::find(myRightOnRedConflicts.begin(), myRightOnRedConflicts.end(), std::make_pair(index, foeIndex)) != myRightOnRedConflicts.end();
584 : }
585 :
586 : std::string
587 0 : NBTrafficLightDefinition::getDescription() const {
588 0 : return getID() + ':' + getProgramID() + '@' + toString(this);
589 : }
590 :
591 :
592 : /****************************************************************************/
|