Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
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-2025 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
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 LinkDirection ld1 = myJunction->getDirection(from1, to1);
282 LinkDirection ld2 = myJunction->getDirection(from2, to2);
283 if (!typeEqual && !myJunction->isBentPriority()) {
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#ifdef DEBUG_SETBLOCKING
325 if (DEBUGCOND) std::cout << "setBlocking1"
326 << " 1:" << from1->getID() << "->" << to1->getID()
327 << " 2:" << from2->getID() << "->" << to2->getID();
328 << " relAngle=" << NBHelpers::relAngle(from1->getAngleAtNode(myJunction), from2->getAngleAtNode(myJunction))
329#endif
330
331 // compute the yielding due to the right-before-left rule
332 // (or left-before-right rule)
333 // get the position of the incoming lanes in the junction-wheel
334 EdgeVector::const_iterator c1 = std::find(myAll.begin(), myAll.end(), from1);
336 // go through next edges clockwise...
337 while (*c1 != from1 && *c1 != from2) {
338 if (*c1 == to2) {
339 // if we encounter to2 the second one prohibits the first
341 && (ld1 != LinkDirection::LEFT || ld2 == LinkDirection::LEFT || (from1->getTurnDestination(true) != to2 &&
342 (ld2 != LinkDirection::RIGHT ||
344 from2->getAngleAtNode(myJunction))) < 150))
345 )) {
346 myForbids[idx1][idx2] = true;
347#ifdef DEBUG_SETBLOCKING
348 if (DEBUGCOND) {
349 std::cout << " case1: 2 yields\n";
350 }
351#endif
352 } else {
353 myForbids[idx2][idx1] = true;
354#ifdef DEBUG_SETBLOCKING
355 if (DEBUGCOND) {
356 std::cout << " case1: 1 yields\n";
357 }
358#endif
359 }
360 return;
361 }
363 }
364 // get the position of the incoming lanes in the junction-wheel
365 EdgeVector::const_iterator c2 = std::find(myAll.begin(), myAll.end(), from2);
367 // go through next edges clockwise...
368 while (*c2 != from2 && *c2 != from1) {
369 if (*c2 == to1) {
370 // if we encounter to1 the second one prohibits the first
372 && (ld2 != LinkDirection::LEFT || ld1 == LinkDirection::LEFT || (from2->getTurnDestination(true) != to1 &&
373 (ld1 != LinkDirection::RIGHT ||
375 from2->getAngleAtNode(myJunction))) < 150))
376 )) {
377 myForbids[idx2][idx1] = true;
378#ifdef DEBUG_SETBLOCKING
379 if (DEBUGCOND) {
380 std::cout << " case2: 1 yields\n";
381 }
382#endif
383 } else {
384 myForbids[idx1][idx2] = true;
385#ifdef DEBUG_SETBLOCKING
386 if (DEBUGCOND) {
387 std::cout << " case2: 2 yields\n";
388 }
389#endif
390 }
391 return;
392 }
394 }
395#ifdef DEBUG_SETBLOCKING
396 if (DEBUGCOND) {
397 std::cout << " noDecision\n";
398 }
399#endif
400}
401
402
403int
405 EdgeVector::const_iterator p = std::find(myAll.begin(), myAll.end(), from);
406 int ret = 0;
407 do {
408 ret++;
409 if (p == myAll.begin()) {
410 p = myAll.end();
411 }
412 p--;
413 } while (*p != to);
414 return ret;
415}
416
417const std::string&
418NBRequest::getFoes(int linkIndex) const {
419 assert(linkIndex >= 0);
420 assert(linkIndex < (int)myFoes.size());
421 return myFoes[linkIndex];
422}
423
424
425const std::string&
426NBRequest::getResponse(int linkIndex) const {
427 assert(linkIndex >= 0);
428 assert(linkIndex < (int)myResponse.size());
429 return myResponse[linkIndex];
430}
431
432
433void
435 int numLinks = (int)myResponse.size();
436 assert((int)myFoes.size() == numLinks);
437 assert((int)myHaveVia.size() == numLinks);
438 const bool padding = numLinks > 10;
439 for (int i = 0; i < numLinks; i++) {
441 into.writeAttr(SUMO_ATTR_INDEX, i);
442 if (padding && i < 10) {
443 into.writePadding(" ");
444 }
447 if (!OptionsCont::getOptions().getBool("no-internal-links")) {
449 }
450 into.closeTag();
451 }
452}
453
454
455void
456NBRequest::computeLogic(const bool checkLaneFoes) {
457 myResponse.clear();
458 myFoes.clear();
459 myHaveVia.clear();
460 int pos = 0;
461 EdgeVector::const_iterator i;
462 // normal connections
463 for (i = myIncoming.begin(); i != myIncoming.end(); i++) {
464 int noLanes = (*i)->getNumLanes();
465 for (int k = 0; k < noLanes; k++) {
466 pos = computeLaneResponse(*i, k, pos, checkLaneFoes || myJunction->getType() == SumoXMLNodeType::ZIPPER);
467 }
468 }
469 // crossings
470 auto crossings = myJunction->getCrossings();
471 for (auto c : crossings) {
472 pos = computeCrossingResponse(*c, pos);
473 }
474}
475
476void
478 // go through possible prohibitions
479 for (EdgeVector::const_iterator i11 = myIncoming.begin(); i11 != myIncoming.end(); i11++) {
480 int noLanesEdge1 = (*i11)->getNumLanes();
481 for (int j1 = 0; j1 < noLanesEdge1; j1++) {
482 std::vector<NBEdge::Connection> el1 = (*i11)->getConnectionsFromLane(j1);
483 for (std::vector<NBEdge::Connection>::iterator i12 = el1.begin(); i12 != el1.end(); ++i12) {
484 int idx1 = getIndex((*i11), (*i12).toEdge);
485 if (idx1 < 0) {
486 continue;
487 }
488 // go through possibly prohibited
489 for (EdgeVector::const_iterator i21 = myIncoming.begin(); i21 != myIncoming.end(); i21++) {
490 int noLanesEdge2 = (*i21)->getNumLanes();
491 for (int j2 = 0; j2 < noLanesEdge2; j2++) {
492 std::vector<NBEdge::Connection> el2 = (*i21)->getConnectionsFromLane(j2);
493 for (std::vector<NBEdge::Connection>::iterator i22 = el2.begin(); i22 != el2.end(); i22++) {
494 int idx2 = getIndex((*i21), (*i22).toEdge);
495 if (idx2 < 0) {
496 continue;
497 }
498 // check
499 // same incoming connections do not prohibit each other
500 if ((*i11) == (*i21)) {
501 myForbids[idx1][idx2] = false;
502 myForbids[idx2][idx1] = false;
503#ifdef DEBUG_SETBLOCKING
504 if (DEBUGCOND) std::cout << "resetSignalised both"
505 << " 1:" << (*i11)->getID() << "->" << (*i12).toEdge->getID()
506 << " 2:" << (*i21)->getID() << "->" << (*i22).toEdge->getID()
507 << "\n";
508#endif
509 continue;
510 }
511 // check other
512 // if both are non-signalised or both are signalised
513 if (((*i12).tlID == "" && (*i22).tlID == "")
514 ||
515 ((*i12).tlID != "" && (*i22).tlID != "")) {
516 // do nothing
517 continue;
518 }
519 // supposing, we don not have to
520 // brake if we are no foes
521 if (!foes(*i11, (*i12).toEdge, *i21, (*i22).toEdge)) {
522 continue;
523 }
524 // otherwise:
525 // the non-signalised must break
526 if ((*i12).tlID != "") {
527 myForbids[idx1][idx2] = true;
528 myForbids[idx2][idx1] = false;
529#ifdef DEBUG_SETBLOCKING
530 if (DEBUGCOND) std::cout << "resetSignalised:2 yields"
531 << " 1:" << (*i11)->getID() << "->" << (*i12).toEdge->getID()
532 << " 2:" << (*i21)->getID() << "->" << (*i22).toEdge->getID() << "\n";
533#endif
534 } else {
535 myForbids[idx1][idx2] = false;
536 myForbids[idx2][idx1] = true;
537#ifdef DEBUG_SETBLOCKING
538 if (DEBUGCOND) std::cout << "resetSignalised:1 yields"
539 << " 1:" << (*i11)->getID() << "->" << (*i12).toEdge->getID()
540 << " 2:" << (*i21)->getID() << "->" << (*i22).toEdge->getID() << "\n";
541#endif
542 }
543 }
544 }
545 }
546 }
547 }
548 }
549}
550
551
552std::pair<int, int>
554 int numLanes = 0;
555 int numLinks = 0;
556 for (const NBEdge* const e : myIncoming) {
557 const int numLanesEdge = e->getNumLanes();
558 for (int j = 0; j < numLanesEdge; j++) {
559 int numConnections = (int)e->getConnectionsFromLane(j).size();
560 numLinks += numConnections;
561 if (numConnections > 0) {
562 numLanes++;
563 }
564 }
565 }
566 return std::make_pair(numLanes, numLinks);
567}
568
569
570bool
571NBRequest::foes(const NBEdge* const from1, const NBEdge* const to1,
572 const NBEdge* const from2, const NBEdge* const to2) const {
573 // unconnected edges do not forbid other edges
574 if (to1 == nullptr || to2 == nullptr) {
575 return false;
576 }
577 // get the indices
578 int idx1 = getIndex(from1, to1);
579 int idx2 = getIndex(from2, to2);
580 if (idx1 < 0 || idx2 < 0) {
581 return false; // sure? (The connection does not exist within this junction)
582 }
583 assert(idx1 < (int)(myIncoming.size() * myOutgoing.size()));
584 assert(idx2 < (int)(myIncoming.size()*myOutgoing.size()));
585 return myForbids[idx1][idx2] || myForbids[idx2][idx1];
586}
587
588
589bool
590NBRequest::forbids(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
591 const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo,
592 bool regardNonSignalisedLowerPriority) const {
593 // unconnected edges do not forbid other edges
594 if (possProhibitorTo == nullptr || possProhibitedTo == nullptr) {
595 return false;
596 }
597 // get the indices
598 int possProhibitorIdx = getIndex(possProhibitorFrom, possProhibitorTo);
599 int possProhibitedIdx = getIndex(possProhibitedFrom, possProhibitedTo);
600 if (possProhibitorIdx < 0 || possProhibitedIdx < 0) {
601 return false; // sure? (The connection does not exist within this junction)
602 }
603 assert(possProhibitorIdx < (int)(myIncoming.size() * myOutgoing.size()));
604 assert(possProhibitedIdx < (int)(myIncoming.size() * myOutgoing.size()));
605 // check simple right-of-way-rules
606 if (!regardNonSignalisedLowerPriority) {
607 return myForbids[possProhibitorIdx][possProhibitedIdx];
608 }
609 // if its not forbidden, report
610 if (!myForbids[possProhibitorIdx][possProhibitedIdx]) {
611 return false;
612 }
613 // do not forbid a signalised stream by a non-signalised
614 if (!possProhibitorFrom->hasSignalisedConnectionTo(possProhibitorTo)) {
615 return false;
616 }
617 return true;
618}
619
620int
621NBRequest::computeLaneResponse(NBEdge* from, int fromLane, int pos, const bool checkLaneFoes) {
622 for (const NBEdge::Connection& c : from->getConnectionsFromLane(fromLane)) {
623 assert(c.toEdge != 0);
624 pos++;
625 const std::string foes = getFoesString(from, c, checkLaneFoes);
626 const std::string response = getResponseString(from, c, checkLaneFoes);
627 myFoes.push_back(foes);
628 myResponse.push_back(response);
629 myHaveVia.push_back(c.haveVia);
630 }
631 return pos;
632}
633
634
635int
637 std::string foes(myJunction->getCrossings().size(), '0');
638 std::string response(myJunction->getCrossings().size(), '0');
639 // conflicts with normal connections
640 for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
641 const NBEdge* from = *i;
642 for (int j = from->getNumLanes(); j-- > 0;) {
643 const std::vector<NBEdge::Connection>& connected = from->getConnectionsFromLane(j);
644 const int size = (int) connected.size();
645 for (int k = size; k-- > 0;) {
646 const NBEdge* to = connected[k].toEdge;
647 bool foe = false;
648 for (const NBEdge* const e : crossing.edges) {
649 if (e == from || e == to) {
650 foe = true;
651 break;
652 }
653 }
654 foes += foe ? '1' : '0';
655 response += mustBrakeForCrossing(myJunction, from, to, crossing) || !foe ? '0' : '1';
656 }
657 }
658 }
659 pos++;
660 myResponse.push_back(response);
661 myFoes.push_back(foes);
662 myHaveVia.push_back(false);
663 return pos;
664}
665
666
667std::string
668NBRequest::getResponseString(const NBEdge* const from, const NBEdge::Connection& c, const bool checkLaneFoes) const {
669 const NBEdge* const to = c.toEdge;
670 const int fromLane = c.fromLane;
671 const int toLane = c.toLane;
672 int idx = 0;
673 if (to != nullptr) {
674 idx = getIndex(from, to);
675 }
676 std::string result;
677 const bool zipper = myJunction->getType() == SumoXMLNodeType::ZIPPER;
678 // crossings
679 auto crossings = myJunction->getCrossings();
680 for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = crossings.rbegin(); i != crossings.rend(); i++) {
681 result += mustBrakeForCrossing(myJunction, from, to, **i) ? '1' : '0';
682 }
683 // normal connections
684 for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
685 //const std::vector<NBEdge::Connection> &allConnections = (*i)->getConnections();
686 int noLanes = (*i)->getNumLanes();
687 for (int j = noLanes; j-- > 0;) {
688 std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
689 int size = (int) connected.size();
690 for (int k = size; k-- > 0;) {
691 if (c.mayDefinitelyPass) {
692 result += '0';
693#ifdef DEBUG_RESPONSE
694 if (DEBUGCOND) {
695 std::cout << " c=" << c.getDescription(from) << " pass\n";
696 }
697#endif
698 } else if ((*i) == from && fromLane == j) {
699 // do not prohibit a connection by others from same lane
700 // except for indirect turns
701#ifdef DEBUG_RESPONSE
702 if (DEBUGCOND) {
703 std::cout << " c=" << c.getDescription(from) << " prohibitC=" << connected[k].getDescription(*i)
704 << " itc=" << indirectLeftTurnConflict(from, c, *i, connected[k], false)
705 << "\n";
706 }
707#endif
708 if (indirectLeftTurnConflict(from, c, *i, connected[k], false)) {
709 result += '1';
710 } else {
711 result += '0';
712 }
713 } else {
714 assert(connected[k].toEdge != 0);
715 const int idx2 = getIndex(*i, connected[k].toEdge);
716 assert(k < (int) connected.size());
717 assert(idx < (int)(myIncoming.size() * myOutgoing.size()));
718 assert(idx2 < (int)(myIncoming.size() * myOutgoing.size()));
719 // check whether the connection is prohibited by another one
720#ifdef DEBUG_RESPONSE
721 if (DEBUGCOND) {
722 std::cout << " c=" << c.getDescription(from) << " prohibitC=" << connected[k].getDescription(*i)
723 << " idx=" << idx << " idx2=" << idx2
724 << " f=" << myForbids[idx2][idx]
725 << " clf=" << checkLaneFoes
726 << " clfbc=" << checkLaneFoesByClass(c, *i, connected[k])
727 << " clfbcoop=" << checkLaneFoesByCooperation(from, c, *i, connected[k])
728 << " lc=" << laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane)
729 << " rtc=" << NBNode::rightTurnConflict(from, to, fromLane, *i, connected[k].toEdge, connected[k].fromLane)
730 << " rtc2=" << rightTurnConflict(from, c, *i, connected[k])
731 << " mc=" << mergeConflict(from, c, *i, connected[k], false)
732 << " oltc=" << oppositeLeftTurnConflict(from, c, *i, connected[k], false)
733 << " itc=" << indirectLeftTurnConflict(from, c, *i, connected[k], zipper)
734 << " bc=" << bidiConflict(from, c, *i, connected[k], false)
735 << " ec=" << (myJunction->extraConflict(c.tlLinkIndex, connected[k].tlLinkIndex) && (myForbids[idx2][idx] || myForbids[idx][idx2]))
736 << " tlscc=" << myJunction->tlsContConflict(from, c, *i, connected[k])
737 << "\n";
738 }
739#endif
740 const bool hasLaneConflict = (!(checkLaneFoes || checkLaneFoesByClass(c, *i, connected[k])
741 || checkLaneFoesByCooperation(from, c, *i, connected[k]))
742 || laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane));
743 if (((myForbids[idx2][idx] || (zipper && myForbids[idx][idx2])) && hasLaneConflict && !bidiConflict(*i, connected[k], from, c, false))
744 || rightTurnConflict(from, c, *i, connected[k])
745 || mergeConflict(from, c, *i, connected[k], zipper)
746 || oppositeLeftTurnConflict(from, c, *i, connected[k], zipper)
747 || indirectLeftTurnConflict(from, c, *i, connected[k], zipper)
748 || bidiConflict(from, c, *i, connected[k], false)
749 // the extra conflict could be specific to another connection within the same signal group
750 || (myJunction->extraConflict(c.tlLinkIndex, connected[k].tlLinkIndex) && (myForbids[idx2][idx] || myForbids[idx][idx2]))
751 || (myJunction->tlsContConflict(from, c, *i, connected[k]) && hasLaneConflict
752 && !OptionsCont::getOptions().getBool("tls.ignore-internal-junction-jam"))
753 ) {
754 result += '1';
755 } else {
756 result += '0';
757 }
758 }
759 }
760 }
761 }
762 return result;
763}
764
765
766std::string
767NBRequest::getFoesString(NBEdge* from, const NBEdge::Connection& c, const bool checkLaneFoes) const {
768 const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
769 // remember the case when the lane is a "dead end" in the meaning that
770 // vehicles must choose another lane to move over the following
771 // junction
772 // !!! move to forbidden
773 std::string result;
774 // crossings
775 auto crossings = myJunction->getCrossings();
776 for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = crossings.rbegin(); i != crossings.rend(); i++) {
777 bool foes = false;
778 for (EdgeVector::const_iterator it_e = (**i).edges.begin(); it_e != (**i).edges.end(); ++it_e) {
779 if ((*it_e) == from || (*it_e) == c.toEdge) {
780 foes = true;
781 break;
782 }
783 }
784 result += foes ? '1' : '0';
785 }
786 // normal connections
787 for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
788 for (int j = (*i)->getNumLanes() - 1; j >= 0; --j) {
789 const std::vector<NBEdge::Connection>& connected = (*i)->getConnectionsFromLane(j);
790 int size = (int) connected.size();
791 for (int k = size; k-- > 0;) {
792 const bool hasLaneConflict = (!(checkLaneFoes || checkLaneFoesByClass(c, *i, connected[k])
793 || checkLaneFoesByCooperation(from, c, *i, connected[k]))
794 || laneConflict(from, c.toEdge, c.toLane, *i, connected[k].toEdge, connected[k].toLane));
795 if ((foes(from, c.toEdge, (*i), connected[k].toEdge) && hasLaneConflict)
796 || rightTurnConflict(from, c, *i, connected[k])
797 || myJunction->turnFoes(from, c.toEdge, c.fromLane, *i, connected[k].toEdge, connected[k].fromLane, lefthand)
798 || mergeConflict(from, c, *i, connected[k], true)
799 || oppositeLeftTurnConflict(from, c, *i, connected[k], true)
800 || indirectLeftTurnConflict(from, c, *i, connected[k], true)
801 || bidiConflict(from, c, *i, connected[k], true)
802 ) {
803 result += '1';
804 } else {
805 result += '0';
806 }
807 }
808 }
809 }
810 return result;
811}
812
813
814bool
816 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon) const {
817 return (!con.mayDefinitelyPass &&
818 (NBNode::rightTurnConflict(from, con.toEdge, con.fromLane, prohibitorFrom, prohibitorCon.toEdge, prohibitorCon.fromLane)
819 // reverse conflicht (override)
820 || (prohibitorCon.mayDefinitelyPass &&
821 NBNode::rightTurnConflict(prohibitorFrom, prohibitorCon.toEdge, prohibitorCon.fromLane, from, con.toEdge, con.fromLane))));
822
823
824}
825
826
827bool
829 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
830 if (from == prohibitorFrom
831 && con.toEdge == prohibitorCon.toEdge
832 && ((con.toLane == prohibitorCon.toLane
833 && con.fromLane != prohibitorCon.fromLane
835 // this is actually a crossing rather than a merger
836 || (con.fromLane > prohibitorCon.fromLane && con.toLane < prohibitorCon.toLane)
837 || (con.fromLane < prohibitorCon.fromLane && con.toLane > prohibitorCon.toLane))) {
838 if (foes) {
839 return true;
840 }
841 if (prohibitorCon.mayDefinitelyPass) {
842 return true;
843 }
844 if (con.mayDefinitelyPass) {
845 return false;
846 }
847 const bool bike = from->getPermissions(con.fromLane) == SVC_BICYCLE;
848 const bool prohibitorBike = prohibitorFrom->getPermissions(prohibitorCon.fromLane) == SVC_BICYCLE;
849 if (myOutgoing.size() == 1) {
850 // at on-ramp like situations, right lane should yield
851 return bike || (con.fromLane < prohibitorCon.fromLane && !prohibitorBike);
852 } else {
853 // priority depends on direction:
854 // for right turns the rightmost lane gets priority
855 // otherwise the left lane
857 if (dir == LinkDirection::RIGHT || dir == LinkDirection::PARTRIGHT) {
858 return con.fromLane > prohibitorCon.fromLane;
859 } else {
860 if (myIncoming.size() == 1) {
861 // at off-ramp like situations, right lane should pass unless it's a bicycle lane
862 return bike || (con.fromLane > prohibitorCon.fromLane && !prohibitorBike);
863 } else {
864 return con.fromLane < prohibitorCon.fromLane;
865 }
866 }
867 }
868
869 } else {
870 return false;
871 }
872}
873
874
875bool
877 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
879 // XXX lefthand issue (solve via #4256)
880 if (dir != LinkDirection::LEFT && dir != LinkDirection::PARTLEFT) {
881 return false;
882 }
883 dir = myJunction->getDirection(prohibitorFrom, prohibitorCon.toEdge);
884 if (dir != LinkDirection::LEFT && dir != LinkDirection::PARTLEFT) {
885 return false;
886 }
887 if (from == prohibitorFrom || NBRequest::foes(from, con.toEdge, prohibitorFrom, prohibitorCon.toEdge)) {
888 // not an opposite pair
889 return false;
890 }
891
892 const double width1 = MIN2(from->getLaneWidth(con.fromLane) / 2, OptionsCont::getOptions().getFloat("internal-junctions.vehicle-width") / 2);
893 const double width2 = prohibitorCon.toEdge->getLaneWidth(prohibitorCon.toLane) / 2;
894 PositionVector shape = con.shape;
895 shape.append(con.viaShape);
896 PositionVector otherShape = prohibitorCon.shape;
897 otherShape.append(prohibitorCon.viaShape);
898 if (shape.size() == 0 || otherShape.size() == 0) {
899 // no internal lanes built
900 return false;
901 }
902 const double minDV = NBEdge::firstIntersection(shape, otherShape, width1, width2);
903 if (minDV < shape.length() - POSITION_EPS && minDV > POSITION_EPS) {
904 // break symmetry using edge id
905 return foes || from->getID() < prohibitorFrom->getID();
906 }
907 return false;
908}
909
910bool
912 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
913 if (from == prohibitorFrom) {
914 if (con.toEdge == prohibitorCon.toEdge) {
915 return false;
916 } else if (con.indirectLeft) {
917 LinkDirection dir = myJunction->getDirection(prohibitorFrom, prohibitorCon.toEdge);
918 return (dir == LinkDirection::STRAIGHT);
919 } else if (foes && prohibitorCon.indirectLeft) {
921 return (dir == LinkDirection::STRAIGHT);
922 }
923 }
924 return false;
925}
926
927bool
929 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
930 if (from == prohibitorFrom) {
931 return false;
932 }
933 if (isRailway(from->getPermissions())) {
934 // railways manage right-of-way via signals
935 return false;
936 }
937 if ((foes && (from->getBidiEdge() == prohibitorCon.toEdge))
938 || prohibitorFrom->getBidiEdge() == con.toEdge) {
939 const bool fromBidi = from->getLaneShape(con.fromLane).reverse().almostSame(
940 prohibitorCon.toEdge->getLaneShape(prohibitorCon.toLane), POSITION_EPS);
941 const bool prohibitorFromBidi = prohibitorFrom->getLaneShape(prohibitorCon.fromLane).reverse().almostSame(
942 con.toEdge->getLaneShape(con.toLane), POSITION_EPS);
943 if (!foes && fromBidi && prohibitorFromBidi) {
944 // do not create a symmetrical conflict
945 return false;
946 }
947 if (prohibitorFromBidi &&
948 prohibitorFrom->getLaneShape(prohibitorCon.fromLane).reverse().almostSame(
949 prohibitorCon.toEdge->getLaneShape(prohibitorCon.toLane), POSITION_EPS)) {
950 // prohibitor has a bidi-turnaround
951 return false;
952 }
953
954 return fromBidi || prohibitorFromBidi;
955 }
956 return false;
957}
958
959bool
961 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon) const {
962 if (con.toEdge != prohibitorCon.toEdge) {
963 return false;
964 }
966 SVCPermissions svc2 = prohibitorFrom->getPermissions(prohibitorCon.fromLane) & prohibitorCon.toEdge->getPermissions(prohibitorCon.toLane);
967 // check for lane level conflict if the only common classes are bicycles or pedestrians
968 return ((svc & svc2 & ~(SVC_BICYCLE | SVC_PEDESTRIAN)) == 0
969 // or if the connection is to a dedicated lane whereas the prohibitor is a "general" lane
970 || (((svc & SVC_PASSENGER) == 0) && ((svc2 & SVC_PASSENGER) != 0)));
971}
972
973
974bool
976 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon) const {
977 if (con.toEdge != prohibitorCon.toEdge) {
978 return false;
979 }
980 // if from and prohibitorFrom target distinct lanes for all their
981 // connections to the common target edge, cooperation is possible
982 // (and should always happen unless the connections cross for some byzantine reason)
983
984 std::set<int> fromTargetLanes;
985 for (const NBEdge::Connection& c : from->getConnections()) {
986 if (c.toEdge == con.toEdge) {
987 fromTargetLanes.insert(c.toLane);
988 }
989 }
990 for (const NBEdge::Connection& c : prohibitorFrom->getConnections()) {
991 if (c.toEdge == con.toEdge && fromTargetLanes.count(c.toLane) != 0) {
992 //std::cout << " con=" << con->getDescription(from) << " foe=" << prohibitorCon.getDescription(prohibitorFrom)
993 // << " no cooperation (targets=" << joinToString(fromTargetLanes, ' ') << " index=" << c.toLane << "\n";
994 return false;
995 }
996 }
997 return true;
998}
999
1000
1001bool
1002NBRequest::laneConflict(const NBEdge* from, const NBEdge* to, int toLane,
1003 const NBEdge* prohibitorFrom, const NBEdge* prohibitorTo, int prohibitorToLane) const {
1004 if (to != prohibitorTo) {
1005 return true;
1006 }
1007 // since we know that the edge2edge connections are in conflict, the only
1008 // situation in which the lane2lane connections can be conflict-free is, if
1009 // they target the same edge but do not cross each other
1010 double angle = NBHelpers::relAngle(
1011 from->getAngleAtNode(from->getToNode()), to->getAngleAtNode(to->getFromNode()));
1012 if (angle == 180) {
1013 angle = -180; // turnarounds are left turns
1014 }
1015 const double prohibitorAngle = NBHelpers::relAngle(
1016 prohibitorFrom->getAngleAtNode(prohibitorFrom->getToNode()), to->getAngleAtNode(to->getFromNode()));
1017 const bool rightOfProhibitor = prohibitorFrom->isTurningDirectionAt(to)
1018 || (angle > prohibitorAngle && !from->isTurningDirectionAt(to));
1019 return rightOfProhibitor ? toLane >= prohibitorToLane : toLane <= prohibitorToLane;
1020}
1021
1022int
1023NBRequest::getIndex(const NBEdge* const from, const NBEdge* const to) const {
1024 EdgeVector::const_iterator fp = std::find(myIncoming.begin(), myIncoming.end(), from);
1025 EdgeVector::const_iterator tp = std::find(myOutgoing.begin(), myOutgoing.end(), to);
1026 if (fp == myIncoming.end() || tp == myOutgoing.end()) {
1027 return -1;
1028 }
1029 // compute the index
1030 return (int)(distance(myIncoming.begin(), fp) * myOutgoing.size() + distance(myOutgoing.begin(), tp));
1031}
1032
1033
1034std::ostream&
1035operator<<(std::ostream& os, const NBRequest& r) {
1036 int variations = r.numLinks();
1037 for (int i = 0; i < variations; i++) {
1038 os << i << ' ';
1039 for (int j = 0; j < variations; j++) {
1040 if (r.myForbids[i][j]) {
1041 os << '1';
1042 } else {
1043 os << '0';
1044 }
1045 }
1046 os << std::endl;
1047 }
1048 os << std::endl;
1049 return os;
1050}
1051
1052
1053bool
1054NBRequest::mustBrake(const NBEdge* const from, const NBEdge* const to, int fromLane, int toLane, bool includePedCrossings) const {
1055 NBEdge::Connection con(fromLane, const_cast<NBEdge*>(to), toLane);
1056 const int linkIndex = myJunction->getConnectionIndex(from, con);
1057 if (linkIndex >= 0 && (int)myResponse.size() > linkIndex) {
1058 std::string response = getResponse(linkIndex);
1059 if (!includePedCrossings) {
1060 response = response.substr(0, response.size() - myJunction->getCrossings().size());
1061 }
1062 if (response.find_first_of("1") == std::string::npos) {
1063 return false;
1064 } else if (!myJunction->isTLControlled()) {
1065 return true;
1066 }
1067 // if the link must respond it could also be due to a tlsConflict. This
1068 // must not carry over the off-state response so we continue with
1069 // the regular check
1070 }
1071 // get the indices
1072 int idx2 = getIndex(from, to);
1073 if (idx2 == -1) {
1074 return false;
1075 }
1076 // go through all (existing) connections;
1077 // check whether any of these forbids the one to determine
1078 assert(idx2 < (int)(myIncoming.size()*myOutgoing.size()));
1079 for (int idx1 = 0; idx1 < numLinks(); idx1++) {
1080 //assert(myDone[idx1][idx2]);
1081 if (myDone[idx1][idx2] && myForbids[idx1][idx2]) {
1082 return true;
1083 }
1084 }
1085 // maybe we need to brake for a pedestrian crossing
1086 if (includePedCrossings) {
1087 auto crossings = myJunction->getCrossings();
1088 for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = crossings.rbegin(); i != crossings.rend(); i++) {
1089 if (mustBrakeForCrossing(myJunction, from, to, **i)) {
1090 return true;
1091 }
1092 }
1093 }
1094 // maybe we need to brake due to a right-turn conflict with straight-going
1095 // bicycles
1096 const NBEdge::Connection& queryCon = from->getConnection(fromLane, to, toLane);
1097 LinkDirection dir = myJunction->getDirection(from, to);
1098 if (dir == LinkDirection::RIGHT || dir == LinkDirection::PARTRIGHT) {
1099 for (const NBEdge::Connection& fromCon : from->getConnections()) {
1100 if (rightTurnConflict(from, queryCon, from, fromCon)) {
1101 return true;
1102 }
1103 }
1104 }
1105 // maybe we need to brake due to a merge conflict
1106 for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
1107 int noLanes = (*i)->getNumLanes();
1108 for (int j = noLanes; j-- > 0;) {
1109 std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
1110 const int size = (int) connected.size();
1111 for (int k = size; k-- > 0;) {
1112 if ((*i) == from && fromLane != j
1113 && mergeConflict(from, queryCon, *i, connected[k], myJunction->getType() == SumoXMLNodeType::ZIPPER)) {
1114 return true;
1115 }
1116 }
1117 }
1118 }
1119 // maybe we need to brake due to a zipper conflict
1121 for (int idx1 = 0; idx1 < numLinks(); idx1++) {
1122 //assert(myDone[idx1][idx2]);
1123 if (myDone[idx1][idx2] && myForbids[idx2][idx1]) {
1124 return true;
1125 }
1126 }
1127 }
1128 return false;
1129}
1130
1131
1132bool
1133NBRequest::mustBrakeForCrossing(const NBNode* node, const NBEdge* const from, const NBEdge* const to, const NBNode::Crossing& crossing) {
1134 const LinkDirection dir = node->getDirection(from, to);
1135 const bool mustYield = dir == LinkDirection::LEFT || dir == LinkDirection::RIGHT;
1136 if (crossing.priority || mustYield) {
1137 for (const NBEdge* const e : crossing.edges) {
1138 // left and right turns must yield to unprioritized crossings only on their destination edge
1139 if ((e == from && crossing.priority) || e == to) {
1140 return true;
1141 }
1142 }
1143 }
1144 return false;
1145}
1146
1147
1148bool
1149NBRequest::mustBrake(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
1150 const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo) const {
1151 // get the indices
1152 int idx1 = getIndex(possProhibitorFrom, possProhibitorTo);
1153 int idx2 = getIndex(possProhibitedFrom, possProhibitedTo);
1154 return (myForbids[idx2][idx1]);
1155}
1156
1157
1158void
1160 // check if any errors occurred on build the link prohibitions
1161 if (myNotBuild != 0) {
1162 WRITE_WARNING(toString(myNotBuild) + " of " + toString(myNotBuild + myGoodBuilds) + " prohibitions were not build.");
1163 }
1164}
1165
1166
1167void
1169 // map from edge to number of incoming connections
1170 std::map<const NBEdge*, int> incomingCount; // initialized to 0
1171 // map from edge to indices of approached lanes
1172 std::map<const NBEdge*, std::set<int> > approachedLanes;
1173 // map from edge to list of incoming edges
1174 std::map<const NBEdge*, std::vector<const NBEdge*> > incomingEdges;
1175 for (const NBEdge* const e : myIncoming) {
1176 for (const NBEdge::Connection& con : e->getConnections()) {
1177 incomingCount[con.toEdge]++;
1178 approachedLanes[con.toEdge].insert(con.toLane);
1179 incomingEdges[con.toEdge].push_back(e);
1180 }
1181 }
1182 for (std::map<const NBEdge*, int>::iterator it = incomingCount.begin(); it != incomingCount.end(); ++it) {
1183 const NBEdge* const to = it->first;
1184 // we cannot test against to->getNumLanes() since not all lanes may be used
1185 if ((int)approachedLanes[to].size() >= it->second) {
1186 const std::vector<const NBEdge*>& incoming = incomingEdges[to];
1187 // make these connections mutually unconflicting
1188 for (const NBEdge* const e1 : incoming) {
1189 for (const NBEdge* const e2 : incoming) {
1190 myForbids[getIndex(e1, to)][getIndex(e2, to)] = false;
1191#ifdef DEBUG_SETBLOCKING
1192 if (DEBUGCOND) std::cout << "resetCooperating"
1193 << " 1:" << e1->getID() << "->" << to->getID()
1194 << " 2:" << e2->getID() << "->" << to->getID()
1195 << "\n";
1196#endif
1197 }
1198 }
1199 }
1200 }
1201}
1202
1203
1204bool
1206 for (int i = 0; i < (int)myFoes.size(); i++) {
1207 if (hasConflictAtLink(i)) {
1208 return true;
1209 }
1210 }
1211 return false;
1212}
1213
1214bool
1215NBRequest::hasConflictAtLink(int linkIndex) const {
1216 return myFoes[linkIndex].find_first_of("1") != std::string::npos;
1217}
1218
1219int
1221 return (int)(myIncoming.size() * myOutgoing.size() + myJunction->getCrossings().size());
1222}
1223
1224
1225/****************************************************************************/
#define DEBUGCOND(PED)
#define WRITE_WARNING(msg)
Definition MsgHandler.h:287
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
std::ostream & operator<<(std::ostream &os, const NBRequest &r)
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permissions is a (exclusive) railway edge.
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_PEDESTRIAN
pedestrian
@ 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:4488
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition NBEdge.h:1041
double getLaneWidth() const
Returns the default width of lanes of this edge.
Definition NBEdge.h:642
NBNode * getToNode() const
Returns the destination node of the edge.
Definition NBEdge.h:546
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:1301
const std::string & getID() const
Definition NBEdge.h:1531
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition NBEdge.cpp:3774
bool hasSignalisedConnectionTo(const NBEdge *const e) const
Check if edge has signalised connections.
Definition NBEdge.cpp:4106
int getNumLanes() const
Returns the number of lanes.
Definition NBEdge.h:520
std::vector< Connection > getConnectionsFromLane(int lane, const NBEdge *to=nullptr, int toLane=-1) const
Returns connections from a given lane.
Definition NBEdge.cpp:1287
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:2051
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:1331
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
Definition NBEdge.cpp:2134
const NBEdge * getBidiEdge() const
Definition NBEdge.h:1517
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition NBEdge.h:539
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition NBEdge.cpp:4117
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
Definition NBEdge.cpp:2160
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
Definition NBEdge.cpp:986
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:158
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:2472
int getConnectionIndex(const NBEdge *from, const NBEdge::Connection &con) const
return the index of the given connection
Definition NBNode.cpp:4182
SumoXMLNodeType getType() const
Returns the type of this node.
Definition NBNode.h:285
bool extraConflict(int index, int foeIndex) const
whether the given index must yield to the foeIndex while turing right on a red light
Definition NBNode.cpp:4258
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:2157
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
Definition NBNode.cpp:3072
bool isBentPriority() const
return whether a priority road turns at this node
Definition NBNode.h:839
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:2237
bool isConstantWidthTransition() const
detects whether a given junction splits or merges lanes while keeping constant road width
Definition NBNode.cpp:895
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:1005
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition NBNode.h:331
std::vector< std::string > myResponse
Definition NBRequest.h:281
const EdgeVector & myOutgoing
edges outgoing from the junction
Definition NBRequest.h:265
CombinationsCont myForbids
the link X link blockings
Definition NBRequest.h:274
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
CombinationsCont myDone
the link X link is done-checks
Definition NBRequest.h:277
const EdgeVector & myAll
all (icoming and outgoing) of the junctions edges
Definition NBRequest.h:259
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
std::vector< std::string > myFoes
precomputed right-of-way matrices for each lane-to-lane link
Definition NBRequest.h:280
int distanceCounterClockwise(NBEdge *from, NBEdge *to)
returns the distance between the incoming (from) and the outgoing (to) edge clockwise in edges
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
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.
bool hasConflictAtLink(int linkIndex) const
whether there are conflicting streams of traffic for the given link index
const EdgeVector & myIncoming
edges incoming to the junction
Definition NBRequest.h:262
NBNode * myJunction
the node the request is assigned to
Definition NBRequest.h:256
int numLinks() const
return to total number of edge-to-edge connections of this request-logic
const std::string & getFoes(int linkIndex) const
bool hasConflict() const
whether there are conflicting streams of traffic at this node
void buildBitfieldLogic()
builds the bitset-representation of the logic
bool oppositeLeftTurnConflict(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon, bool foes) const
whether opposite left turns intersect
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...
void resetSignalised()
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
int getIndex(const NBEdge *const from, const NBEdge *const to) const
Returns the index to the internal combination container for the given edge combination.
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.
void computeRightOutgoingLinkCrossings(NBEdge *from, NBEdge *to)
computes the relationships between links outgoing right of the given link *‍/
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
void writeLogic(OutputDevice &into) const
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
std::string getResponseString(const NBEdge *const from, const NBEdge::Connection &c, const bool checkLaneFoes) const
Writes the response of a certain link.
std::pair< int, int > getSizes() const
returns the number of the junction's lanes and the number of the junction's links in respect.
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.
const std::string & getResponse(int linkIndex) const
int computeCrossingResponse(const NBNode::Crossing &crossing, int pos)
computes the response of a certain crossing Returns the next link index within the junction
void setBlocking(NBEdge *from1, NBEdge *to1, NBEdge *from2, NBEdge *to2)
void computeLeftOutgoingLinkCrossings(NBEdge *from, NBEdge *to)
computes the relationships between links outgoing left of the given link
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
void resetCooperating()
reset foes it the number of lanes matches (or exceeds) the number of incoming connections for an edge
~NBRequest()
destructor
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.
static int myNotBuild
Definition NBRequest.h:285
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
static void reportWarnings()
reports warnings if any occurred
static int myGoodBuilds
Definition NBRequest.h:285
std::vector< bool > LinkInfoCont
definition of a container to store boolean informations about a link into
Definition NBRequest.h:268
std::string getFoesString(NBEdge *from, const NBEdge::Connection &c, const bool checkLaneFoes) const
std::vector< bool > myHaveVia
Definition NBRequest.h:282
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.
Static storage of an output device and its base (abstract) implementation.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
OutputDevice & writePadding(const std::string &val)
writes padding (ignored for binary output)
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:104
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