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 147 : NBTrafficLightDefinition::NBTrafficLightDefinition(const std::string& id,
56 : const std::vector<NBNode*>& junctions, const std::string& programID,
57 147 : SUMOTime offset, TrafficLightType type) :
58 : Named(id),
59 147 : myControlledNodes(junctions),
60 147 : mySubID(programID), myOffset(offset),
61 147 : myType(type),
62 147 : myNeedsContRelationReady(false),
63 294 : myRightOnRedConflictsReady(false) {
64 : std::vector<NBNode*>::iterator i = myControlledNodes.begin();
65 543 : while (i != myControlledNodes.end()) {
66 1333 : for (std::vector<NBNode*>::iterator j = i + 1; j != myControlledNodes.end();) {
67 937 : if (*i == *j) {
68 : j = myControlledNodes.erase(j);
69 : } else {
70 : j++;
71 : }
72 : }
73 : i++;
74 : }
75 147 : std::sort(myControlledNodes.begin(), myControlledNodes.end(), NBNode::nodes_by_id_sorter());
76 784 : for (NBNode* const node : junctions) {
77 637 : node->addTrafficLight(this);
78 : }
79 147 : }
80 :
81 :
82 5518 : NBTrafficLightDefinition::NBTrafficLightDefinition(const std::string& id,
83 5518 : NBNode* junction, const std::string& programID, SUMOTime offset, TrafficLightType type) :
84 : Named(id),
85 5518 : mySubID(programID),
86 5518 : myOffset(offset),
87 5518 : myType(type),
88 5518 : myNeedsContRelationReady(false),
89 5518 : myRightOnRedConflictsReady(false) {
90 5518 : addNode(junction);
91 5518 : }
92 :
93 :
94 594 : NBTrafficLightDefinition::NBTrafficLightDefinition(const std::string& id, const std::string& programID,
95 594 : SUMOTime offset, TrafficLightType type) :
96 : Named(id),
97 594 : mySubID(programID),
98 594 : myOffset(offset),
99 594 : myType(type),
100 594 : myNeedsContRelationReady(false),
101 594 : myRightOnRedConflictsReady(false) {
102 594 : }
103 :
104 :
105 18777 : NBTrafficLightDefinition::~NBTrafficLightDefinition() {}
106 :
107 :
108 : NBTrafficLightLogic*
109 2863 : NBTrafficLightDefinition::compute(const OptionsCont& oc) {
110 : // it is not really a traffic light if no incoming edge exists
111 2863 : if (amInvalid()) {
112 : // make a copy of myControlledNodes because it will be modified;
113 64 : std::vector<NBNode*> nodes = myControlledNodes;
114 128 : for (auto it : nodes) {
115 64 : it->removeTrafficLight(this);
116 : }
117 192 : WRITE_WARNINGF(TL("The traffic light '%' does not control any links; it will not be build."), getID());
118 : return nullptr;
119 64 : }
120 : // compute the time needed to brake
121 2799 : 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 5598 : if (!oc.isDefault("tls.yellow.time")) {
125 4 : brakingTime = oc.getInt("tls.yellow.time");
126 : }
127 2799 : NBTrafficLightLogic* ret = myCompute(brakingTime);
128 2799 : ret->updateParameters(getParametersMap());
129 2799 : return ret;
130 : }
131 :
132 :
133 : bool
134 2241 : NBTrafficLightDefinition::amInvalid() const {
135 2241 : return myControlledLinks.size() == 0;
136 : }
137 :
138 :
139 : int
140 2811 : NBTrafficLightDefinition::computeBrakingTime(double minDecel) const {
141 2811 : if (myIncomingEdges.empty()) {
142 : // don't crash
143 : return MIN_YELLOW_SECONDS;
144 : }
145 2811 : const double vmax = NBContHelper::maxSpeed(myIncomingEdges);
146 2811 : 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 4990 : 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 162 : return (int)(1.8 + vmax / 2 / minDecel);
155 : }
156 : }
157 :
158 :
159 : void
160 5122 : NBTrafficLightDefinition::setParticipantsInformation() {
161 : // collect the information about participating edges and links
162 5122 : collectEdges();
163 5122 : collectLinks();
164 5122 : }
165 :
166 : std::set<NBEdge*>
167 9278 : NBTrafficLightDefinition::collectReachable(EdgeVector outer, const EdgeVector& within, bool checkControlled) {
168 : std::set<NBEdge*> reachable;
169 31178 : while (outer.size() > 0) {
170 21900 : NBEdge* from = outer.back();
171 : outer.pop_back();
172 : std::vector<NBEdge::Connection>& cons = from->getConnections();
173 75282 : for (std::vector<NBEdge::Connection>::iterator k = cons.begin(); k != cons.end(); k++) {
174 53382 : NBEdge* to = (*k).toEdge;
175 51952 : if (reachable.count(to) == 0 &&
176 53684 : (find(within.begin(), within.end(), to) != within.end()) &&
177 302 : (!checkControlled || from->mayBeTLSControlled((*k).fromLane, to, (*k).toLane))) {
178 : reachable.insert(to);
179 604 : outer.push_back(to);
180 : }
181 : }
182 : }
183 9278 : return reachable;
184 : }
185 :
186 :
187 : void
188 4639 : NBTrafficLightDefinition::collectEdges() {
189 : myIncomingEdges.clear();
190 : myEdgesWithin.clear();
191 : EdgeVector myOutgoing;
192 : // collect the edges from the participating nodes
193 9041 : for (std::vector<NBNode*>::iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
194 4402 : const EdgeVector& incoming = (*i)->getIncomingEdges();
195 4402 : copy(incoming.begin(), incoming.end(), back_inserter(myIncomingEdges));
196 4402 : 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 15629 : 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 10990 : EdgeVector::iterator k = std::find(myOutgoing.begin(), myOutgoing.end(), edge);
206 10990 : if (k != myOutgoing.end()) {
207 342 : myEdgesWithin.push_back(edge);
208 : } else {
209 10648 : outer.push_back(edge);
210 : }
211 : }
212 : // collect edges that are reachable from the outside via controlled connections
213 4639 : std::set<NBEdge*> reachable = collectReachable(outer, myEdgesWithin, true);
214 : // collect edges that are reachable from the outside regardless of controllability
215 4639 : std::set<NBEdge*> reachable2 = collectReachable(outer, myEdgesWithin, false);
216 :
217 9278 : const bool uncontrolledWithin = OptionsCont::getOptions().getBool("tls.uncontrolled-within");
218 4981 : for (EdgeVector::iterator j = myEdgesWithin.begin(); j != myEdgesWithin.end(); ++j) {
219 342 : 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 310 : if (uncontrolledWithin && myControlledInnerEdges.count(edge->getID()) == 0) {
226 23 : myIncomingEdges.erase(find(myIncomingEdges.begin(), myIncomingEdges.end(), edge));
227 : }
228 : }
229 32 : if (reachable2.count(edge) == 0 && edge->getFirstNonPedestrianLaneIndex(NBNode::FORWARD, true) >= 0
230 5 : && getID() != DummyID) {
231 20 : WRITE_WARNINGF(TL("Unreachable edge '%' within tlLogic '%'"), edge->getID(), getID());
232 : }
233 : }
234 4639 : }
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 764894 : 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 764894 : 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 764894 : find_if(myControlledNodes.begin(), myControlledNodes.end(), NBContHelper::node_with_incoming_finder(possProhibitorFrom));
287 : std::vector<NBNode*>::const_iterator outgoing =
288 764894 : find_if(myControlledNodes.begin(), myControlledNodes.end(), NBContHelper::node_with_outgoing_finder(possProhibitedTo));
289 : assert(incoming != myControlledNodes.end());
290 764894 : NBNode* incnode = *incoming;
291 764894 : 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 764894 : if (incnode != outnode) {
300 137672 : 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 77081 : const EdgeVector& ev1 = possProhibitedTo->getConnectedEdges();
310 : // go through the following edge,
311 : // check whether one of these connections is prohibited
312 179283 : for (i = ev1.begin(); i != ev1.end(); ++i) {
313 : std::vector<NBNode*>::const_iterator outgoing2 =
314 102800 : find_if(myControlledNodes.begin(), myControlledNodes.end(), NBContHelper::node_with_outgoing_finder(*i));
315 102800 : if (outgoing2 == myControlledNodes.end()) {
316 64894 : continue;
317 : }
318 37906 : NBNode* outnode2 = *outgoing2;
319 37906 : if (incnode != outnode2) {
320 27182 : continue;
321 : }
322 10724 : if (incnode->getDirection(possProhibitedTo, *i) != LinkDirection::STRAIGHT) {
323 6409 : continue;
324 : }
325 4315 : bool ret1 = incnode->foes(possProhibitorFrom, possProhibitorTo,
326 : possProhibitedTo, *i);
327 4315 : bool ret2 = incnode->forbids(possProhibitorFrom, possProhibitorTo,
328 : possProhibitedTo, *i,
329 : regardNonSignalisedLowerPriority);
330 4315 : bool ret = ret1 || ret2;
331 4315 : 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 76483 : const EdgeVector& ev2 = possProhibitorTo->getConnectedEdges();
342 : // go through the following edge,
343 : // check whether one of these connections is prohibited
344 177866 : for (i = ev2.begin(); i != ev2.end(); ++i) {
345 : std::vector<NBNode*>::const_iterator incoming2 =
346 102263 : find_if(myControlledNodes.begin(), myControlledNodes.end(), NBContHelper::node_with_incoming_finder(possProhibitorTo));
347 102263 : if (incoming2 == myControlledNodes.end()) {
348 64053 : continue;
349 : }
350 38210 : NBNode* incnode2 = *incoming2;
351 38210 : if (incnode2 != outnode) {
352 26997 : continue;
353 : }
354 11213 : if (incnode2->getDirection(possProhibitorTo, *i) != LinkDirection::STRAIGHT) {
355 6619 : continue;
356 : }
357 4594 : bool ret1 = incnode2->foes(possProhibitorTo, *i,
358 : possProhibitedFrom, possProhibitedTo);
359 4594 : bool ret2 = incnode2->forbids(possProhibitorTo, *i,
360 : possProhibitedFrom, possProhibitedTo,
361 : regardNonSignalisedLowerPriority);
362 4594 : bool ret = ret1 || ret2;
363 4594 : 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 77081 : }
379 : // both links are located at the same node
380 : // check using this node's information
381 627222 : 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 185604 : NBTrafficLightDefinition::foes(const NBEdge* const from1, const NBEdge* const to1,
395 : const NBEdge* const from2, const NBEdge* const to2) const {
396 185604 : 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 185604 : find_if(myControlledNodes.begin(), myControlledNodes.end(),
402 : NBContHelper::node_with_incoming_finder(from1));
403 : std::vector<NBNode*>::const_iterator outgoing =
404 185604 : find_if(myControlledNodes.begin(), myControlledNodes.end(),
405 : NBContHelper::node_with_outgoing_finder(to1));
406 : assert(incoming != myControlledNodes.end());
407 185604 : NBNode* incnode = *incoming;
408 185604 : NBNode* outnode = *outgoing;
409 185604 : if (incnode != outnode) {
410 : return false;
411 : }
412 185604 : return incnode->foes(from1, to1, from2, to2);
413 : }
414 :
415 :
416 : void
417 16959 : NBTrafficLightDefinition::addNode(NBNode* node) {
418 16959 : if (std::find(myControlledNodes.begin(), myControlledNodes.end(), node) == myControlledNodes.end()) {
419 6282 : myControlledNodes.push_back(node);
420 6282 : std::sort(myControlledNodes.begin(), myControlledNodes.end(), NBNode::nodes_by_id_sorter());
421 : }
422 16959 : node->addTrafficLight(this);
423 16959 : }
424 :
425 :
426 : void
427 4583 : NBTrafficLightDefinition::removeNode(NBNode* node) {
428 4583 : std::vector<NBNode*>::iterator i = std::find(myControlledNodes.begin(), myControlledNodes.end(), node);
429 4583 : if (i != myControlledNodes.end()) {
430 4342 : myControlledNodes.erase(i);
431 : }
432 : // !!! remove in node?
433 4583 : }
434 :
435 :
436 : void
437 46 : NBTrafficLightDefinition::addControlledInnerEdges(const std::vector<std::string>& edges) {
438 : myControlledInnerEdges.insert(edges.begin(), edges.end());
439 46 : }
440 :
441 :
442 : std::vector<std::string>
443 124 : NBTrafficLightDefinition::getControlledInnerEdges() const {
444 124 : return std::vector<std::string>(myControlledInnerEdges.begin(), myControlledInnerEdges.end());
445 : }
446 :
447 :
448 : const EdgeVector&
449 2805 : NBTrafficLightDefinition::getIncomingEdges() const {
450 2805 : return myIncomingEdges;
451 : }
452 :
453 :
454 : void
455 4597 : 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 14487 : for (EdgeVector::iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
460 9890 : NBEdge* incoming = *i;
461 : int noLanes = incoming->getNumLanes();
462 26557 : for (int j = 0; j < noLanes; j++) {
463 16667 : std::vector<NBEdge::Connection> connected = incoming->getConnectionsFromLane(j);
464 40486 : for (std::vector<NBEdge::Connection>::iterator k = connected.begin(); k != connected.end(); k++) {
465 : const NBEdge::Connection& el = *k;
466 23819 : if (incoming->mayBeTLSControlled(el.fromLane, el.toEdge, el.toLane)) {
467 23797 : 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 23797 : && isRailway(incoming->getPermissions())) {
472 : // railways stay uncontrolled at rail crossing but they
473 : // must be registered in MSRailCrossing
474 572 : into.push_back(NBConnection(incoming, el.fromLane, el.toEdge, el.toLane, -1));
475 : } else if (incoming->getToNode()->getType() == SumoXMLNodeType::RAIL_SIGNAL
476 2103 : && 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 23536 : && (incoming->getBidiEdge() == el.toEdge)
481 : ) {
482 : // turnarounds stay uncontrolled at rail signal
483 23486 : } 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 45914 : into.push_back(NBConnection(incoming, el.fromLane, el.toEdge, el.toLane, tlIndex++));
487 22957 : if (el.indirectLeft) {
488 4 : indirectLeft.push_back((int)into.size() - 1);
489 : }
490 : }
491 : }
492 : }
493 16667 : }
494 : }
495 4597 : 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 4597 : if (into.size() > 0 && tlIndex == 0) {
513 450 : WRITE_WARNINGF(TL("The rail crossing '%' does not have any roads."), getID());
514 : }
515 4597 : }
516 :
517 : bool
518 2078 : NBTrafficLightDefinition::railSignalUncontrolled(const NBEdge* in, const NBEdge* out) {
519 : const NBNode* n = in->getToNode();
520 2078 : if (n->hasParameter(OSM_SIGNAL_DIRECTION) && in->hasParameter(OSM_DIRECTION) && out->hasParameter(OSM_DIRECTION)) {
521 4125 : if (in->getParameter(OSM_DIRECTION) == out->getParameter(OSM_DIRECTION)) {
522 4125 : if (n->getParameter(OSM_SIGNAL_DIRECTION) != in->getParameter(OSM_DIRECTION)) {
523 : 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 68793 : NBTrafficLightDefinition::needsCont(const NBEdge* fromE, const NBEdge* toE, const NBEdge* otherFromE, const NBEdge* otherToE) const {
537 68793 : if (!myNeedsContRelationReady) {
538 355 : initNeedsContRelation();
539 : assert(myNeedsContRelationReady);
540 : }
541 68793 : return std::find(myNeedsContRelation.begin(), myNeedsContRelation.end(),
542 68793 : 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 165647 : NBTrafficLightDefinition::initRightOnRedConflicts() const {
562 165647 : 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 165647 : }
578 :
579 :
580 : bool
581 165644 : NBTrafficLightDefinition::rightOnRedConflict(int index, int foeIndex) const {
582 165644 : initRightOnRedConflicts();
583 165644 : 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 : /****************************************************************************/
|