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#ifdef DEBUG_SETBLOCKING
340 if (DEBUGCOND) std::cout << "setBlocking"
341 << " 1:" << from1->getID() << "->" << to1->getID()
342 << " 2:" << from2->getID() << "->" << to2->getID()
343 << " 1 yields\n";
344#endif
345 return;
346 }
348 }
349 // get the position of the incoming lanes in the junction-wheel
350 EdgeVector::const_iterator c2 = std::find(myAll.begin(), myAll.end(), from2);
352 // go through next edges clockwise...
353 while (*c2 != from2 && *c2 != from1) {
354 if (*c2 == to1) {
355 // if we encounter to1 the second one prohibits the first
357 myForbids[idx2][idx1] = true;
358 } else {
359 myForbids[idx1][idx2] = true;
360 }
361#ifdef DEBUG_SETBLOCKING
362 if (DEBUGCOND) std::cout << "setBlocking"
363 << " 1:" << from1->getID() << "->" << to1->getID()
364 << " 2:" << from2->getID() << "->" << to2->getID()
365 << " 2 yields\n";
366#endif
367 return;
368 }
370 }
371#ifdef DEBUG_SETBLOCKING
372 if (DEBUGCOND) std::cout << "setBlocking"
373 << " 1:" << from1->getID() << "->" << to1->getID()
374 << " 2:" << from2->getID() << "->" << to2->getID()
375 << " noDecision\n";
376#endif
377}
378
379
380int
382 EdgeVector::const_iterator p = std::find(myAll.begin(), myAll.end(), from);
383 int ret = 0;
384 do {
385 ret++;
386 if (p == myAll.begin()) {
387 p = myAll.end();
388 }
389 p--;
390 } while (*p != to);
391 return ret;
392}
393
394const std::string&
395NBRequest::getFoes(int linkIndex) const {
396 assert(linkIndex >= 0);
397 assert(linkIndex < (int)myFoes.size());
398 return myFoes[linkIndex];
399}
400
401
402const std::string&
403NBRequest::getResponse(int linkIndex) const {
404 assert(linkIndex >= 0);
405 assert(linkIndex < (int)myResponse.size());
406 return myResponse[linkIndex];
407}
408
409
410void
412 int numLinks = (int)myResponse.size();
413 assert((int)myFoes.size() == numLinks);
414 assert((int)myHaveVia.size() == numLinks);
415 const bool padding = numLinks > 10;
416 for (int i = 0; i < numLinks; i++) {
418 into.writeAttr(SUMO_ATTR_INDEX, i);
419 if (padding && i < 10) {
420 into.writePadding(" ");
421 }
424 if (!OptionsCont::getOptions().getBool("no-internal-links")) {
426 }
427 into.closeTag();
428 }
429}
430
431
432void
433NBRequest::computeLogic(const bool checkLaneFoes) {
434 myResponse.clear();
435 myFoes.clear();
436 myHaveVia.clear();
437 int pos = 0;
438 EdgeVector::const_iterator i;
439 // normal connections
440 for (i = myIncoming.begin(); i != myIncoming.end(); i++) {
441 int noLanes = (*i)->getNumLanes();
442 for (int k = 0; k < noLanes; k++) {
443 pos = computeLaneResponse(*i, k, pos, checkLaneFoes || myJunction->getType() == SumoXMLNodeType::ZIPPER);
444 }
445 }
446 // crossings
447 auto crossings = myJunction->getCrossings();
448 for (auto c : crossings) {
449 pos = computeCrossingResponse(*c, pos);
450 }
451}
452
453void
455 // go through possible prohibitions
456 for (EdgeVector::const_iterator i11 = myIncoming.begin(); i11 != myIncoming.end(); i11++) {
457 int noLanesEdge1 = (*i11)->getNumLanes();
458 for (int j1 = 0; j1 < noLanesEdge1; j1++) {
459 std::vector<NBEdge::Connection> el1 = (*i11)->getConnectionsFromLane(j1);
460 for (std::vector<NBEdge::Connection>::iterator i12 = el1.begin(); i12 != el1.end(); ++i12) {
461 int idx1 = getIndex((*i11), (*i12).toEdge);
462 if (idx1 < 0) {
463 continue;
464 }
465 // go through possibly prohibited
466 for (EdgeVector::const_iterator i21 = myIncoming.begin(); i21 != myIncoming.end(); i21++) {
467 int noLanesEdge2 = (*i21)->getNumLanes();
468 for (int j2 = 0; j2 < noLanesEdge2; j2++) {
469 std::vector<NBEdge::Connection> el2 = (*i21)->getConnectionsFromLane(j2);
470 for (std::vector<NBEdge::Connection>::iterator i22 = el2.begin(); i22 != el2.end(); i22++) {
471 int idx2 = getIndex((*i21), (*i22).toEdge);
472 if (idx2 < 0) {
473 continue;
474 }
475 // check
476 // same incoming connections do not prohibit each other
477 if ((*i11) == (*i21)) {
478 myForbids[idx1][idx2] = false;
479 myForbids[idx2][idx1] = false;
480#ifdef DEBUG_SETBLOCKING
481 if (DEBUGCOND) std::cout << "resetSignalised both"
482 << " 1:" << (*i11)->getID() << "->" << (*i12).toEdge->getID()
483 << " 2:" << (*i21)->getID() << "->" << (*i22).toEdge->getID()
484 << "\n";
485#endif
486 continue;
487 }
488 // check other
489 // if both are non-signalised or both are signalised
490 if (((*i12).tlID == "" && (*i22).tlID == "")
491 ||
492 ((*i12).tlID != "" && (*i22).tlID != "")) {
493 // do nothing
494 continue;
495 }
496 // supposing, we don not have to
497 // brake if we are no foes
498 if (!foes(*i11, (*i12).toEdge, *i21, (*i22).toEdge)) {
499 continue;
500 }
501 // otherwise:
502 // the non-signalised must break
503 if ((*i12).tlID != "") {
504 myForbids[idx1][idx2] = true;
505 myForbids[idx2][idx1] = false;
506#ifdef DEBUG_SETBLOCKING
507 if (DEBUGCOND) std::cout << "resetSignalised:2 yields"
508 << " 1:" << (*i11)->getID() << "->" << (*i12).toEdge->getID()
509 << " 2:" << (*i21)->getID() << "->" << (*i22).toEdge->getID() << "\n";
510#endif
511 } else {
512 myForbids[idx1][idx2] = false;
513 myForbids[idx2][idx1] = true;
514#ifdef DEBUG_SETBLOCKING
515 if (DEBUGCOND) std::cout << "resetSignalised:1 yields"
516 << " 1:" << (*i11)->getID() << "->" << (*i12).toEdge->getID()
517 << " 2:" << (*i21)->getID() << "->" << (*i22).toEdge->getID() << "\n";
518#endif
519 }
520 }
521 }
522 }
523 }
524 }
525 }
526}
527
528
529std::pair<int, int>
531 int numLanes = 0;
532 int numLinks = 0;
533 for (const NBEdge* const e : myIncoming) {
534 const int numLanesEdge = e->getNumLanes();
535 for (int j = 0; j < numLanesEdge; j++) {
536 int numConnections = (int)e->getConnectionsFromLane(j).size();
537 numLinks += numConnections;
538 if (numConnections > 0) {
539 numLanes++;
540 }
541 }
542 }
543 return std::make_pair(numLanes, numLinks);
544}
545
546
547bool
548NBRequest::foes(const NBEdge* const from1, const NBEdge* const to1,
549 const NBEdge* const from2, const NBEdge* const to2) const {
550 // unconnected edges do not forbid other edges
551 if (to1 == nullptr || to2 == nullptr) {
552 return false;
553 }
554 // get the indices
555 int idx1 = getIndex(from1, to1);
556 int idx2 = getIndex(from2, to2);
557 if (idx1 < 0 || idx2 < 0) {
558 return false; // sure? (The connection does not exist within this junction)
559 }
560 assert(idx1 < (int)(myIncoming.size() * myOutgoing.size()));
561 assert(idx2 < (int)(myIncoming.size()*myOutgoing.size()));
562 return myForbids[idx1][idx2] || myForbids[idx2][idx1];
563}
564
565
566bool
567NBRequest::forbids(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
568 const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo,
569 bool regardNonSignalisedLowerPriority) const {
570 // unconnected edges do not forbid other edges
571 if (possProhibitorTo == nullptr || possProhibitedTo == nullptr) {
572 return false;
573 }
574 // get the indices
575 int possProhibitorIdx = getIndex(possProhibitorFrom, possProhibitorTo);
576 int possProhibitedIdx = getIndex(possProhibitedFrom, possProhibitedTo);
577 if (possProhibitorIdx < 0 || possProhibitedIdx < 0) {
578 return false; // sure? (The connection does not exist within this junction)
579 }
580 assert(possProhibitorIdx < (int)(myIncoming.size() * myOutgoing.size()));
581 assert(possProhibitedIdx < (int)(myIncoming.size() * myOutgoing.size()));
582 // check simple right-of-way-rules
583 if (!regardNonSignalisedLowerPriority) {
584 return myForbids[possProhibitorIdx][possProhibitedIdx];
585 }
586 // if its not forbidden, report
587 if (!myForbids[possProhibitorIdx][possProhibitedIdx]) {
588 return false;
589 }
590 // do not forbid a signalised stream by a non-signalised
591 if (!possProhibitorFrom->hasSignalisedConnectionTo(possProhibitorTo)) {
592 return false;
593 }
594 return true;
595}
596
597int
598NBRequest::computeLaneResponse(NBEdge* from, int fromLane, int pos, const bool checkLaneFoes) {
599 for (const NBEdge::Connection& c : from->getConnectionsFromLane(fromLane)) {
600 assert(c.toEdge != 0);
601 pos++;
602 const std::string foes = getFoesString(from, c.toEdge, fromLane, c.toLane, checkLaneFoes);
603 const std::string response = getResponseString(from, c, checkLaneFoes);
604 myFoes.push_back(foes);
605 myResponse.push_back(response);
606 myHaveVia.push_back(c.haveVia);
607 }
608 return pos;
609}
610
611
612int
614 std::string foes(myJunction->getCrossings().size(), '0');
615 std::string response(myJunction->getCrossings().size(), '0');
616 // conflicts with normal connections
617 for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
618 const NBEdge* from = *i;
619 for (int j = from->getNumLanes(); j-- > 0;) {
620 const std::vector<NBEdge::Connection>& connected = from->getConnectionsFromLane(j);
621 const int size = (int) connected.size();
622 for (int k = size; k-- > 0;) {
623 const NBEdge* to = connected[k].toEdge;
624 bool foe = false;
625 for (const NBEdge* const e : crossing.edges) {
626 if (e == from || e == to) {
627 foe = true;
628 break;
629 }
630 }
631 foes += foe ? '1' : '0';
632 response += mustBrakeForCrossing(myJunction, from, to, crossing) || !foe ? '0' : '1';
633 }
634 }
635 }
636 pos++;
637 myResponse.push_back(response);
638 myFoes.push_back(foes);
639 myHaveVia.push_back(false);
640 return pos;
641}
642
643
644std::string
645NBRequest::getResponseString(const NBEdge* const from, const NBEdge::Connection& c, const bool checkLaneFoes) const {
646 const NBEdge* const to = c.toEdge;
647 const int fromLane = c.fromLane;
648 const int toLane = c.toLane;
649 int idx = 0;
650 if (to != nullptr) {
651 idx = getIndex(from, to);
652 }
653 std::string result;
654 const bool zipper = myJunction->getType() == SumoXMLNodeType::ZIPPER;
655 // crossings
656 auto crossings = myJunction->getCrossings();
657 for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = crossings.rbegin(); i != crossings.rend(); i++) {
658 result += mustBrakeForCrossing(myJunction, from, to, **i) ? '1' : '0';
659 }
660 const NBEdge::Connection& queryCon = from->getConnection(fromLane, to, toLane);
661 // normal connections
662 for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
663 //const std::vector<NBEdge::Connection> &allConnections = (*i)->getConnections();
664 int noLanes = (*i)->getNumLanes();
665 for (int j = noLanes; j-- > 0;) {
666 std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
667 int size = (int) connected.size();
668 for (int k = size; k-- > 0;) {
669 if (c.mayDefinitelyPass) {
670 result += '0';
671#ifdef DEBUG_RESPONSE
672 if (DEBUGCOND) {
673 std::cout << " c=" << queryCon.getDescription(from) << " pass\n";
674 }
675#endif
676 } else if ((*i) == from && fromLane == j) {
677 // do not prohibit a connection by others from same lane
678 // except for indirect turns
679#ifdef DEBUG_RESPONSE
680 if (DEBUGCOND) {
681 std::cout << " c=" << queryCon.getDescription(from) << " prohibitC=" << connected[k].getDescription(*i)
682 << " itc=" << indirectLeftTurnConflict(from, queryCon, *i, connected[k], false)
683 << "\n";
684 }
685#endif
686 if (indirectLeftTurnConflict(from, queryCon, *i, connected[k], false)) {
687 result += '1';
688 } else {
689 result += '0';
690 }
691 } else {
692 assert(connected[k].toEdge != 0);
693 const int idx2 = getIndex(*i, connected[k].toEdge);
694 assert(k < (int) connected.size());
695 assert(idx < (int)(myIncoming.size() * myOutgoing.size()));
696 assert(idx2 < (int)(myIncoming.size() * myOutgoing.size()));
697 // check whether the connection is prohibited by another one
698#ifdef DEBUG_RESPONSE
699 if (DEBUGCOND) {
700 std::cout << " c=" << queryCon.getDescription(from) << " prohibitC=" << connected[k].getDescription(*i)
701 << " idx=" << idx << " idx2=" << idx2
702 << " f=" << myForbids[idx2][idx]
703 << " clf=" << checkLaneFoes
704 << " clfbc=" << checkLaneFoesByClass(queryCon, *i, connected[k])
705 << " clfbcoop=" << checkLaneFoesByCooperation(from, queryCon, *i, connected[k])
706 << " lc=" << laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane)
707 << " rtc=" << NBNode::rightTurnConflict(from, to, fromLane, *i, connected[k].toEdge, connected[k].fromLane)
708 << " rtc2=" << rightTurnConflict(from, queryCon, *i, connected[k])
709 << " mc=" << mergeConflict(from, queryCon, *i, connected[k], false)
710 << " oltc=" << oppositeLeftTurnConflict(from, queryCon, *i, connected[k], false)
711 << " itc=" << indirectLeftTurnConflict(from, queryCon, *i, connected[k], zipper)
712 << " bc=" << bidiConflict(from, queryCon, *i, connected[k], false)
713 << " rorc=" << myJunction->rightOnRedConflict(c.tlLinkIndex, connected[k].tlLinkIndex)
714 << " tlscc=" << myJunction->tlsContConflict(from, c, *i, connected[k])
715 << "\n";
716 }
717#endif
718 const bool hasLaneConflict = (!(checkLaneFoes || checkLaneFoesByClass(queryCon, *i, connected[k])
719 || checkLaneFoesByCooperation(from, queryCon, *i, connected[k]))
720 || laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane));
721 if (((myForbids[idx2][idx] || (zipper && myForbids[idx][idx2])) && hasLaneConflict && !bidiConflict(*i, connected[k], from, queryCon, false))
722 || rightTurnConflict(from, queryCon, *i, connected[k])
723 || mergeConflict(from, queryCon, *i, connected[k], zipper)
724 || oppositeLeftTurnConflict(from, queryCon, *i, connected[k], zipper)
725 || indirectLeftTurnConflict(from, queryCon, *i, connected[k], zipper)
726 || bidiConflict(from, queryCon, *i, connected[k], false)
727 || myJunction->rightOnRedConflict(c.tlLinkIndex, connected[k].tlLinkIndex)
728 || (myJunction->tlsContConflict(from, c, *i, connected[k]) && hasLaneConflict
729 && !OptionsCont::getOptions().getBool("tls.ignore-internal-junction-jam"))
730 ) {
731 result += '1';
732 } else {
733 result += '0';
734 }
735 }
736 }
737 }
738 }
739 return result;
740}
741
742
743std::string
744NBRequest::getFoesString(NBEdge* from, NBEdge* to, int fromLane, int toLane, const bool checkLaneFoes) const {
745 const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
746 // remember the case when the lane is a "dead end" in the meaning that
747 // vehicles must choose another lane to move over the following
748 // junction
749 // !!! move to forbidden
750 std::string result;
751 // crossings
752 auto crossings = myJunction->getCrossings();
753 for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = crossings.rbegin(); i != crossings.rend(); i++) {
754 bool foes = false;
755 for (EdgeVector::const_iterator it_e = (**i).edges.begin(); it_e != (**i).edges.end(); ++it_e) {
756 if ((*it_e) == from || (*it_e) == to) {
757 foes = true;
758 break;
759 }
760 }
761 result += foes ? '1' : '0';
762 }
763 const NBEdge::Connection& queryCon = from->getConnection(fromLane, to, toLane);
764 // normal connections
765 for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
766 for (int j = (*i)->getNumLanes() - 1; j >= 0; --j) {
767 const std::vector<NBEdge::Connection>& connected = (*i)->getConnectionsFromLane(j);
768 int size = (int) connected.size();
769 for (int k = size; k-- > 0;) {
770 const bool hasLaneConflict = (!(checkLaneFoes || checkLaneFoesByClass(queryCon, *i, connected[k])
771 || checkLaneFoesByCooperation(from, queryCon, *i, connected[k]))
772 || laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane));
773 if ((foes(from, to, (*i), connected[k].toEdge) && hasLaneConflict)
774 || rightTurnConflict(from, queryCon, *i, connected[k])
775 || myJunction->turnFoes(from, to, fromLane, *i, connected[k].toEdge, connected[k].fromLane, lefthand)
776 || mergeConflict(from, queryCon, *i, connected[k], true)
777 || oppositeLeftTurnConflict(from, queryCon, *i, connected[k], true)
778 || indirectLeftTurnConflict(from, queryCon, *i, connected[k], true)
779 || bidiConflict(from, queryCon, *i, connected[k], true)
780 ) {
781 result += '1';
782 } else {
783 result += '0';
784 }
785 }
786 }
787 }
788 return result;
789}
790
791
792bool
794 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon) const {
795 return (!con.mayDefinitelyPass &&
796 (NBNode::rightTurnConflict(from, con.toEdge, con.fromLane, prohibitorFrom, prohibitorCon.toEdge, prohibitorCon.fromLane)
797 // reverse conflicht (override)
798 || (prohibitorCon.mayDefinitelyPass &&
799 NBNode::rightTurnConflict(prohibitorFrom, prohibitorCon.toEdge, prohibitorCon.fromLane, from, con.toEdge, con.fromLane))));
800
801
802}
803
804
805bool
807 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
808 if (from == prohibitorFrom
809 && con.toEdge == prohibitorCon.toEdge
810 && ((con.toLane == prohibitorCon.toLane
811 && con.fromLane != prohibitorCon.fromLane
813 // this is actually a crossing rather than a merger
814 || (con.fromLane > prohibitorCon.fromLane && con.toLane < prohibitorCon.toLane)
815 || (con.fromLane < prohibitorCon.fromLane && con.toLane > prohibitorCon.toLane))) {
816 if (foes) {
817 return true;
818 }
819 if (prohibitorCon.mayDefinitelyPass) {
820 return true;
821 }
822 if (con.mayDefinitelyPass) {
823 return false;
824 }
825 const bool bike = from->getPermissions(con.fromLane) == SVC_BICYCLE;
826 const bool prohibitorBike = prohibitorFrom->getPermissions(prohibitorCon.fromLane) == SVC_BICYCLE;
827 if (myOutgoing.size() == 1) {
828 // at on-ramp like situations, right lane should yield
829 return bike || (con.fromLane < prohibitorCon.fromLane && !prohibitorBike);
830 } else {
831 // priority depends on direction:
832 // for right turns the rightmost lane gets priority
833 // otherwise the left lane
835 if (dir == LinkDirection::RIGHT || dir == LinkDirection::PARTRIGHT) {
836 return con.fromLane > prohibitorCon.fromLane;
837 } else {
838 if (myIncoming.size() == 1) {
839 // at off-ramp like situations, right lane should pass unless it's a bicycle lane
840 return bike || (con.fromLane > prohibitorCon.fromLane && !prohibitorBike);
841 } else {
842 return con.fromLane < prohibitorCon.fromLane;
843 }
844 }
845 }
846
847 } else {
848 return false;
849 }
850}
851
852
853bool
855 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
857 // XXX lefthand issue (solve via #4256)
858 if (dir != LinkDirection::LEFT && dir != LinkDirection::PARTLEFT) {
859 return false;
860 }
861 dir = myJunction->getDirection(prohibitorFrom, prohibitorCon.toEdge);
862 if (dir != LinkDirection::LEFT && dir != LinkDirection::PARTLEFT) {
863 return false;
864 }
865 if (from == prohibitorFrom || NBRequest::foes(from, con.toEdge, prohibitorFrom, prohibitorCon.toEdge)) {
866 // not an opposite pair
867 return false;
868 }
869
870 const double width1 = MIN2(from->getLaneWidth(con.fromLane) / 2, OptionsCont::getOptions().getFloat("internal-junctions.vehicle-width") / 2);
871 const double width2 = prohibitorCon.toEdge->getLaneWidth(prohibitorCon.toLane) / 2;
872 PositionVector shape = con.shape;
873 shape.append(con.viaShape);
874 PositionVector otherShape = prohibitorCon.shape;
875 otherShape.append(prohibitorCon.viaShape);
876 if (shape.size() == 0 || otherShape.size() == 0) {
877 // no internal lanes built
878 return false;
879 }
880 const double minDV = NBEdge::firstIntersection(shape, otherShape, width1, width2);
881 if (minDV < shape.length() - POSITION_EPS && minDV > POSITION_EPS) {
882 // break symmetry using edge id
883 return foes || from->getID() < prohibitorFrom->getID();
884 }
885 return false;
886}
887
888bool
890 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
891 if (from == prohibitorFrom) {
892 if (con.toEdge == prohibitorCon.toEdge) {
893 return false;
894 } else if (con.indirectLeft) {
895 LinkDirection dir = myJunction->getDirection(prohibitorFrom, prohibitorCon.toEdge);
896 return (dir == LinkDirection::STRAIGHT);
897 } else if (foes && prohibitorCon.indirectLeft) {
899 return (dir == LinkDirection::STRAIGHT);
900 }
901 }
902 return false;
903}
904
905bool
907 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
908 if (from == prohibitorFrom) {
909 return false;
910 }
911 if (isRailway(from->getPermissions())) {
912 // railways manage right-of-way via signals
913 return false;
914 }
915 if ((foes && (from->getBidiEdge() == prohibitorCon.toEdge))
916 || prohibitorFrom->getBidiEdge() == con.toEdge) {
917 const bool fromBidi = from->getLaneShape(con.fromLane).reverse().almostSame(
918 prohibitorCon.toEdge->getLaneShape(prohibitorCon.toLane), POSITION_EPS);
919 const bool prohibitorFromBidi = prohibitorFrom->getLaneShape(prohibitorCon.fromLane).reverse().almostSame(
920 con.toEdge->getLaneShape(con.toLane), POSITION_EPS);
921 if (!foes && fromBidi && prohibitorFromBidi) {
922 // do not create a symmetrical conflict
923 return false;
924 }
925 if (prohibitorFromBidi &&
926 prohibitorFrom->getLaneShape(prohibitorCon.fromLane).reverse().almostSame(
927 prohibitorCon.toEdge->getLaneShape(prohibitorCon.toLane), POSITION_EPS)) {
928 // prohibitor has a bidi-turnaround
929 return false;
930 }
931
932 return fromBidi || prohibitorFromBidi;
933 }
934 return false;
935}
936
937bool
939 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon) const {
940 if (con.toEdge != prohibitorCon.toEdge) {
941 return false;
942 }
944 SVCPermissions svc2 = prohibitorFrom->getPermissions(prohibitorCon.fromLane) & prohibitorCon.toEdge->getPermissions(prohibitorCon.toLane);
945 // check for lane level conflict if the only common classes are bicycles or pedestrians
946 return ((svc & svc2 & ~(SVC_BICYCLE | SVC_PEDESTRIAN)) == 0
947 // or if the connection is to a dedicated lane whereas the prohibitor is a "general" lane
948 || (((svc & SVC_PASSENGER) == 0) && ((svc2 & SVC_PASSENGER) != 0)));
949}
950
951
952bool
954 const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon) const {
955 if (con.toEdge != prohibitorCon.toEdge) {
956 return false;
957 }
958 // if from and prohibitorFrom target distinct lanes for all their
959 // connections to the common target edge, cooperation is possible
960 // (and should always happen unless the connections cross for some byzantine reason)
961
962 std::set<int> fromTargetLanes;
963 for (const NBEdge::Connection& c : from->getConnections()) {
964 if (c.toEdge == con.toEdge) {
965 fromTargetLanes.insert(c.toLane);
966 }
967 }
968 for (const NBEdge::Connection& c : prohibitorFrom->getConnections()) {
969 if (c.toEdge == con.toEdge && fromTargetLanes.count(c.toLane) != 0) {
970 //std::cout << " con=" << con->getDescription(from) << " foe=" << prohibitorCon.getDescription(prohibitorFrom)
971 // << " no cooperation (targets=" << joinToString(fromTargetLanes, ' ') << " index=" << c.toLane << "\n";
972 return false;
973 }
974 }
975 return true;
976}
977
978
979bool
980NBRequest::laneConflict(const NBEdge* from, const NBEdge* to, int toLane,
981 const NBEdge* prohibitorFrom, const NBEdge* prohibitorTo, int prohibitorToLane) const {
982 if (to != prohibitorTo) {
983 return true;
984 }
985 // since we know that the edge2edge connections are in conflict, the only
986 // situation in which the lane2lane connections can be conflict-free is, if
987 // they target the same edge but do not cross each other
988 double angle = NBHelpers::relAngle(
989 from->getAngleAtNode(from->getToNode()), to->getAngleAtNode(to->getFromNode()));
990 if (angle == 180) {
991 angle = -180; // turnarounds are left turns
992 }
993 const double prohibitorAngle = NBHelpers::relAngle(
994 prohibitorFrom->getAngleAtNode(prohibitorFrom->getToNode()), to->getAngleAtNode(to->getFromNode()));
995 const bool rightOfProhibitor = prohibitorFrom->isTurningDirectionAt(to)
996 || (angle > prohibitorAngle && !from->isTurningDirectionAt(to));
997 return rightOfProhibitor ? toLane >= prohibitorToLane : toLane <= prohibitorToLane;
998}
999
1000int
1001NBRequest::getIndex(const NBEdge* const from, const NBEdge* const to) const {
1002 EdgeVector::const_iterator fp = std::find(myIncoming.begin(), myIncoming.end(), from);
1003 EdgeVector::const_iterator tp = std::find(myOutgoing.begin(), myOutgoing.end(), to);
1004 if (fp == myIncoming.end() || tp == myOutgoing.end()) {
1005 return -1;
1006 }
1007 // compute the index
1008 return (int)(distance(myIncoming.begin(), fp) * myOutgoing.size() + distance(myOutgoing.begin(), tp));
1009}
1010
1011
1012std::ostream&
1013operator<<(std::ostream& os, const NBRequest& r) {
1014 int variations = r.numLinks();
1015 for (int i = 0; i < variations; i++) {
1016 os << i << ' ';
1017 for (int j = 0; j < variations; j++) {
1018 if (r.myForbids[i][j]) {
1019 os << '1';
1020 } else {
1021 os << '0';
1022 }
1023 }
1024 os << std::endl;
1025 }
1026 os << std::endl;
1027 return os;
1028}
1029
1030
1031bool
1032NBRequest::mustBrake(const NBEdge* const from, const NBEdge* const to, int fromLane, int toLane, bool includePedCrossings) const {
1033 NBEdge::Connection con(fromLane, const_cast<NBEdge*>(to), toLane);
1034 const int linkIndex = myJunction->getConnectionIndex(from, con);
1035 if (linkIndex >= 0 && (int)myResponse.size() > linkIndex) {
1036 std::string response = getResponse(linkIndex);
1037 if (!includePedCrossings) {
1038 response = response.substr(0, response.size() - myJunction->getCrossings().size());
1039 }
1040 if (response.find_first_of("1") == std::string::npos) {
1041 return false;
1042 } else if (!myJunction->isTLControlled()) {
1043 return true;
1044 }
1045 // if the link must respond it could also be due to a tlsConflict. This
1046 // must not carry over the off-state response so we continue with
1047 // the regular check
1048 }
1049 // get the indices
1050 int idx2 = getIndex(from, to);
1051 if (idx2 == -1) {
1052 return false;
1053 }
1054 // go through all (existing) connections;
1055 // check whether any of these forbids the one to determine
1056 assert(idx2 < (int)(myIncoming.size()*myOutgoing.size()));
1057 for (int idx1 = 0; idx1 < numLinks(); idx1++) {
1058 //assert(myDone[idx1][idx2]);
1059 if (myDone[idx1][idx2] && myForbids[idx1][idx2]) {
1060 return true;
1061 }
1062 }
1063 // maybe we need to brake for a pedestrian crossing
1064 if (includePedCrossings) {
1065 auto crossings = myJunction->getCrossings();
1066 for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = crossings.rbegin(); i != crossings.rend(); i++) {
1067 if (mustBrakeForCrossing(myJunction, from, to, **i)) {
1068 return true;
1069 }
1070 }
1071 }
1072 // maybe we need to brake due to a right-turn conflict with straight-going
1073 // bicycles
1074 const NBEdge::Connection& queryCon = from->getConnection(fromLane, to, toLane);
1075 LinkDirection dir = myJunction->getDirection(from, to);
1076 if (dir == LinkDirection::RIGHT || dir == LinkDirection::PARTRIGHT) {
1077 for (const NBEdge::Connection& fromCon : from->getConnections()) {
1078 if (rightTurnConflict(from, queryCon, from, fromCon)) {
1079 return true;
1080 }
1081 }
1082 }
1083 // maybe we need to brake due to a merge conflict
1084 for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
1085 int noLanes = (*i)->getNumLanes();
1086 for (int j = noLanes; j-- > 0;) {
1087 std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
1088 const int size = (int) connected.size();
1089 for (int k = size; k-- > 0;) {
1090 if ((*i) == from && fromLane != j
1091 && mergeConflict(from, queryCon, *i, connected[k], myJunction->getType() == SumoXMLNodeType::ZIPPER)) {
1092 return true;
1093 }
1094 }
1095 }
1096 }
1097 // maybe we need to brake due to a zipper conflict
1099 for (int idx1 = 0; idx1 < numLinks(); idx1++) {
1100 //assert(myDone[idx1][idx2]);
1101 if (myDone[idx1][idx2] && myForbids[idx2][idx1]) {
1102 return true;
1103 }
1104 }
1105 }
1106 return false;
1107}
1108
1109
1110bool
1111NBRequest::mustBrakeForCrossing(const NBNode* node, const NBEdge* const from, const NBEdge* const to, const NBNode::Crossing& crossing) {
1112 const LinkDirection dir = node->getDirection(from, to);
1113 const bool mustYield = dir == LinkDirection::LEFT || dir == LinkDirection::RIGHT;
1114 if (crossing.priority || mustYield) {
1115 for (const NBEdge* const e : crossing.edges) {
1116 // left and right turns must yield to unprioritized crossings only on their destination edge
1117 if ((e == from && crossing.priority) || e == to) {
1118 return true;
1119 }
1120 }
1121 }
1122 return false;
1123}
1124
1125
1126bool
1127NBRequest::mustBrake(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
1128 const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo) const {
1129 // get the indices
1130 int idx1 = getIndex(possProhibitorFrom, possProhibitorTo);
1131 int idx2 = getIndex(possProhibitedFrom, possProhibitedTo);
1132 return (myForbids[idx2][idx1]);
1133}
1134
1135
1136void
1138 // check if any errors occurred on build the link prohibitions
1139 if (myNotBuild != 0) {
1140 WRITE_WARNING(toString(myNotBuild) + " of " + toString(myNotBuild + myGoodBuilds) + " prohibitions were not build.");
1141 }
1142}
1143
1144
1145void
1147 // map from edge to number of incoming connections
1148 std::map<const NBEdge*, int> incomingCount; // initialized to 0
1149 // map from edge to indices of approached lanes
1150 std::map<const NBEdge*, std::set<int> > approachedLanes;
1151 // map from edge to list of incoming edges
1152 std::map<const NBEdge*, std::vector<const NBEdge*> > incomingEdges;
1153 for (const NBEdge* const e : myIncoming) {
1154 for (const NBEdge::Connection& con : e->getConnections()) {
1155 incomingCount[con.toEdge]++;
1156 approachedLanes[con.toEdge].insert(con.toLane);
1157 incomingEdges[con.toEdge].push_back(e);
1158 }
1159 }
1160 for (std::map<const NBEdge*, int>::iterator it = incomingCount.begin(); it != incomingCount.end(); ++it) {
1161 const NBEdge* const to = it->first;
1162 // we cannot test against to->getNumLanes() since not all lanes may be used
1163 if ((int)approachedLanes[to].size() >= it->second) {
1164 const std::vector<const NBEdge*>& incoming = incomingEdges[to];
1165 // make these connections mutually unconflicting
1166 for (const NBEdge* const e1 : incoming) {
1167 for (const NBEdge* const e2 : incoming) {
1168 myForbids[getIndex(e1, to)][getIndex(e2, to)] = false;
1169#ifdef DEBUG_SETBLOCKING
1170 if (DEBUGCOND) std::cout << "resetCooperating"
1171 << " 1:" << e1->getID() << "->" << to->getID()
1172 << " 2:" << e2->getID() << "->" << to->getID()
1173 << "\n";
1174#endif
1175 }
1176 }
1177 }
1178 }
1179}
1180
1181
1182bool
1184 for (int i = 0; i < (int)myFoes.size(); i++) {
1185 if (hasConflictAtLink(i)) {
1186 return true;
1187 }
1188 }
1189 return false;
1190}
1191
1192bool
1193NBRequest::hasConflictAtLink(int linkIndex) const {
1194 return myFoes[linkIndex].find_first_of("1") != std::string::npos;
1195}
1196
1197int
1199 return (int)(myIncoming.size() * myOutgoing.size() + myJunction->getCrossings().size());
1200}
1201
1202
1203/****************************************************************************/
#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:4379
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition NBEdge.h:1041
double getLaneWidth() const
Returns the default width of lanes of this edge.
Definition NBEdge.h:642
NBNode * getToNode() const
Returns the destination node of the edge.
Definition NBEdge.h:546
const Connection & getConnection(int fromLane, const NBEdge *to, int toLane) const
Returns the specified connection (unmodifiable) This method goes through "myConnections" and returns ...
Definition NBEdge.cpp:1301
const std::string & getID() const
Definition NBEdge.h:1528
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition NBEdge.cpp:3665
bool hasSignalisedConnectionTo(const NBEdge *const e) const
Check if edge has signalised connections.
Definition NBEdge.cpp:3997
int getNumLanes() const
Returns the number of lanes.
Definition NBEdge.h:520
std::vector< Connection > getConnectionsFromLane(int lane, const NBEdge *to=nullptr, int toLane=-1) const
Returns connections from a given lane.
Definition NBEdge.cpp:1287
static double firstIntersection(const PositionVector &v1, const PositionVector &v2, double width1, double width2, const std::string &error="", bool secondIntersection=false)
compute the first intersection point between the given lane geometries considering their rspective wi...
Definition NBEdge.cpp:2050
bool isConnectedTo(const NBEdge *e, const bool ignoreTurnaround=false) const
Returns the information whethe a connection to the given edge has been added (or computed)
Definition NBEdge.cpp:1331
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
Definition NBEdge.cpp:2133
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:2159
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:2409
int getConnectionIndex(const NBEdge *from, const NBEdge::Connection &con) const
return the index of the given connection
Definition NBNode.cpp:4004
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:4080
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:2094
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
Definition NBNode.cpp:2982
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:2174
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