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