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