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->tlsStrandedConflict(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->tlsStrandedConflict(from, c, *i, connected[k])
752 && laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane)
753 && !OptionsCont::getOptions().getBool("tls.ignore-internal-junction-jam"))
754 ) {
755 result += '1';
756 } else {
757 result += '0';
758 }
759 }
760 }
761 }
762 }
763 return result;
764}
765
766
767std::string
768NBRequest::getFoesString(NBEdge* from, const NBEdge::Connection& c, const bool checkLaneFoes) const {
769 const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
770 // remember the case when the lane is a "dead end" in the meaning that
771 // vehicles must choose another lane to move over the following
772 // junction
773 // !!! move to forbidden
774 std::string result;
775 // crossings
776 auto crossings = myJunction->getCrossings();
777 for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = crossings.rbegin(); i != crossings.rend(); i++) {
778 bool foes = false;
779 for (EdgeVector::const_iterator it_e = (**i).edges.begin(); it_e != (**i).edges.end(); ++it_e) {
780 if ((*it_e) == from || (*it_e) == c.toEdge) {
781 foes = true;
782 break;
783 }
784 }
785 result += foes ? '1' : '0';
786 }
787 // normal connections
788 for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
789 for (int j = (*i)->getNumLanes() - 1; j >= 0; --j) {
790 const std::vector<NBEdge::Connection>& connected = (*i)->getConnectionsFromLane(j);
791 int size = (int) connected.size();
792 for (int k = size; k-- > 0;) {
793 const bool hasLaneConflict = (!(checkLaneFoes || checkLaneFoesByClass(c, *i, connected[k])
794 || checkLaneFoesByCooperation(from, c, *i, connected[k]))
795 || laneConflict(from, c.toEdge, c.toLane, *i, connected[k].toEdge, connected[k].toLane));
796 if ((foes(from, c.toEdge, (*i), connected[k].toEdge) && hasLaneConflict)
797 || rightTurnConflict(from, c, *i, connected[k])
798 || myJunction->turnFoes(from, c.toEdge, c.fromLane, *i, connected[k].toEdge, connected[k].fromLane, lefthand)
799 || mergeConflict(from, c, *i, connected[k], true)
800 || oppositeLeftTurnConflict(from, c, *i, connected[k], true)
801 || indirectLeftTurnConflict(from, c, *i, connected[k], true)
802 || bidiConflict(from, c, *i, connected[k], true)
803 ) {
804 result += '1';
805 } else {
806 result += '0';
807 }
808 }
809 }
810 }
811 return result;
812}
813
814
815bool
817 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon) const {
818 return (!con.mayDefinitelyPass &&
819 (NBNode::rightTurnConflict(from, con.toEdge, con.fromLane, prohibitorFrom, prohibitorCon.toEdge, prohibitorCon.fromLane)
820 // reverse conflicht (override)
821 || (prohibitorCon.mayDefinitelyPass &&
822 NBNode::rightTurnConflict(prohibitorFrom, prohibitorCon.toEdge, prohibitorCon.fromLane, from, con.toEdge, con.fromLane))));
823
824
825}
826
827
828bool
830 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
831 if (from == prohibitorFrom
832 && con.toEdge == prohibitorCon.toEdge
833 && ((con.toLane == prohibitorCon.toLane
834 && con.fromLane != prohibitorCon.fromLane
836 // this is actually a crossing rather than a merger
837 || (con.fromLane > prohibitorCon.fromLane && con.toLane < prohibitorCon.toLane)
838 || (con.fromLane < prohibitorCon.fromLane && con.toLane > prohibitorCon.toLane))) {
839 if (foes) {
840 return true;
841 }
842 if (prohibitorCon.mayDefinitelyPass) {
843 return true;
844 }
845 if (con.mayDefinitelyPass) {
846 return false;
847 }
848 const bool bike = from->getPermissions(con.fromLane) == SVC_BICYCLE;
849 const bool prohibitorBike = prohibitorFrom->getPermissions(prohibitorCon.fromLane) == SVC_BICYCLE;
850 if (myOutgoing.size() == 1) {
851 // at on-ramp like situations, right lane should yield
852 return bike || (con.fromLane < prohibitorCon.fromLane && !prohibitorBike);
853 } else {
854 // priority depends on direction:
855 // for right turns the rightmost lane gets priority
856 // otherwise the left lane
858 if (dir == LinkDirection::RIGHT || dir == LinkDirection::PARTRIGHT) {
859 return con.fromLane > prohibitorCon.fromLane;
860 } else {
861 if (myIncoming.size() == 1) {
862 // at off-ramp like situations, right lane should pass unless it's a bicycle lane
863 return bike || (con.fromLane > prohibitorCon.fromLane && !prohibitorBike);
864 } else {
865 return con.fromLane < prohibitorCon.fromLane;
866 }
867 }
868 }
869
870 } else {
871 return false;
872 }
873}
874
875
876bool
878 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
880 // XXX lefthand issue (solve via #4256)
881 if (dir != LinkDirection::LEFT && dir != LinkDirection::PARTLEFT) {
882 return false;
883 }
884 dir = myJunction->getDirection(prohibitorFrom, prohibitorCon.toEdge);
885 if (dir != LinkDirection::LEFT && dir != LinkDirection::PARTLEFT) {
886 return false;
887 }
888 if (from == prohibitorFrom || NBRequest::foes(from, con.toEdge, prohibitorFrom, prohibitorCon.toEdge)) {
889 // not an opposite pair
890 return false;
891 }
892
893 const double width1 = MIN2(from->getLaneWidth(con.fromLane) / 2, OptionsCont::getOptions().getFloat("internal-junctions.vehicle-width") / 2);
894 const double width2 = prohibitorCon.toEdge->getLaneWidth(prohibitorCon.toLane) / 2;
895 PositionVector shape = con.shape;
896 shape.append(con.viaShape);
897 PositionVector otherShape = prohibitorCon.shape;
898 otherShape.append(prohibitorCon.viaShape);
899 if (shape.size() == 0 || otherShape.size() == 0) {
900 // no internal lanes built
901 return false;
902 }
903 const double minDV = NBEdge::firstIntersection(shape, otherShape, width1, width2);
904 if (minDV < shape.length() - POSITION_EPS && minDV > POSITION_EPS) {
905 // break symmetry using edge id
906 return foes || from->getID() < prohibitorFrom->getID();
907 }
908 return false;
909}
910
911bool
913 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
914 if (from == prohibitorFrom) {
915 if (con.toEdge == prohibitorCon.toEdge) {
916 return false;
917 } else if (con.indirectLeft) {
918 LinkDirection dir = myJunction->getDirection(prohibitorFrom, prohibitorCon.toEdge);
919 return (dir == LinkDirection::STRAIGHT);
920 } else if (foes && prohibitorCon.indirectLeft) {
922 return (dir == LinkDirection::STRAIGHT);
923 }
924 }
925 return false;
926}
927
928bool
930 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
931 if (from == prohibitorFrom) {
932 return false;
933 }
934 if (isRailway(from->getPermissions())) {
935 // railways manage right-of-way via signals
936 return false;
937 }
938 if ((foes && (from->getBidiEdge() == prohibitorCon.toEdge))
939 || prohibitorFrom->getBidiEdge() == con.toEdge) {
940 const bool fromBidi = from->getLaneShape(con.fromLane).reverse().almostSame(
941 prohibitorCon.toEdge->getLaneShape(prohibitorCon.toLane), POSITION_EPS);
942 const bool prohibitorFromBidi = prohibitorFrom->getLaneShape(prohibitorCon.fromLane).reverse().almostSame(
943 con.toEdge->getLaneShape(con.toLane), POSITION_EPS);
944 if (!foes && fromBidi && prohibitorFromBidi) {
945 // do not create a symmetrical conflict
946 return false;
947 }
948 if (prohibitorFromBidi &&
949 prohibitorFrom->getLaneShape(prohibitorCon.fromLane).reverse().almostSame(
950 prohibitorCon.toEdge->getLaneShape(prohibitorCon.toLane), POSITION_EPS)) {
951 // prohibitor has a bidi-turnaround
952 return false;
953 }
954
955 return fromBidi || prohibitorFromBidi;
956 }
957 return false;
958}
959
960bool
962 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon) const {
963 if (con.toEdge != prohibitorCon.toEdge) {
964 return false;
965 }
967 SVCPermissions svc2 = prohibitorFrom->getPermissions(prohibitorCon.fromLane) & prohibitorCon.toEdge->getPermissions(prohibitorCon.toLane);
968 // check for lane level conflict if the only common classes are bicycles or pedestrians
969 return ((svc & svc2 & ~(SVC_BICYCLE | SVC_PEDESTRIAN)) == 0
970 // or if the connection is to a dedicated lane whereas the prohibitor is a "general" lane
971 || (((svc & SVC_PASSENGER) == 0) && ((svc2 & SVC_PASSENGER) != 0)));
972}
973
974
975bool
977 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon) const {
978 if (con.toEdge != prohibitorCon.toEdge) {
979 return false;
980 }
981 // if from and prohibitorFrom target distinct lanes for all their
982 // connections to the common target edge, cooperation is possible
983 // (and should always happen unless the connections cross for some byzantine reason)
984
985 std::set<int> fromTargetLanes;
986 for (const NBEdge::Connection& c : from->getConnections()) {
987 if (c.toEdge == con.toEdge) {
988 fromTargetLanes.insert(c.toLane);
989 }
990 }
991 for (const NBEdge::Connection& c : prohibitorFrom->getConnections()) {
992 if (c.toEdge == con.toEdge && fromTargetLanes.count(c.toLane) != 0) {
993 //std::cout << " con=" << con->getDescription(from) << " foe=" << prohibitorCon.getDescription(prohibitorFrom)
994 // << " no cooperation (targets=" << joinToString(fromTargetLanes, ' ') << " index=" << c.toLane << "\n";
995 return false;
996 }
997 }
998 return true;
999}
1000
1001
1002bool
1003NBRequest::laneConflict(const NBEdge* from, const NBEdge* to, int toLane,
1004 const NBEdge* prohibitorFrom, const NBEdge* prohibitorTo, int prohibitorToLane) const {
1005 if (to != prohibitorTo) {
1006 return true;
1007 }
1008 // since we know that the edge2edge connections are in conflict, the only
1009 // situation in which the lane2lane connections can be conflict-free is, if
1010 // they target the same edge but do not cross each other
1011 double angle = NBHelpers::relAngle(
1012 from->getAngleAtNode(from->getToNode()), to->getAngleAtNode(to->getFromNode()));
1013 if (angle == 180) {
1014 angle = -180; // turnarounds are left turns
1015 }
1016 const double prohibitorAngle = NBHelpers::relAngle(
1017 prohibitorFrom->getAngleAtNode(prohibitorFrom->getToNode()), to->getAngleAtNode(to->getFromNode()));
1018 const bool rightOfProhibitor = prohibitorFrom->isTurningDirectionAt(to)
1019 || (angle > prohibitorAngle && !from->isTurningDirectionAt(to));
1020 return rightOfProhibitor ? toLane >= prohibitorToLane : toLane <= prohibitorToLane;
1021}
1022
1023int
1024NBRequest::getIndex(const NBEdge* const from, const NBEdge* const to) const {
1025 EdgeVector::const_iterator fp = std::find(myIncoming.begin(), myIncoming.end(), from);
1026 EdgeVector::const_iterator tp = std::find(myOutgoing.begin(), myOutgoing.end(), to);
1027 if (fp == myIncoming.end() || tp == myOutgoing.end()) {
1028 return -1;
1029 }
1030 // compute the index
1031 return (int)(distance(myIncoming.begin(), fp) * myOutgoing.size() + distance(myOutgoing.begin(), tp));
1032}
1033
1034
1035std::ostream&
1036operator<<(std::ostream& os, const NBRequest& r) {
1037 int variations = r.numLinks();
1038 for (int i = 0; i < variations; i++) {
1039 os << i << ' ';
1040 for (int j = 0; j < variations; j++) {
1041 if (r.myForbids[i][j]) {
1042 os << '1';
1043 } else {
1044 os << '0';
1045 }
1046 }
1047 os << std::endl;
1048 }
1049 os << std::endl;
1050 return os;
1051}
1052
1053
1054bool
1055NBRequest::mustBrake(const NBEdge* const from, const NBEdge* const to, int fromLane, int toLane, bool includePedCrossings) const {
1056 NBEdge::Connection con(fromLane, const_cast<NBEdge*>(to), toLane);
1057 const int linkIndex = myJunction->getConnectionIndex(from, con);
1058 if (linkIndex >= 0 && (int)myResponse.size() > linkIndex) {
1059 std::string response = getResponse(linkIndex);
1060 if (!includePedCrossings) {
1061 response = response.substr(0, response.size() - myJunction->getCrossings().size());
1062 }
1063 if (response.find_first_of("1") == std::string::npos) {
1064 return false;
1065 } else if (!myJunction->isTLControlled()) {
1066 return true;
1067 }
1068 // if the link must respond it could also be due to a tlsConflict. This
1069 // must not carry over the off-state response so we continue with
1070 // the regular check
1071 }
1072 // get the indices
1073 int idx2 = getIndex(from, to);
1074 if (idx2 == -1) {
1075 return false;
1076 }
1077 // go through all (existing) connections;
1078 // check whether any of these forbids the one to determine
1079 assert(idx2 < (int)(myIncoming.size()*myOutgoing.size()));
1080 for (int idx1 = 0; idx1 < numLinks(); idx1++) {
1081 //assert(myDone[idx1][idx2]);
1082 if (myDone[idx1][idx2] && myForbids[idx1][idx2]) {
1083 return true;
1084 }
1085 }
1086 // maybe we need to brake for a pedestrian crossing
1087 if (includePedCrossings) {
1088 auto crossings = myJunction->getCrossings();
1089 for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = crossings.rbegin(); i != crossings.rend(); i++) {
1090 if (mustBrakeForCrossing(myJunction, from, to, **i)) {
1091 return true;
1092 }
1093 }
1094 }
1095 // maybe we need to brake due to a right-turn conflict with straight-going
1096 // bicycles
1097 const NBEdge::Connection& queryCon = from->getConnection(fromLane, to, toLane);
1098 LinkDirection dir = myJunction->getDirection(from, to);
1099 if (dir == LinkDirection::RIGHT || dir == LinkDirection::PARTRIGHT) {
1100 for (const NBEdge::Connection& fromCon : from->getConnections()) {
1101 if (rightTurnConflict(from, queryCon, from, fromCon)) {
1102 return true;
1103 }
1104 }
1105 }
1106 // maybe we need to brake due to a merge conflict
1107 for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
1108 int noLanes = (*i)->getNumLanes();
1109 for (int j = noLanes; j-- > 0;) {
1110 std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
1111 const int size = (int) connected.size();
1112 for (int k = size; k-- > 0;) {
1113 if ((*i) == from && fromLane != j
1114 && mergeConflict(from, queryCon, *i, connected[k], myJunction->getType() == SumoXMLNodeType::ZIPPER)) {
1115 return true;
1116 }
1117 }
1118 }
1119 }
1120 // maybe we need to brake due to a zipper conflict
1122 for (int idx1 = 0; idx1 < numLinks(); idx1++) {
1123 //assert(myDone[idx1][idx2]);
1124 if (myDone[idx1][idx2] && myForbids[idx2][idx1]) {
1125 return true;
1126 }
1127 }
1128 }
1129 return false;
1130}
1131
1132
1133bool
1134NBRequest::mustBrakeForCrossing(const NBNode* node, const NBEdge* const from, const NBEdge* const to, const NBNode::Crossing& crossing) {
1135 const LinkDirection dir = node->getDirection(from, to);
1136 const bool mustYield = dir == LinkDirection::LEFT || dir == LinkDirection::RIGHT;
1137 if (crossing.priority || mustYield) {
1138 for (const NBEdge* const e : crossing.edges) {
1139 // left and right turns must yield to unprioritized crossings only on their destination edge
1140 if ((e == from && crossing.priority) || e == to) {
1141 return true;
1142 }
1143 }
1144 }
1145 return false;
1146}
1147
1148
1149bool
1150NBRequest::mustBrake(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
1151 const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo) const {
1152 // get the indices
1153 int idx1 = getIndex(possProhibitorFrom, possProhibitorTo);
1154 int idx2 = getIndex(possProhibitedFrom, possProhibitedTo);
1155 return (myForbids[idx2][idx1]);
1156}
1157
1158
1159void
1161 // check if any errors occurred on build the link prohibitions
1162 if (myNotBuild != 0) {
1163 WRITE_WARNING(toString(myNotBuild) + " of " + toString(myNotBuild + myGoodBuilds) + " prohibitions were not build.");
1164 }
1165}
1166
1167
1168void
1170 // map from edge to number of incoming connections
1171 std::map<const NBEdge*, int> incomingCount; // initialized to 0
1172 // map from edge to indices of approached lanes
1173 std::map<const NBEdge*, std::set<int> > approachedLanes;
1174 // map from edge to list of incoming edges
1175 std::map<const NBEdge*, std::vector<const NBEdge*> > incomingEdges;
1176 for (const NBEdge* const e : myIncoming) {
1177 for (const NBEdge::Connection& con : e->getConnections()) {
1178 incomingCount[con.toEdge]++;
1179 approachedLanes[con.toEdge].insert(con.toLane);
1180 incomingEdges[con.toEdge].push_back(e);
1181 }
1182 }
1183 for (std::map<const NBEdge*, int>::iterator it = incomingCount.begin(); it != incomingCount.end(); ++it) {
1184 const NBEdge* const to = it->first;
1185 // we cannot test against to->getNumLanes() since not all lanes may be used
1186 if ((int)approachedLanes[to].size() >= it->second) {
1187 const std::vector<const NBEdge*>& incoming = incomingEdges[to];
1188 // make these connections mutually unconflicting
1189 for (const NBEdge* const e1 : incoming) {
1190 for (const NBEdge* const e2 : incoming) {
1191 myForbids[getIndex(e1, to)][getIndex(e2, to)] = false;
1192#ifdef DEBUG_SETBLOCKING
1193 if (DEBUGCOND) std::cout << "resetCooperating"
1194 << " 1:" << e1->getID() << "->" << to->getID()
1195 << " 2:" << e2->getID() << "->" << to->getID()
1196 << "\n";
1197#endif
1198 }
1199 }
1200 }
1201 }
1202}
1203
1204
1205bool
1207 for (int i = 0; i < (int)myFoes.size(); i++) {
1208 if (hasConflictAtLink(i)) {
1209 return true;
1210 }
1211 }
1212 return false;
1213}
1214
1215bool
1216NBRequest::hasConflictAtLink(int linkIndex) const {
1217 return myFoes[linkIndex].find_first_of("1") != std::string::npos;
1218}
1219
1220int
1222 return (int)(myIncoming.size() * myOutgoing.size() + myJunction->getCrossings().size());
1223}
1224
1225
1226/****************************************************************************/
#define DEBUGCOND(PED)
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
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:80
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:4540
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition NBEdge.h:1047
double getLaneWidth() const
Returns the default width of lanes of this edge.
Definition NBEdge.h:648
NBNode * getToNode() const
Returns the destination node of the edge.
Definition NBEdge.h:552
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:1324
const std::string & getID() const
Definition NBEdge.h:1551
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition NBEdge.cpp:3807
bool hasSignalisedConnectionTo(const NBEdge *const e) const
Check if edge has signalised connections.
Definition NBEdge.cpp:4158
int getNumLanes() const
Returns the number of lanes.
Definition NBEdge.h:526
std::vector< Connection > getConnectionsFromLane(int lane, const NBEdge *to=nullptr, int toLane=-1) const
Returns connections from a given lane.
Definition NBEdge.cpp:1310
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:2074
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:1354
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
Definition NBEdge.cpp:2157
const NBEdge * getBidiEdge() const
Definition NBEdge.h:1537
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition NBEdge.h:545
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition NBEdge.cpp:4169
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
Definition NBEdge.cpp:2183
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
Definition NBEdge.cpp:1009
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:2496
int getConnectionIndex(const NBEdge *from, const NBEdge::Connection &con) const
return the index of the given connection
Definition NBNode.cpp:4206
SumoXMLNodeType getType() const
Returns the type of this node.
Definition NBNode.h:285
bool tlsStrandedConflict(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:1029
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:4286
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:2181
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
Definition NBNode.cpp:3096
bool isBentPriority() const
return whether a priority road turns at this node
Definition NBNode.h:842
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:2261
bool isConstantWidthTransition() const
detects whether a given junction splits or merges lanes while keeping constant road width
Definition NBNode.cpp:919
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