Eclipse SUMO - Simulation of Urban MObility
NBRequest.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2023 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/****************************************************************************/
21// This class computes the logic of a junction
22/****************************************************************************/
23#include <config.h>
24
25#include <string>
26#include <vector>
27#include <set>
28#include <algorithm>
29#include <bitset>
30#include <sstream>
31#include <map>
32#include <cassert>
37#include "NBEdge.h"
38#include "NBContHelper.h"
39#include "NBNode.h"
40#include "NBRequest.h"
41
42//#define DEBUG_RESPONSE
43//#define DEBUG_SETBLOCKING
44#define DEBUGCOND (myJunction->getID() == "C")
45
46// ===========================================================================
47// static member variables
48// ===========================================================================
51
52
53// ===========================================================================
54// method definitions
55// ===========================================================================
57 NBNode* junction,
58 const EdgeVector& all,
59 const EdgeVector& incoming,
60 const EdgeVector& outgoing,
61 const NBConnectionProhibits& loadedProhibits) :
62 myJunction(junction),
63 myAll(all),
64 myIncoming(incoming),
65 myOutgoing(outgoing) {
66 const int variations = numLinks();
67 // build maps with information which forbidding connection were
68 // computed and what's in there
69 myForbids.reserve(variations);
70 myDone.reserve(variations);
71 for (int i = 0; i < variations; i++) {
72 myForbids.push_back(LinkInfoCont(variations, false));
73 myDone.push_back(LinkInfoCont(variations, false));
74 }
75 // insert loaded prohibits
76 for (NBConnectionProhibits::const_iterator j = loadedProhibits.begin(); j != loadedProhibits.end(); j++) {
77 NBConnection prohibited = (*j).first;
78 bool ok1 = prohibited.check(ec);
79 if (find(myIncoming.begin(), myIncoming.end(), prohibited.getFrom()) == myIncoming.end()) {
80 ok1 = false;
81 }
82 if (find(myOutgoing.begin(), myOutgoing.end(), prohibited.getTo()) == myOutgoing.end()) {
83 ok1 = false;
84 }
85 int idx1 = 0;
86 if (ok1) {
87 idx1 = getIndex(prohibited.getFrom(), prohibited.getTo());
88 if (idx1 < 0) {
89 ok1 = false;
90 }
91 }
92 const NBConnectionVector& prohibiting = (*j).second;
93 for (NBConnectionVector::const_iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
94 NBConnection sprohibiting = *k;
95 bool ok2 = sprohibiting.check(ec);
96 if (find(myIncoming.begin(), myIncoming.end(), sprohibiting.getFrom()) == myIncoming.end()) {
97 ok2 = false;
98 }
99 if (find(myOutgoing.begin(), myOutgoing.end(), sprohibiting.getTo()) == myOutgoing.end()) {
100 ok2 = false;
101 }
102 if (ok1 && ok2) {
103 int idx2 = getIndex(sprohibiting.getFrom(), sprohibiting.getTo());
104 if (idx2 < 0) {
105 ok2 = false;
106 } else {
107 myForbids[idx2][idx1] = true;
108 myDone[idx2][idx1] = true;
109 myDone[idx1][idx2] = true;
110 myGoodBuilds++;
111 }
112 } else {
113 std::string pfID = prohibited.getFrom() != nullptr ? prohibited.getFrom()->getID() : "UNKNOWN";
114 std::string ptID = prohibited.getTo() != nullptr ? prohibited.getTo()->getID() : "UNKNOWN";
115 std::string bfID = sprohibiting.getFrom() != nullptr ? sprohibiting.getFrom()->getID() : "UNKNOWN";
116 std::string btID = sprohibiting.getTo() != nullptr ? sprohibiting.getTo()->getID() : "UNKNOWN";
117 WRITE_WARNING("could not prohibit " + pfID + "->" + ptID + " by " + bfID + "->" + btID);
118 myNotBuild++;
119 }
120 }
121 }
122 // ok, check whether someone has prohibited two links vice versa
123 // (this happens also in some Vissim-networks, when edges are joined)
124 for (int s1 = 0; s1 < variations; s1++) {
125 for (int s2 = s1 + 1; s2 < variations; s2++) {
126 // not set, yet
127 if (!myDone[s1][s2]) {
128 continue;
129 }
130 // check whether both prohibit vice versa
131 if (myForbids[s1][s2] && myForbids[s2][s1]) {
132 // mark unset - let our algorithm fix it later
133 myDone[s1][s2] = false;
134 myDone[s2][s1] = false;
135 }
136 }
137 }
138}
139
140
142
143
144void
146 EdgeVector::const_iterator i, j;
147 for (i = myIncoming.begin(); i != myIncoming.end(); i++) {
148 for (j = myOutgoing.begin(); j != myOutgoing.end(); j++) {
151 }
152 }
153 // reset signalised/non-signalised dependencies
155 // reset foes it the number of lanes matches (or exceeds) the number of incoming connections
157}
158
159
160void
162 EdgeVector::const_iterator pfrom = std::find(myAll.begin(), myAll.end(), from);
163 while (*pfrom != to) {
165 if ((*pfrom)->getToNode() == myJunction) {
166 EdgeVector::const_iterator pto = std::find(myAll.begin(), myAll.end(), to);
167 while (*pto != from) {
168 if (!((*pto)->getToNode() == myJunction)) {
169 setBlocking(from, to, *pfrom, *pto);
170 }
172 }
173 }
174 }
175}
176
177
178void
180 EdgeVector::const_iterator pfrom = std::find(myAll.begin(), myAll.end(), from);
181 while (*pfrom != to) {
183 if ((*pfrom)->getToNode() == myJunction) {
184 EdgeVector::const_iterator pto = std::find(myAll.begin(), myAll.end(), to);
185 while (*pto != from) {
186 if (!((*pto)->getToNode() == myJunction)) {
187 setBlocking(from, to, *pfrom, *pto);
188 }
190 }
191 }
192 }
193}
194
195
196void
198 NBEdge* from2, NBEdge* to2) {
199 // check whether one of the links has a dead end
200 if (to1 == nullptr || to2 == nullptr) {
201 return;
202 }
203 // get the indices of both links
204 int idx1 = getIndex(from1, to1);
205 int idx2 = getIndex(from2, to2);
206 if (idx1 < 0 || idx2 < 0) {
207 return; // !!! error output? did not happend, yet
208 }
209 // check whether the link crossing has already been checked
210 assert(idx1 < (int)(myIncoming.size() * myOutgoing.size()));
211 if (myDone[idx1][idx2]) {
212 return;
213 }
214 // mark the crossings as done
215 myDone[idx1][idx2] = true;
216 myDone[idx2][idx1] = true;
217 // special case all-way stop
219 // all ways forbid each other. Conflict resolution happens via arrival time
220 myForbids[idx1][idx2] = true;
221 myForbids[idx2][idx1] = true;
222 return;
223 }
224 // check if one of the links is a turn; this link is always not priorised
225 // true for right-before-left and priority
226 if (from1->isTurningDirectionAt(to1)) {
227 myForbids[idx2][idx1] = true;
228 return;
229 }
230 if (from2->isTurningDirectionAt(to2)) {
231 myForbids[idx1][idx2] = true;
232 return;
233 }
234 // if there are no connections, there are no prohibitions
235 if (from1->isConnectedTo(to1)) {
236 if (!from2->isConnectedTo(to2)) {
237 myForbids[idx1][idx2] = true;
238 myForbids[idx2][idx1] = false;
239 return;
240 }
241 } else {
242 if (!from2->isConnectedTo(to2)) {
243 myForbids[idx1][idx2] = false;
244 myForbids[idx2][idx1] = false;
245 return;
246 } else {
247 myForbids[idx1][idx2] = false;
248 myForbids[idx2][idx1] = true;
249 return;
250 }
251 }
252#ifdef DEBUG_SETBLOCKING
253 if (DEBUGCOND) std::cout << "setBlocking type=" << toString(myJunction->getType())
254 << " bentPrio=" << myJunction->isBentPriority()
255 << " 1:" << from1->getID() << "->" << to1->getID()
256 << " 2:" << from2->getID() << "->" << to2->getID() << "\n";
257#endif
258 // check the priorities if required by node type
260 if (!typeEqual) {
261 int from1p = from1->getJunctionPriority(myJunction);
262 int from2p = from2->getJunctionPriority(myJunction);
263#ifdef DEBUG_SETBLOCKING
264 if (DEBUGCOND) {
265 std::cout << " p1=" << from1p << " p2=" << from2p << "\n";
266 }
267#endif
268 // check if one of the connections is higher priorised when incoming into
269 // the junction, the connection road will yield
270 if (from1p > from2p) {
271 myForbids[idx1][idx2] = true;
272 return;
273 }
274 if (from2p > from1p) {
275 myForbids[idx2][idx1] = true;
276 return;
277 }
278 }
279 // straight connections prohibit turning connections if the priorities are equal
280 // (unless the junction is a bent priority junction)
281 if (!typeEqual && !myJunction->isBentPriority()) {
282 LinkDirection ld1 = myJunction->getDirection(from1, to1);
283 LinkDirection ld2 = myJunction->getDirection(from2, to2);
284#ifdef DEBUG_SETBLOCKING
285 if (DEBUGCOND) std::cout << "setBlocking"
286 << " 1:" << from1->getID() << "->" << to1->getID()
287 << " 2:" << from2->getID() << "->" << to2->getID()
288 << " dir1=" << toString(ld1) << " dir2=" << toString(ld2) << "\n";
289#endif
290 if (ld1 == LinkDirection::STRAIGHT) {
291 if (ld2 != LinkDirection::STRAIGHT) {
292 myForbids[idx1][idx2] = true;
293 myForbids[idx2][idx1] = false;
294 return;
295 }
296 } else {
297 if (ld2 == LinkDirection::STRAIGHT) {
298 myForbids[idx1][idx2] = false;
299 myForbids[idx2][idx1] = true;
300 return;
301 }
302 }
303 }
304
305 // check whether one of the connections is higher priorised on
306 // the outgoing edge when both roads are high priorised
307 // the connection with the lower priorised outgoing edge will lead
308 // should be valid for priority junctions only
309 /*
310 if (from1p > 0 && from2p > 0) {
311 assert(myJunction->getType() != SumoXMLNodeType::RIGHT_BEFORE_LEFT);
312 int to1p = to1->getJunctionPriority(myJunction);
313 int to2p = to2->getJunctionPriority(myJunction);
314 if (to1p > to2p) {
315 myForbids[idx1][idx2] = true;
316 return;
317 }
318 if (to2p > to1p) {
319 myForbids[idx2][idx1] = true;
320 return;
321 }
322 }
323 */
324
325 // compute the yielding due to the right-before-left rule
326 // (or left-before-right rule)
327 // get the position of the incoming lanes in the junction-wheel
328 EdgeVector::const_iterator c1 = std::find(myAll.begin(), myAll.end(), from1);
330 // go through next edges clockwise...
331 while (*c1 != from1 && *c1 != from2) {
332 if (*c1 == to2) {
333 // if we encounter to2 the second one prohibits the first
335 myForbids[idx1][idx2] = true;
336 } else {
337 myForbids[idx2][idx1] = true;
338 }
339 return;
340 }
342 }
343 // get the position of the incoming lanes in the junction-wheel
344 EdgeVector::const_iterator c2 = std::find(myAll.begin(), myAll.end(), from2);
346 // go through next edges clockwise...
347 while (*c2 != from2 && *c2 != from1) {
348 if (*c2 == to1) {
349 // if we encounter to1 the second one prohibits the first
351 myForbids[idx2][idx1] = true;
352 } else {
353 myForbids[idx1][idx2] = true;
354 }
355 return;
356 }
358 }
359#ifdef DEBUG_SETBLOCKING
360 if (DEBUGCOND) std::cout << "setBlocking"
361 << " 1:" << from1->getID() << "->" << to1->getID()
362 << " 2:" << from2->getID() << "->" << to2->getID()
363 << " noDecision\n";
364#endif
365}
366
367
368int
370 EdgeVector::const_iterator p = std::find(myAll.begin(), myAll.end(), from);
371 int ret = 0;
372 do {
373 ret++;
374 if (p == myAll.begin()) {
375 p = myAll.end();
376 }
377 p--;
378 } while (*p != to);
379 return ret;
380}
381
382const std::string&
383NBRequest::getFoes(int linkIndex) const {
384 assert(linkIndex >= 0);
385 assert(linkIndex < (int)myFoes.size());
386 return myFoes[linkIndex];
387}
388
389
390const std::string&
391NBRequest::getResponse(int linkIndex) const {
392 assert(linkIndex >= 0);
393 assert(linkIndex < (int)myResponse.size());
394 return myResponse[linkIndex];
395}
396
397
398void
400 int numLinks = (int)myResponse.size();
401 assert((int)myFoes.size() == numLinks);
402 assert((int)myHaveVia.size() == numLinks);
403 const bool padding = numLinks > 10;
404 for (int i = 0; i < numLinks; i++) {
406 into.writeAttr(SUMO_ATTR_INDEX, i);
407 if (padding && i < 10) {
408 into.writePadding(" ");
409 }
412 if (!OptionsCont::getOptions().getBool("no-internal-links")) {
414 }
415 into.closeTag();
416 }
417}
418
419
420void
421NBRequest::computeLogic(const bool checkLaneFoes) {
422 myResponse.clear();
423 myFoes.clear();
424 myHaveVia.clear();
425 int pos = 0;
426 EdgeVector::const_iterator i;
427 // normal connections
428 for (i = myIncoming.begin(); i != myIncoming.end(); i++) {
429 int noLanes = (*i)->getNumLanes();
430 for (int k = 0; k < noLanes; k++) {
431 pos = computeLaneResponse(*i, k, pos, checkLaneFoes || myJunction->getType() == SumoXMLNodeType::ZIPPER);
432 }
433 }
434 // crossings
435 auto crossings = myJunction->getCrossings();
436 for (auto c : crossings) {
437 pos = computeCrossingResponse(*c, pos);
438 }
439}
440
441void
443 // go through possible prohibitions
444 for (EdgeVector::const_iterator i11 = myIncoming.begin(); i11 != myIncoming.end(); i11++) {
445 int noLanesEdge1 = (*i11)->getNumLanes();
446 for (int j1 = 0; j1 < noLanesEdge1; j1++) {
447 std::vector<NBEdge::Connection> el1 = (*i11)->getConnectionsFromLane(j1);
448 for (std::vector<NBEdge::Connection>::iterator i12 = el1.begin(); i12 != el1.end(); ++i12) {
449 int idx1 = getIndex((*i11), (*i12).toEdge);
450 if (idx1 < 0) {
451 continue;
452 }
453 // go through possibly prohibited
454 for (EdgeVector::const_iterator i21 = myIncoming.begin(); i21 != myIncoming.end(); i21++) {
455 int noLanesEdge2 = (*i21)->getNumLanes();
456 for (int j2 = 0; j2 < noLanesEdge2; j2++) {
457 std::vector<NBEdge::Connection> el2 = (*i21)->getConnectionsFromLane(j2);
458 for (std::vector<NBEdge::Connection>::iterator i22 = el2.begin(); i22 != el2.end(); i22++) {
459 int idx2 = getIndex((*i21), (*i22).toEdge);
460 if (idx2 < 0) {
461 continue;
462 }
463 // check
464 // same incoming connections do not prohibit each other
465 if ((*i11) == (*i21)) {
466 myForbids[idx1][idx2] = false;
467 myForbids[idx2][idx1] = false;
468 continue;
469 }
470 // check other
471 // if both are non-signalised or both are signalised
472 if (((*i12).tlID == "" && (*i22).tlID == "")
473 ||
474 ((*i12).tlID != "" && (*i22).tlID != "")) {
475 // do nothing
476 continue;
477 }
478 // supposing, we don not have to
479 // brake if we are no foes
480 if (!foes(*i11, (*i12).toEdge, *i21, (*i22).toEdge)) {
481 continue;
482 }
483 // otherwise:
484 // the non-signalised must break
485 if ((*i12).tlID != "") {
486 myForbids[idx1][idx2] = true;
487 myForbids[idx2][idx1] = false;
488 } else {
489 myForbids[idx1][idx2] = false;
490 myForbids[idx2][idx1] = true;
491 }
492 }
493 }
494 }
495 }
496 }
497 }
498}
499
500
501std::pair<int, int>
503 int numLanes = 0;
504 int numLinks = 0;
505 for (const NBEdge* const e : myIncoming) {
506 const int numLanesEdge = e->getNumLanes();
507 for (int j = 0; j < numLanesEdge; j++) {
508 int numConnections = (int)e->getConnectionsFromLane(j).size();
509 numLinks += numConnections;
510 if (numConnections > 0) {
511 numLanes++;
512 }
513 }
514 }
515 return std::make_pair(numLanes, numLinks);
516}
517
518
519bool
520NBRequest::foes(const NBEdge* const from1, const NBEdge* const to1,
521 const NBEdge* const from2, const NBEdge* const to2) const {
522 // unconnected edges do not forbid other edges
523 if (to1 == nullptr || to2 == nullptr) {
524 return false;
525 }
526 // get the indices
527 int idx1 = getIndex(from1, to1);
528 int idx2 = getIndex(from2, to2);
529 if (idx1 < 0 || idx2 < 0) {
530 return false; // sure? (The connection does not exist within this junction)
531 }
532 assert(idx1 < (int)(myIncoming.size() * myOutgoing.size()));
533 assert(idx2 < (int)(myIncoming.size()*myOutgoing.size()));
534 return myForbids[idx1][idx2] || myForbids[idx2][idx1];
535}
536
537
538bool
539NBRequest::forbids(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
540 const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo,
541 bool regardNonSignalisedLowerPriority) const {
542 // unconnected edges do not forbid other edges
543 if (possProhibitorTo == nullptr || possProhibitedTo == nullptr) {
544 return false;
545 }
546 // get the indices
547 int possProhibitorIdx = getIndex(possProhibitorFrom, possProhibitorTo);
548 int possProhibitedIdx = getIndex(possProhibitedFrom, possProhibitedTo);
549 if (possProhibitorIdx < 0 || possProhibitedIdx < 0) {
550 return false; // sure? (The connection does not exist within this junction)
551 }
552 assert(possProhibitorIdx < (int)(myIncoming.size() * myOutgoing.size()));
553 assert(possProhibitedIdx < (int)(myIncoming.size() * myOutgoing.size()));
554 // check simple right-of-way-rules
555 if (!regardNonSignalisedLowerPriority) {
556 return myForbids[possProhibitorIdx][possProhibitedIdx];
557 }
558 // if its not forbidden, report
559 if (!myForbids[possProhibitorIdx][possProhibitedIdx]) {
560 return false;
561 }
562 // do not forbid a signalised stream by a non-signalised
563 if (!possProhibitorFrom->hasSignalisedConnectionTo(possProhibitorTo)) {
564 return false;
565 }
566 return true;
567}
568
569int
570NBRequest::computeLaneResponse(NBEdge* from, int fromLane, int pos, const bool checkLaneFoes) {
571 for (const NBEdge::Connection& c : from->getConnectionsFromLane(fromLane)) {
572 assert(c.toEdge != 0);
573 pos++;
574 const std::string foes = getFoesString(from, c.toEdge, fromLane, c.toLane, checkLaneFoes);
575 const std::string response = getResponseString(from, c, checkLaneFoes);
576 myFoes.push_back(foes);
577 myResponse.push_back(response);
578 myHaveVia.push_back(c.haveVia);
579 }
580 return pos;
581}
582
583
584int
586 std::string foes(myJunction->getCrossings().size(), '0');
587 std::string response(myJunction->getCrossings().size(), '0');
588 // conflicts with normal connections
589 for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
590 const NBEdge* from = *i;
591 for (int j = from->getNumLanes(); j-- > 0;) {
592 const std::vector<NBEdge::Connection>& connected = from->getConnectionsFromLane(j);
593 const int size = (int) connected.size();
594 for (int k = size; k-- > 0;) {
595 const NBEdge* to = connected[k].toEdge;
596 bool foe = false;
597 for (const NBEdge* const e : crossing.edges) {
598 if (e == from || e == to) {
599 foe = true;
600 break;
601 }
602 }
603 foes += foe ? '1' : '0';
604 response += mustBrakeForCrossing(myJunction, from, to, crossing) || !foe ? '0' : '1';
605 }
606 }
607 }
608 pos++;
609 myResponse.push_back(response);
610 myFoes.push_back(foes);
611 myHaveVia.push_back(false);
612 return pos;
613}
614
615
616std::string
617NBRequest::getResponseString(const NBEdge* const from, const NBEdge::Connection& c, const bool checkLaneFoes) const {
618 const NBEdge* const to = c.toEdge;
619 const int fromLane = c.fromLane;
620 const int toLane = c.toLane;
621 int idx = 0;
622 if (to != nullptr) {
623 idx = getIndex(from, to);
624 }
625 std::string result;
626 const bool zipper = myJunction->getType() == SumoXMLNodeType::ZIPPER;
627 // crossings
628 auto crossings = myJunction->getCrossings();
629 for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = crossings.rbegin(); i != crossings.rend(); i++) {
630 result += mustBrakeForCrossing(myJunction, from, to, **i) ? '1' : '0';
631 }
632 const NBEdge::Connection& queryCon = from->getConnection(fromLane, to, toLane);
633 // normal connections
634 for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
635 //const std::vector<NBEdge::Connection> &allConnections = (*i)->getConnections();
636 int noLanes = (*i)->getNumLanes();
637 for (int j = noLanes; j-- > 0;) {
638 std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
639 int size = (int) connected.size();
640 for (int k = size; k-- > 0;) {
641 if (c.mayDefinitelyPass) {
642 result += '0';
643#ifdef DEBUG_RESPONSE
644 if (DEBUGCOND) {
645 std::cout << " c=" << queryCon.getDescription(from) << " pass\n";
646 }
647#endif
648 } else if ((*i) == from && fromLane == j) {
649 // do not prohibit a connection by others from same lane
650 // except for indirect turns
651#ifdef DEBUG_RESPONSE
652 if (DEBUGCOND) {
653 std::cout << " c=" << queryCon.getDescription(from) << " prohibitC=" << connected[k].getDescription(*i)
654 << " itc=" << indirectLeftTurnConflict(from, queryCon, *i, connected[k], false)
655 << "\n";
656 }
657#endif
658 if (indirectLeftTurnConflict(from, queryCon, *i, connected[k], false)) {
659 result += '1';
660 } else {
661 result += '0';
662 }
663 } else {
664 assert(connected[k].toEdge != 0);
665 const int idx2 = getIndex(*i, connected[k].toEdge);
666 assert(k < (int) connected.size());
667 assert(idx < (int)(myIncoming.size() * myOutgoing.size()));
668 assert(idx2 < (int)(myIncoming.size() * myOutgoing.size()));
669 // check whether the connection is prohibited by another one
670#ifdef DEBUG_RESPONSE
671 if (DEBUGCOND) {
672 std::cout << " c=" << queryCon.getDescription(from) << " prohibitC=" << connected[k].getDescription(*i)
673 << " f=" << myForbids[idx2][idx]
674 << " clf=" << checkLaneFoes
675 << " clfbc=" << checkLaneFoesByClass(queryCon, *i, connected[k])
676 << " clfbcoop=" << checkLaneFoesByCooperation(from, queryCon, *i, connected[k])
677 << " lc=" << laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane)
678 << " rtc=" << NBNode::rightTurnConflict(from, to, fromLane, *i, connected[k].toEdge, connected[k].fromLane)
679 << " rtc2=" << rightTurnConflict(from, queryCon, *i, connected[k])
680 << " mc=" << mergeConflict(from, queryCon, *i, connected[k], false)
681 << " oltc=" << oppositeLeftTurnConflict(from, queryCon, *i, connected[k], false)
682 << " itc=" << indirectLeftTurnConflict(from, queryCon, *i, connected[k], zipper)
683 << " rorc=" << myJunction->rightOnRedConflict(c.tlLinkIndex, connected[k].tlLinkIndex)
684 << " tlscc=" << myJunction->tlsContConflict(from, c, *i, connected[k])
685 << "\n";
686 }
687#endif
688 const bool hasLaneConflict = (!(checkLaneFoes || checkLaneFoesByClass(queryCon, *i, connected[k])
689 || checkLaneFoesByCooperation(from, queryCon, *i, connected[k]))
690 || laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane));
691 if (((myForbids[idx2][idx] || (zipper && myForbids[idx][idx2])) && hasLaneConflict && !bidiConflict(*i, connected[k], from, queryCon, false))
692 || rightTurnConflict(from, queryCon, *i, connected[k])
693 || mergeConflict(from, queryCon, *i, connected[k], zipper)
694 || oppositeLeftTurnConflict(from, queryCon, *i, connected[k], zipper)
695 || indirectLeftTurnConflict(from, queryCon, *i, connected[k], zipper)
696 || bidiConflict(from, queryCon, *i, connected[k], false)
697 || myJunction->rightOnRedConflict(c.tlLinkIndex, connected[k].tlLinkIndex)
698 || (myJunction->tlsContConflict(from, c, *i, connected[k]) && hasLaneConflict
699 && !OptionsCont::getOptions().getBool("tls.ignore-internal-junction-jam"))
700 ) {
701 result += '1';
702 } else {
703 result += '0';
704 }
705 }
706 }
707 }
708 }
709 return result;
710}
711
712
713std::string
714NBRequest::getFoesString(NBEdge* from, NBEdge* to, int fromLane, int toLane, const bool checkLaneFoes) const {
715 const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
716 // remember the case when the lane is a "dead end" in the meaning that
717 // vehicles must choose another lane to move over the following
718 // junction
719 // !!! move to forbidden
720 std::string result;
721 // crossings
722 auto crossings = myJunction->getCrossings();
723 for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = crossings.rbegin(); i != crossings.rend(); i++) {
724 bool foes = false;
725 for (EdgeVector::const_iterator it_e = (**i).edges.begin(); it_e != (**i).edges.end(); ++it_e) {
726 if ((*it_e) == from || (*it_e) == to) {
727 foes = true;
728 break;
729 }
730 }
731 result += foes ? '1' : '0';
732 }
733 const NBEdge::Connection& queryCon = from->getConnection(fromLane, to, toLane);
734 // normal connections
735 for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
736 for (int j = (*i)->getNumLanes() - 1; j >= 0; --j) {
737 const std::vector<NBEdge::Connection>& connected = (*i)->getConnectionsFromLane(j);
738 int size = (int) connected.size();
739 for (int k = size; k-- > 0;) {
740 const bool hasLaneConflict = (!(checkLaneFoes || checkLaneFoesByClass(queryCon, *i, connected[k])
741 || checkLaneFoesByCooperation(from, queryCon, *i, connected[k]))
742 || laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane));
743 if ((foes(from, to, (*i), connected[k].toEdge) && hasLaneConflict)
744 || rightTurnConflict(from, queryCon, *i, connected[k])
745 || myJunction->turnFoes(from, to, fromLane, *i, connected[k].toEdge, connected[k].fromLane, lefthand)
746 || mergeConflict(from, queryCon, *i, connected[k], true)
747 || oppositeLeftTurnConflict(from, queryCon, *i, connected[k], true)
748 || indirectLeftTurnConflict(from, queryCon, *i, connected[k], true)
749 || bidiConflict(from, queryCon, *i, connected[k], true)
750 ) {
751 result += '1';
752 } else {
753 result += '0';
754 }
755 }
756 }
757 }
758 return result;
759}
760
761
762bool
764 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon) const {
765 return (!con.mayDefinitelyPass &&
766 (NBNode::rightTurnConflict(from, con.toEdge, con.fromLane, prohibitorFrom, prohibitorCon.toEdge, prohibitorCon.fromLane)
767 // reverse conflicht (override)
768 || (prohibitorCon.mayDefinitelyPass &&
769 NBNode::rightTurnConflict(prohibitorFrom, prohibitorCon.toEdge, prohibitorCon.fromLane, from, con.toEdge, con.fromLane))));
770
771
772}
773
774
775bool
777 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
778 if (from == prohibitorFrom
779 && con.toEdge == prohibitorCon.toEdge
780 && con.toLane == prohibitorCon.toLane
781 && con.fromLane != prohibitorCon.fromLane
783 if (foes) {
784 return true;
785 }
786 if (prohibitorCon.mayDefinitelyPass) {
787 return true;
788 }
789 if (con.mayDefinitelyPass) {
790 return false;
791 }
792 const bool bike = from->getPermissions(con.fromLane) == SVC_BICYCLE;
793 const bool prohibitorBike = prohibitorFrom->getPermissions(prohibitorCon.fromLane) == SVC_BICYCLE;
794 if (myOutgoing.size() == 1) {
795 // at on-ramp like situations, right lane should yield
796 return bike || (con.fromLane < prohibitorCon.fromLane && !prohibitorBike);
797 } else {
798 // priority depends on direction:
799 // for right turns the rightmost lane gets priority
800 // otherwise the left lane
802 if (dir == LinkDirection::RIGHT || dir == LinkDirection::PARTRIGHT) {
803 return con.fromLane > prohibitorCon.fromLane;
804 } else {
805 if (myIncoming.size() == 1) {
806 // at off-ramp like situations, right lane should pass unless it's a bicycle lane
807 return bike || (con.fromLane > prohibitorCon.fromLane && !prohibitorBike);
808 } else {
809 return con.fromLane < prohibitorCon.fromLane;
810 }
811 }
812 }
813
814 } else {
815 return false;
816 }
817}
818
819
820bool
822 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
824 // XXX lefthand issue (solve via #4256)
825 if (dir != LinkDirection::LEFT && dir != LinkDirection::PARTLEFT) {
826 return false;
827 }
828 dir = myJunction->getDirection(prohibitorFrom, prohibitorCon.toEdge);
829 if (dir != LinkDirection::LEFT && dir != LinkDirection::PARTLEFT) {
830 return false;
831 }
832 if (from == prohibitorFrom || NBRequest::foes(from, con.toEdge, prohibitorFrom, prohibitorCon.toEdge)) {
833 // not an opposite pair
834 return false;
835 }
836
837 const double width1 = MIN2(from->getLaneWidth(con.fromLane) / 2, OptionsCont::getOptions().getFloat("internal-junctions.vehicle-width") / 2);
838 const double width2 = prohibitorCon.toEdge->getLaneWidth(prohibitorCon.toLane) / 2;
839 PositionVector shape = con.shape;
840 shape.append(con.viaShape);
841 PositionVector otherShape = prohibitorCon.shape;
842 otherShape.append(prohibitorCon.viaShape);
843 if (shape.size() == 0 || otherShape.size() == 0) {
844 // no internal lanes built
845 return false;
846 }
847 const double minDV = NBEdge::firstIntersection(shape, otherShape, width1, width2);
848 if (minDV < shape.length() - POSITION_EPS && minDV > POSITION_EPS) {
849 // break symmetry using edge id
850 return foes || from->getID() < prohibitorFrom->getID();
851 }
852 return false;
853}
854
855bool
857 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
858 if (from == prohibitorFrom) {
859 if (con.toEdge == prohibitorCon.toEdge) {
860 return false;
861 } else if (con.indirectLeft) {
862 LinkDirection dir = myJunction->getDirection(prohibitorFrom, prohibitorCon.toEdge);
863 return (dir == LinkDirection::STRAIGHT);
864 } else if (foes && prohibitorCon.indirectLeft) {
866 return (dir == LinkDirection::STRAIGHT);
867 }
868 }
869 return false;
870}
871
872bool
874 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
875 if (from == prohibitorFrom) {
876 return false;
877 }
878 if (isRailway(from->getPermissions())) {
879 // railways manage right-of-way via signals
880 return false;
881 }
882 if ((foes && (from->getBidiEdge() == prohibitorCon.toEdge))
883 || prohibitorFrom->getBidiEdge() == con.toEdge) {
884 const bool fromBidi = from->getLaneShape(con.fromLane).reverse().almostSame(
885 prohibitorCon.toEdge->getLaneShape(prohibitorCon.toLane), POSITION_EPS);
886 const bool prohibitorFromBidi = prohibitorFrom->getLaneShape(prohibitorCon.fromLane).reverse().almostSame(
887 con.toEdge->getLaneShape(con.toLane), POSITION_EPS);
888 if (!foes && fromBidi && prohibitorFromBidi) {
889 // do not create a symmetrical conflict
890 return false;
891 }
892 if (prohibitorFromBidi &&
893 prohibitorFrom->getLaneShape(prohibitorCon.fromLane).reverse().almostSame(
894 prohibitorCon.toEdge->getLaneShape(prohibitorCon.toLane), POSITION_EPS)) {
895 // prohibitor has a bidi-turnaround
896 return false;
897 }
898
899 return fromBidi || prohibitorFromBidi;
900 }
901 return false;
902}
903
904bool
906 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon) const {
907 if (con.toEdge != prohibitorCon.toEdge) {
908 return false;
909 }
911 SVCPermissions svc2 = prohibitorFrom->getPermissions(prohibitorCon.fromLane) & prohibitorCon.toEdge->getPermissions(prohibitorCon.toLane);
912 // check for lane level conflict if the only common classes are bicycles or pedestrians
913 return ((svc & svc2 & ~(SVC_BICYCLE | SVC_PEDESTRIAN)) == 0
914 // or if the connection is to a dedicated lane whereas the prohibitor is a "general" lane
915 || (((svc & SVC_PASSENGER) == 0) && ((svc2 & SVC_PASSENGER) != 0)));
916}
917
918
919bool
921 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon) const {
922 if (con.toEdge != prohibitorCon.toEdge) {
923 return false;
924 }
925 // if from and prohibitorFrom target distinct lanes for all their
926 // connections to the common target edge, cooperation is possible
927 // (and should always happen unless the connections cross for some byzantine reason)
928
929 std::set<int> fromTargetLanes;
930 for (const NBEdge::Connection& c : from->getConnections()) {
931 if (c.toEdge == con.toEdge) {
932 fromTargetLanes.insert(c.toLane);
933 }
934 }
935 for (const NBEdge::Connection& c : prohibitorFrom->getConnections()) {
936 if (c.toEdge == con.toEdge && fromTargetLanes.count(c.toLane) != 0) {
937 //std::cout << " con=" << con->getDescription(from) << " foe=" << prohibitorCon.getDescription(prohibitorFrom)
938 // << " no cooperation (targets=" << joinToString(fromTargetLanes, ' ') << " index=" << c.toLane << "\n";
939 return false;
940 }
941 }
942 return true;
943}
944
945
946bool
947NBRequest::laneConflict(const NBEdge* from, const NBEdge* to, int toLane,
948 const NBEdge* prohibitorFrom, const NBEdge* prohibitorTo, int prohibitorToLane) const {
949 if (to != prohibitorTo) {
950 return true;
951 }
952 // since we know that the edge2edge connections are in conflict, the only
953 // situation in which the lane2lane connections can be conflict-free is, if
954 // they target the same edge but do not cross each other
955 double angle = NBHelpers::relAngle(
956 from->getAngleAtNode(from->getToNode()), to->getAngleAtNode(to->getFromNode()));
957 if (angle == 180) {
958 angle = -180; // turnarounds are left turns
959 }
960 const double prohibitorAngle = NBHelpers::relAngle(
961 prohibitorFrom->getAngleAtNode(prohibitorFrom->getToNode()), to->getAngleAtNode(to->getFromNode()));
962 const bool rightOfProhibitor = prohibitorFrom->isTurningDirectionAt(to)
963 || (angle > prohibitorAngle && !from->isTurningDirectionAt(to));
964 return rightOfProhibitor ? toLane >= prohibitorToLane : toLane <= prohibitorToLane;
965}
966
967int
968NBRequest::getIndex(const NBEdge* const from, const NBEdge* const to) const {
969 EdgeVector::const_iterator fp = std::find(myIncoming.begin(), myIncoming.end(), from);
970 EdgeVector::const_iterator tp = std::find(myOutgoing.begin(), myOutgoing.end(), to);
971 if (fp == myIncoming.end() || tp == myOutgoing.end()) {
972 return -1;
973 }
974 // compute the index
975 return (int)(distance(myIncoming.begin(), fp) * myOutgoing.size() + distance(myOutgoing.begin(), tp));
976}
977
978
979std::ostream&
980operator<<(std::ostream& os, const NBRequest& r) {
981 int variations = r.numLinks();
982 for (int i = 0; i < variations; i++) {
983 os << i << ' ';
984 for (int j = 0; j < variations; j++) {
985 if (r.myForbids[i][j]) {
986 os << '1';
987 } else {
988 os << '0';
989 }
990 }
991 os << std::endl;
992 }
993 os << std::endl;
994 return os;
995}
996
997
998bool
999NBRequest::mustBrake(const NBEdge* const from, const NBEdge* const to, int fromLane, int toLane, bool includePedCrossings) const {
1000 NBEdge::Connection con(fromLane, const_cast<NBEdge*>(to), toLane);
1001 const int linkIndex = myJunction->getConnectionIndex(from, con);
1002 if (linkIndex >= 0 && (int)myResponse.size() > linkIndex) {
1003 std::string response = getResponse(linkIndex);
1004 if (!includePedCrossings) {
1005 response = response.substr(0, response.size() - myJunction->getCrossings().size());
1006 }
1007 if (response.find_first_of("1") == std::string::npos) {
1008 return false;
1009 } else if (!myJunction->isTLControlled()) {
1010 return true;
1011 }
1012 // if the link must respond it could also be due to a tlsConflict. This
1013 // must not carry over the the off-state response so we continue with
1014 // the regular check
1015 }
1016 // get the indices
1017 int idx2 = getIndex(from, to);
1018 if (idx2 == -1) {
1019 return false;
1020 }
1021 // go through all (existing) connections;
1022 // check whether any of these forbids the one to determine
1023 assert(idx2 < (int)(myIncoming.size()*myOutgoing.size()));
1024 for (int idx1 = 0; idx1 < numLinks(); idx1++) {
1025 //assert(myDone[idx1][idx2]);
1026 if (myDone[idx1][idx2] && myForbids[idx1][idx2]) {
1027 return true;
1028 }
1029 }
1030 // maybe we need to brake for a pedestrian crossing
1031 if (includePedCrossings) {
1032 auto crossings = myJunction->getCrossings();
1033 for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = crossings.rbegin(); i != crossings.rend(); i++) {
1034 if (mustBrakeForCrossing(myJunction, from, to, **i)) {
1035 return true;
1036 }
1037 }
1038 }
1039 // maybe we need to brake due to a right-turn conflict with straight-going
1040 // bicycles
1041 const NBEdge::Connection& queryCon = from->getConnection(fromLane, to, toLane);
1042 LinkDirection dir = myJunction->getDirection(from, to);
1043 if (dir == LinkDirection::RIGHT || dir == LinkDirection::PARTRIGHT) {
1044 for (const NBEdge::Connection& fromCon : from->getConnections()) {
1045 if (rightTurnConflict(from, queryCon, from, fromCon)) {
1046 return true;
1047 }
1048 }
1049 }
1050 // maybe we need to brake due to a merge conflict
1051 for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
1052 int noLanes = (*i)->getNumLanes();
1053 for (int j = noLanes; j-- > 0;) {
1054 std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
1055 const int size = (int) connected.size();
1056 for (int k = size; k-- > 0;) {
1057 if ((*i) == from && fromLane != j
1058 && mergeConflict(from, queryCon, *i, connected[k], myJunction->getType() == SumoXMLNodeType::ZIPPER)) {
1059 return true;
1060 }
1061 }
1062 }
1063 }
1064 // maybe we need to brake due to a zipper conflict
1066 for (int idx1 = 0; idx1 < numLinks(); idx1++) {
1067 //assert(myDone[idx1][idx2]);
1068 if (myDone[idx1][idx2] && myForbids[idx2][idx1]) {
1069 return true;
1070 }
1071 }
1072 }
1073 return false;
1074}
1075
1076
1077bool
1078NBRequest::mustBrakeForCrossing(const NBNode* node, const NBEdge* const from, const NBEdge* const to, const NBNode::Crossing& crossing) {
1079 const LinkDirection dir = node->getDirection(from, to);
1080 const bool mustYield = dir == LinkDirection::LEFT || dir == LinkDirection::RIGHT;
1081 if (crossing.priority || mustYield) {
1082 for (const NBEdge* const e : crossing.edges) {
1083 // left and right turns must yield to unprioritized crossings only on their destination edge
1084 if ((e == from && crossing.priority) || e == to) {
1085 return true;
1086 }
1087 }
1088 }
1089 return false;
1090}
1091
1092
1093bool
1094NBRequest::mustBrake(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
1095 const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo) const {
1096 // get the indices
1097 int idx1 = getIndex(possProhibitorFrom, possProhibitorTo);
1098 int idx2 = getIndex(possProhibitedFrom, possProhibitedTo);
1099 return (myForbids[idx2][idx1]);
1100}
1101
1102
1103void
1105 // check if any errors occurred on build the link prohibitions
1106 if (myNotBuild != 0) {
1107 WRITE_WARNING(toString(myNotBuild) + " of " + toString(myNotBuild + myGoodBuilds) + " prohibitions were not build.");
1108 }
1109}
1110
1111
1112void
1114 // map from edge to number of incoming connections
1115 std::map<const NBEdge*, int> incomingCount; // initialized to 0
1116 // map from edge to indices of approached lanes
1117 std::map<const NBEdge*, std::set<int> > approachedLanes;
1118 // map from edge to list of incoming edges
1119 std::map<const NBEdge*, std::vector<const NBEdge*> > incomingEdges;
1120 for (const NBEdge* const e : myIncoming) {
1121 for (const NBEdge::Connection& con : e->getConnections()) {
1122 incomingCount[con.toEdge]++;
1123 approachedLanes[con.toEdge].insert(con.toLane);
1124 incomingEdges[con.toEdge].push_back(e);
1125 }
1126 }
1127 for (std::map<const NBEdge*, int>::iterator it = incomingCount.begin(); it != incomingCount.end(); ++it) {
1128 const NBEdge* const to = it->first;
1129 // we cannot test against to->getNumLanes() since not all lanes may be used
1130 if ((int)approachedLanes[to].size() >= it->second) {
1131 const std::vector<const NBEdge*>& incoming = incomingEdges[to];
1132 // make these connections mutually unconflicting
1133 for (const NBEdge* const e1 : incoming) {
1134 for (const NBEdge* const e2 : incoming) {
1135 myForbids[getIndex(e1, to)][getIndex(e2, to)] = false;
1136 }
1137 }
1138 }
1139 }
1140}
1141
1142
1143bool
1145 for (int i = 0; i < (int)myFoes.size(); i++) {
1146 if (hasConflictAtLink(i)) {
1147 return true;
1148 }
1149 }
1150 return false;
1151}
1152
1153bool
1154NBRequest::hasConflictAtLink(int linkIndex) const {
1155 return myFoes[linkIndex].find_first_of("1") != std::string::npos;
1156}
1157
1158int
1160 return (int)(myIncoming.size() * myOutgoing.size() + myJunction->getCrossings().size());
1161}
1162
1163
1164/****************************************************************************/
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:270
std::map< NBConnection, NBConnectionVector > NBConnectionProhibits
Definition of a container for connection block dependencies Includes a list of all connections which ...
std::vector< NBConnection > NBConnectionVector
Definition of a connection vector.
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:42
#define DEBUGCOND
Definition: NBRequest.cpp:44
std::ostream & operator<<(std::ostream &os, const NBRequest &r)
Definition: NBRequest.cpp:980
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission is a railway edge.
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_PEDESTRIAN
pedestrian
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
@ SUMO_TAG_REQUEST
description of a logic request within the junction
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)....
@ PARTLEFT
The link is a partial left direction.
@ RIGHT
The link is a (hard) right direction.
@ LEFT
The link is a (hard) left direction.
@ STRAIGHT
The link is a straight direction.
@ PARTRIGHT
The link is a partial right direction.
@ SUMO_ATTR_CONT
@ SUMO_ATTR_RESPONSE
@ SUMO_ATTR_INDEX
@ SUMO_ATTR_FOES
T MIN2(T a, T b)
Definition: StdDefs.h:76
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
NBEdge * getFrom() const
returns the from-edge (start of the connection)
NBEdge * getTo() const
returns the to-edge (end of the connection)
bool check(const NBEdgeCont &ec)
checks whether the edges are still valid
static void nextCCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
static void nextCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:59
The representation of a single edge during network building.
Definition: NBEdge.h:92
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:4232
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:1027
double getLaneWidth() const
Returns the default width of lanes of this edge.
Definition: NBEdge.h:632
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:536
const Connection & getConnection(int fromLane, const NBEdge *to, int toLane) const
Returns the specified connection (unmodifiable) This method goes through "myConnections" and returns ...
Definition: NBEdge.cpp:1235
const std::string & getID() const
Definition: NBEdge.h:1515
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:3516
bool hasSignalisedConnectionTo(const NBEdge *const e) const
Check if edge has signalised connections.
Definition: NBEdge.cpp:3850
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:510
std::vector< Connection > getConnectionsFromLane(int lane, const NBEdge *to=nullptr, int toLane=-1) const
Returns connections from a given lane.
Definition: NBEdge.cpp:1221
static double firstIntersection(const PositionVector &v1, const PositionVector &v2, double width1, double width2, const std::string &error="", bool secondIntersection=false)
compute the first intersection point between the given lane geometries considering their rspective wi...
Definition: NBEdge.cpp:1968
bool isConnectedTo(const NBEdge *e, const bool ignoreTurnaround=false) const
Returns the information whethe a connection to the given edge has been added (or computed)
Definition: NBEdge.cpp:1265
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
Definition: NBEdge.cpp:2051
const NBEdge * getBidiEdge() const
Definition: NBEdge.h:1501
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:529
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
Definition: NBEdge.cpp:2077
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
Definition: NBEdge.cpp:936
static double relAngle(double angle1, double angle2)
computes the relative angle between the two angles
Definition: NBHelpers.cpp:45
A definition of a pedestrian crossing.
Definition: NBNode.h:135
bool priority
whether the pedestrians have priority
Definition: NBNode.h:156
EdgeVector edges
The edges being crossed.
Definition: NBNode.h:142
Represents a single node (junction) during network building.
Definition: NBNode.h:66
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing, bool leftHand=false) const
Returns the representation of the described stream's direction.
Definition: NBNode.cpp:2315
int getConnectionIndex(const NBEdge *from, const NBEdge::Connection &con) const
return the index of the given connection
Definition: NBNode.cpp:3755
bool rightOnRedConflict(int index, int foeIndex) const
whether the given index must yield to the foeIndex while turing right on a red light
Definition: NBNode.cpp:3833
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:283
static bool rightTurnConflict(const NBEdge *from, const NBEdge *to, int fromLane, const NBEdge *prohibitorFrom, const NBEdge *prohibitorTo, int prohibitorFromLane)
return whether the given laneToLane connection is a right turn which must yield to a bicycle crossing...
Definition: NBNode.cpp:2000
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
Definition: NBNode.cpp:2905
bool isBentPriority() const
return whether a priority road turns at this node
Definition: NBNode.h:826
bool turnFoes(const NBEdge *from, const NBEdge *to, int fromLane, const NBEdge *from2, const NBEdge *to2, int fromLane2, bool lefthand=false) const
return whether the given laneToLane connection originate from the same edge and are in conflict due t...
Definition: NBNode.cpp:2080
bool isConstantWidthTransition() const
detects whether a given junction splits or merges lanes while keeping constant road width
Definition: NBNode.cpp:843
bool tlsContConflict(const NBEdge *from, const NBEdge::Connection &c, const NBEdge *foeFrom, const NBEdge::Connection &foe) const
whether the connection must yield if the foe remains on the intersection after its phase ends
Definition: NBNode.cpp:954
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:329
std::vector< std::string > myResponse
Definition: NBRequest.h:282
const EdgeVector & myOutgoing
edges outgoing from the junction
Definition: NBRequest.h:266
CombinationsCont myForbids
the link X link blockings
Definition: NBRequest.h:275
int computeLaneResponse(NBEdge *from, int lane, int pos, const bool checkLaneFoes)
computes the response of a certain lane Returns the next link index within the junction
Definition: NBRequest.cpp:570
CombinationsCont myDone
the link X link is done-checks
Definition: NBRequest.h:278
const EdgeVector & myAll
all (icoming and outgoing) of the junctions edges
Definition: NBRequest.h:260
bool checkLaneFoesByCooperation(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon) const
whether the given connections must be checked for lane conflicts due to disjunct target lanes
Definition: NBRequest.cpp:920
std::vector< std::string > myFoes
precomputed right-of-way matrices for each lane-to-lane link
Definition: NBRequest.h:281
int distanceCounterClockwise(NBEdge *from, NBEdge *to)
returns the distance between the incoming (from) and the outgoing (to) edge clockwise in edges
Definition: NBRequest.cpp:369
bool bidiConflict(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon, bool foes) const
whether straight connections are in conflict via bidirectional lane use
Definition: NBRequest.cpp:873
bool forbids(const NBEdge *const possProhibitorFrom, const NBEdge *const possProhibitorTo, const NBEdge *const possProhibitedFrom, const NBEdge *const possProhibitedTo, bool regardNonSignalisedLowerPriority) const
Returns the information whether "prohibited" flow must let "prohibitor" flow pass.
Definition: NBRequest.cpp:539
bool hasConflictAtLink(int linkIndex) const
whether there are conflicting streams of traffic for the given link index
Definition: NBRequest.cpp:1154
const EdgeVector & myIncoming
edges incoming to the junction
Definition: NBRequest.h:263
NBNode * myJunction
the node the request is assigned to
Definition: NBRequest.h:257
int numLinks() const
return to total number of edge-to-edge connections of this request-logic
Definition: NBRequest.cpp:1159
const std::string & getFoes(int linkIndex) const
Definition: NBRequest.cpp:383
bool hasConflict() const
whether there are conflicting streams of traffic at this node
Definition: NBRequest.cpp:1144
std::string getFoesString(NBEdge *from, NBEdge *to, int fromLane, int toLane, const bool checkLaneFoes) const
Definition: NBRequest.cpp:714
void buildBitfieldLogic()
builds the bitset-representation of the logic
Definition: NBRequest.cpp:145
bool oppositeLeftTurnConflict(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon, bool foes) const
whether opposite left turns intersect
Definition: NBRequest.cpp:821
bool laneConflict(const NBEdge *from, const NBEdge *to, int toLane, const NBEdge *prohibitorFrom, const NBEdge *prohibitorTo, int prohibitorToLane) const
return whether the given laneToLane connections prohibit each other under the assumption that the edg...
Definition: NBRequest.cpp:947
void resetSignalised()
Definition: NBRequest.cpp:442
bool indirectLeftTurnConflict(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon, bool foes) const
whether straight and indirect left turn are in conflict
Definition: NBRequest.cpp:856
int getIndex(const NBEdge *const from, const NBEdge *const to) const
Returns the index to the internal combination container for the given edge combination.
Definition: NBRequest.cpp:968
static bool mustBrakeForCrossing(const NBNode *node, const NBEdge *const from, const NBEdge *const to, const NBNode::Crossing &crossing)
Returns the information whether the described flow must brake for the given crossing.
Definition: NBRequest.cpp:1078
void computeRightOutgoingLinkCrossings(NBEdge *from, NBEdge *to)
computes the relationships between links outgoing right of the given link *‍/
Definition: NBRequest.cpp:161
bool mergeConflict(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon, bool foes) const
whether multple connections from the same edge target the same lane
Definition: NBRequest.cpp:776
void writeLogic(OutputDevice &into) const
Definition: NBRequest.cpp:399
NBRequest(const NBEdgeCont &ec, NBNode *junction, const EdgeVector &all, const EdgeVector &incoming, const EdgeVector &outgoing, const NBConnectionProhibits &loadedProhibits)
Definition: NBRequest.cpp:56
void computeLogic(const bool checkLaneFoes)
writes the XML-representation of the logic as a bitset-logic XML representation
Definition: NBRequest.cpp:421
std::string getResponseString(const NBEdge *const from, const NBEdge::Connection &c, const bool checkLaneFoes) const
Writes the response of a certain link.
Definition: NBRequest.cpp:617
std::pair< int, int > getSizes() const
returns the number of the junction's lanes and the number of the junction's links in respect.
Definition: NBRequest.cpp:502
bool mustBrake(const NBEdge *const possProhibitorFrom, const NBEdge *const possProhibitorTo, const NBEdge *const possProhibitedFrom, const NBEdge *const possProhibitedTo) const
Returns the information whether "prohibited" flow must let "prohibitor" flow pass.
Definition: NBRequest.cpp:1094
const std::string & getResponse(int linkIndex) const
Definition: NBRequest.cpp:391
int computeCrossingResponse(const NBNode::Crossing &crossing, int pos)
computes the response of a certain crossing Returns the next link index within the junction
Definition: NBRequest.cpp:585
void setBlocking(NBEdge *from1, NBEdge *to1, NBEdge *from2, NBEdge *to2)
Definition: NBRequest.cpp:197
void computeLeftOutgoingLinkCrossings(NBEdge *from, NBEdge *to)
computes the relationships between links outgoing left of the given link
Definition: NBRequest.cpp:179
bool checkLaneFoesByClass(const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon) const
whether the given connections must be checked for lane conflicts due to the vClasses involved
Definition: NBRequest.cpp:905
void resetCooperating()
reset foes it the number of lanes matches (or exceeds) the number of incoming connections for an edge
Definition: NBRequest.cpp:1113
~NBRequest()
destructor
Definition: NBRequest.cpp:141
bool foes(const NBEdge *const from1, const NBEdge *const to1, const NBEdge *const from2, const NBEdge *const to2) const
Returns the information whether the given flows cross.
Definition: NBRequest.cpp:520
static int myNotBuild
Definition: NBRequest.h:286
bool rightTurnConflict(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon) const
whether the given connections crosses the foe connection from the same lane and must yield
Definition: NBRequest.cpp:763
static void reportWarnings()
reports warnings if any occurred
Definition: NBRequest.cpp:1104
static int myGoodBuilds
Definition: NBRequest.h:286
std::vector< bool > LinkInfoCont
definition of a container to store boolean informations about a link into
Definition: NBRequest.h:269
std::vector< bool > myHaveVia
Definition: NBRequest.h:283
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:60
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
OutputDevice & writePadding(const std::string &val)
writes padding (ignored for binary output)
Definition: OutputDevice.h:317
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
A list of positions.
void append(const PositionVector &v, double sameThreshold=2.0)
double length() const
Returns the length.
bool almostSame(const PositionVector &v2, double maxDiv=POSITION_EPS) const
check if the two vectors have the same length and pairwise similar positions
PositionVector reverse() const
reverse position vector
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:201
bool indirectLeft
Whether this connection is an indirect left turn.
Definition: NBEdge.h:261
int fromLane
The lane the connections starts at.
Definition: NBEdge.h:210
int toLane
The lane the connections yields in.
Definition: NBEdge.h:216
NBEdge * toEdge
The edge the connections yields in.
Definition: NBEdge.h:213
bool mayDefinitelyPass
Information about being definitely free to drive (on-ramps)
Definition: NBEdge.h:228
PositionVector viaShape
shape of via
Definition: NBEdge.h:282
std::string getDescription(const NBEdge *parent) const
get string describing this connection
Definition: NBEdge.cpp:96
PositionVector shape
shape of Connection
Definition: NBEdge.h:270
int tlLinkIndex
The index of this connection within the controlling traffic light.
Definition: NBEdge.h:222