Eclipse SUMO - Simulation of Urban MObility
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>
34 #include <utils/common/ToString.h>
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 // ===========================================================================
50 int NBRequest::myNotBuild = 0;
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 
144 void
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
154  resetSignalised();
155  // reset foes it the number of lanes matches (or exceeds) the number of incoming connections
157 }
158 
159 
160 void
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 
178 void
180  EdgeVector::const_iterator pfrom = std::find(myAll.begin(), myAll.end(), from);
181  while (*pfrom != to) {
182  NBContHelper::nextCW(myAll, pfrom);
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 
196 void
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 
368 int
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 
382 const std::string&
383 NBRequest::getFoes(int linkIndex) const {
384  assert(linkIndex >= 0);
385  assert(linkIndex < (int)myFoes.size());
386  return myFoes[linkIndex];
387 }
388 
389 
390 const std::string&
391 NBRequest::getResponse(int linkIndex) const {
392  assert(linkIndex >= 0);
393  assert(linkIndex < (int)myResponse.size());
394  return myResponse[linkIndex];
395 }
396 
397 
398 void
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  }
411  into.writeAttr(SUMO_ATTR_FOES, myFoes[i]);
412  if (!OptionsCont::getOptions().getBool("no-internal-links")) {
414  }
415  into.closeTag();
416  }
417 }
418 
419 
420 void
421 NBRequest::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 
441 void
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 
501 std::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 
519 bool
520 NBRequest::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 
538 bool
539 NBRequest::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 
569 int
570 NBRequest::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 
584 int
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 
616 std::string
617 NBRequest::getResponseString(const NBEdge* const from, const NBEdge::Connection& c, const bool checkLaneFoes) const {
618  const NBEdge* const to = c.toEdge;
619  const int fromLane = c.fromLane;
620  const int toLane = c.toLane;
621  int idx = 0;
622  if (to != nullptr) {
623  idx = getIndex(from, to);
624  }
625  std::string result;
626  const bool zipper = myJunction->getType() == SumoXMLNodeType::ZIPPER;
627  // crossings
628  auto crossings = myJunction->getCrossings();
629  for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = crossings.rbegin(); i != crossings.rend(); i++) {
630  result += mustBrakeForCrossing(myJunction, from, to, **i) ? '1' : '0';
631  }
632  const NBEdge::Connection& queryCon = from->getConnection(fromLane, to, toLane);
633  // normal connections
634  for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
635  //const std::vector<NBEdge::Connection> &allConnections = (*i)->getConnections();
636  int noLanes = (*i)->getNumLanes();
637  for (int j = noLanes; j-- > 0;) {
638  std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
639  int size = (int) connected.size();
640  for (int k = size; k-- > 0;) {
641  if (c.mayDefinitelyPass) {
642  result += '0';
643 #ifdef DEBUG_RESPONSE
644  if (DEBUGCOND) {
645  std::cout << " c=" << queryCon.getDescription(from) << " pass\n";
646  }
647 #endif
648  } else if ((*i) == from && fromLane == j) {
649  // do not prohibit a connection by others from same lane
650  // except for indirect turns
651 #ifdef DEBUG_RESPONSE
652  if (DEBUGCOND) {
653  std::cout << " c=" << queryCon.getDescription(from) << " prohibitC=" << connected[k].getDescription(*i)
654  << " itc=" << indirectLeftTurnConflict(from, queryCon, *i, connected[k], false)
655  << "\n";
656  }
657 #endif
658  if (indirectLeftTurnConflict(from, queryCon, *i, connected[k], false)) {
659  result += '1';
660  } else {
661  result += '0';
662  }
663  } else {
664  assert(connected[k].toEdge != 0);
665  const int idx2 = getIndex(*i, connected[k].toEdge);
666  assert(k < (int) connected.size());
667  assert(idx < (int)(myIncoming.size() * myOutgoing.size()));
668  assert(idx2 < (int)(myIncoming.size() * myOutgoing.size()));
669  // check whether the connection is prohibited by another one
670 #ifdef DEBUG_RESPONSE
671  if (DEBUGCOND) {
672  std::cout << " c=" << queryCon.getDescription(from) << " prohibitC=" << connected[k].getDescription(*i)
673  << " f=" << myForbids[idx2][idx]
674  << " clf=" << checkLaneFoes
675  << " clfbc=" << checkLaneFoesByClass(queryCon, *i, connected[k])
676  << " clfbcoop=" << checkLaneFoesByCooperation(from, queryCon, *i, connected[k])
677  << " lc=" << laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane)
678  << " rtc=" << NBNode::rightTurnConflict(from, to, fromLane, *i, connected[k].toEdge, connected[k].fromLane)
679  << " rtc2=" << rightTurnConflict(from, queryCon, *i, connected[k])
680  << " mc=" << mergeConflict(from, queryCon, *i, connected[k], false)
681  << " oltc=" << oppositeLeftTurnConflict(from, queryCon, *i, connected[k], false)
682  << " itc=" << indirectLeftTurnConflict(from, queryCon, *i, connected[k], zipper)
683  << " bc=" << bidiConflict(from, queryCon, *i, connected[k], false)
684  << " rorc=" << myJunction->rightOnRedConflict(c.tlLinkIndex, connected[k].tlLinkIndex)
685  << " tlscc=" << myJunction->tlsContConflict(from, c, *i, connected[k])
686  << "\n";
687  }
688 #endif
689  const bool hasLaneConflict = (!(checkLaneFoes || checkLaneFoesByClass(queryCon, *i, connected[k])
690  || checkLaneFoesByCooperation(from, queryCon, *i, connected[k]))
691  || laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane));
692  if (((myForbids[idx2][idx] || (zipper && myForbids[idx][idx2])) && hasLaneConflict && !bidiConflict(*i, connected[k], from, queryCon, false))
693  || rightTurnConflict(from, queryCon, *i, connected[k])
694  || mergeConflict(from, queryCon, *i, connected[k], zipper)
695  || oppositeLeftTurnConflict(from, queryCon, *i, connected[k], zipper)
696  || indirectLeftTurnConflict(from, queryCon, *i, connected[k], zipper)
697  || bidiConflict(from, queryCon, *i, connected[k], false)
698  || myJunction->rightOnRedConflict(c.tlLinkIndex, connected[k].tlLinkIndex)
699  || (myJunction->tlsContConflict(from, c, *i, connected[k]) && hasLaneConflict
700  && !OptionsCont::getOptions().getBool("tls.ignore-internal-junction-jam"))
701  ) {
702  result += '1';
703  } else {
704  result += '0';
705  }
706  }
707  }
708  }
709  }
710  return result;
711 }
712 
713 
714 std::string
715 NBRequest::getFoesString(NBEdge* from, NBEdge* to, int fromLane, int toLane, const bool checkLaneFoes) const {
716  const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
717  // remember the case when the lane is a "dead end" in the meaning that
718  // vehicles must choose another lane to move over the following
719  // junction
720  // !!! move to forbidden
721  std::string result;
722  // crossings
723  auto crossings = myJunction->getCrossings();
724  for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = crossings.rbegin(); i != crossings.rend(); i++) {
725  bool foes = false;
726  for (EdgeVector::const_iterator it_e = (**i).edges.begin(); it_e != (**i).edges.end(); ++it_e) {
727  if ((*it_e) == from || (*it_e) == to) {
728  foes = true;
729  break;
730  }
731  }
732  result += foes ? '1' : '0';
733  }
734  const NBEdge::Connection& queryCon = from->getConnection(fromLane, to, toLane);
735  // normal connections
736  for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
737  for (int j = (*i)->getNumLanes() - 1; j >= 0; --j) {
738  const std::vector<NBEdge::Connection>& connected = (*i)->getConnectionsFromLane(j);
739  int size = (int) connected.size();
740  for (int k = size; k-- > 0;) {
741  const bool hasLaneConflict = (!(checkLaneFoes || checkLaneFoesByClass(queryCon, *i, connected[k])
742  || checkLaneFoesByCooperation(from, queryCon, *i, connected[k]))
743  || laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane));
744  if ((foes(from, to, (*i), connected[k].toEdge) && hasLaneConflict)
745  || rightTurnConflict(from, queryCon, *i, connected[k])
746  || myJunction->turnFoes(from, to, fromLane, *i, connected[k].toEdge, connected[k].fromLane, lefthand)
747  || mergeConflict(from, queryCon, *i, connected[k], true)
748  || oppositeLeftTurnConflict(from, queryCon, *i, connected[k], true)
749  || indirectLeftTurnConflict(from, queryCon, *i, connected[k], true)
750  || bidiConflict(from, queryCon, *i, connected[k], true)
751  ) {
752  result += '1';
753  } else {
754  result += '0';
755  }
756  }
757  }
758  }
759  return result;
760 }
761 
762 
763 bool
765  const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon) const {
766  return (!con.mayDefinitelyPass &&
767  (NBNode::rightTurnConflict(from, con.toEdge, con.fromLane, prohibitorFrom, prohibitorCon.toEdge, prohibitorCon.fromLane)
768  // reverse conflicht (override)
769  || (prohibitorCon.mayDefinitelyPass &&
770  NBNode::rightTurnConflict(prohibitorFrom, prohibitorCon.toEdge, prohibitorCon.fromLane, from, con.toEdge, con.fromLane))));
771 
772 
773 }
774 
775 
776 bool
778  const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
779  if (from == prohibitorFrom
780  && con.toEdge == prohibitorCon.toEdge
781  && con.toLane == prohibitorCon.toLane
782  && con.fromLane != prohibitorCon.fromLane
784  if (foes) {
785  return true;
786  }
787  if (prohibitorCon.mayDefinitelyPass) {
788  return true;
789  }
790  if (con.mayDefinitelyPass) {
791  return false;
792  }
793  const bool bike = from->getPermissions(con.fromLane) == SVC_BICYCLE;
794  const bool prohibitorBike = prohibitorFrom->getPermissions(prohibitorCon.fromLane) == SVC_BICYCLE;
795  if (myOutgoing.size() == 1) {
796  // at on-ramp like situations, right lane should yield
797  return bike || (con.fromLane < prohibitorCon.fromLane && !prohibitorBike);
798  } else {
799  // priority depends on direction:
800  // for right turns the rightmost lane gets priority
801  // otherwise the left lane
802  LinkDirection dir = myJunction->getDirection(from, con.toEdge);
803  if (dir == LinkDirection::RIGHT || dir == LinkDirection::PARTRIGHT) {
804  return con.fromLane > prohibitorCon.fromLane;
805  } else {
806  if (myIncoming.size() == 1) {
807  // at off-ramp like situations, right lane should pass unless it's a bicycle lane
808  return bike || (con.fromLane > prohibitorCon.fromLane && !prohibitorBike);
809  } else {
810  return con.fromLane < prohibitorCon.fromLane;
811  }
812  }
813  }
814 
815  } else {
816  return false;
817  }
818 }
819 
820 
821 bool
823  const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
824  LinkDirection dir = myJunction->getDirection(from, con.toEdge);
825  // XXX lefthand issue (solve via #4256)
826  if (dir != LinkDirection::LEFT && dir != LinkDirection::PARTLEFT) {
827  return false;
828  }
829  dir = myJunction->getDirection(prohibitorFrom, prohibitorCon.toEdge);
830  if (dir != LinkDirection::LEFT && dir != LinkDirection::PARTLEFT) {
831  return false;
832  }
833  if (from == prohibitorFrom || NBRequest::foes(from, con.toEdge, prohibitorFrom, prohibitorCon.toEdge)) {
834  // not an opposite pair
835  return false;
836  }
837 
838  const double width1 = MIN2(from->getLaneWidth(con.fromLane) / 2, OptionsCont::getOptions().getFloat("internal-junctions.vehicle-width") / 2);
839  const double width2 = prohibitorCon.toEdge->getLaneWidth(prohibitorCon.toLane) / 2;
840  PositionVector shape = con.shape;
841  shape.append(con.viaShape);
842  PositionVector otherShape = prohibitorCon.shape;
843  otherShape.append(prohibitorCon.viaShape);
844  if (shape.size() == 0 || otherShape.size() == 0) {
845  // no internal lanes built
846  return false;
847  }
848  const double minDV = NBEdge::firstIntersection(shape, otherShape, width1, width2);
849  if (minDV < shape.length() - POSITION_EPS && minDV > POSITION_EPS) {
850  // break symmetry using edge id
851  return foes || from->getID() < prohibitorFrom->getID();
852  }
853  return false;
854 }
855 
856 bool
858  const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
859  if (from == prohibitorFrom) {
860  if (con.toEdge == prohibitorCon.toEdge) {
861  return false;
862  } else if (con.indirectLeft) {
863  LinkDirection dir = myJunction->getDirection(prohibitorFrom, prohibitorCon.toEdge);
864  return (dir == LinkDirection::STRAIGHT);
865  } else if (foes && prohibitorCon.indirectLeft) {
866  LinkDirection dir = myJunction->getDirection(from, con.toEdge);
867  return (dir == LinkDirection::STRAIGHT);
868  }
869  }
870  return false;
871 }
872 
873 bool
875  const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
876  if (from == prohibitorFrom) {
877  return false;
878  }
879  if (isRailway(from->getPermissions())) {
880  // railways manage right-of-way via signals
881  return false;
882  }
883  if ((foes && (from->getBidiEdge() == prohibitorCon.toEdge))
884  || prohibitorFrom->getBidiEdge() == con.toEdge) {
885  const bool fromBidi = from->getLaneShape(con.fromLane).reverse().almostSame(
886  prohibitorCon.toEdge->getLaneShape(prohibitorCon.toLane), POSITION_EPS);
887  const bool prohibitorFromBidi = prohibitorFrom->getLaneShape(prohibitorCon.fromLane).reverse().almostSame(
888  con.toEdge->getLaneShape(con.toLane), POSITION_EPS);
889  if (!foes && fromBidi && prohibitorFromBidi) {
890  // do not create a symmetrical conflict
891  return false;
892  }
893  if (prohibitorFromBidi &&
894  prohibitorFrom->getLaneShape(prohibitorCon.fromLane).reverse().almostSame(
895  prohibitorCon.toEdge->getLaneShape(prohibitorCon.toLane), POSITION_EPS)) {
896  // prohibitor has a bidi-turnaround
897  return false;
898  }
899 
900  return fromBidi || prohibitorFromBidi;
901  }
902  return false;
903 }
904 
905 bool
907  const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon) const {
908  if (con.toEdge != prohibitorCon.toEdge) {
909  return false;
910  }
911  SVCPermissions svc = con.toEdge->getPermissions(con.toLane);
912  SVCPermissions svc2 = prohibitorFrom->getPermissions(prohibitorCon.fromLane) & prohibitorCon.toEdge->getPermissions(prohibitorCon.toLane);
913  // check for lane level conflict if the only common classes are bicycles or pedestrians
914  return ((svc & svc2 & ~(SVC_BICYCLE | SVC_PEDESTRIAN)) == 0
915  // or if the connection is to a dedicated lane whereas the prohibitor is a "general" lane
916  || (((svc & SVC_PASSENGER) == 0) && ((svc2 & SVC_PASSENGER) != 0)));
917 }
918 
919 
920 bool
922  const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon) const {
923  if (con.toEdge != prohibitorCon.toEdge) {
924  return false;
925  }
926  // if from and prohibitorFrom target distinct lanes for all their
927  // connections to the common target edge, cooperation is possible
928  // (and should always happen unless the connections cross for some byzantine reason)
929 
930  std::set<int> fromTargetLanes;
931  for (const NBEdge::Connection& c : from->getConnections()) {
932  if (c.toEdge == con.toEdge) {
933  fromTargetLanes.insert(c.toLane);
934  }
935  }
936  for (const NBEdge::Connection& c : prohibitorFrom->getConnections()) {
937  if (c.toEdge == con.toEdge && fromTargetLanes.count(c.toLane) != 0) {
938  //std::cout << " con=" << con->getDescription(from) << " foe=" << prohibitorCon.getDescription(prohibitorFrom)
939  // << " no cooperation (targets=" << joinToString(fromTargetLanes, ' ') << " index=" << c.toLane << "\n";
940  return false;
941  }
942  }
943  return true;
944 }
945 
946 
947 bool
948 NBRequest::laneConflict(const NBEdge* from, const NBEdge* to, int toLane,
949  const NBEdge* prohibitorFrom, const NBEdge* prohibitorTo, int prohibitorToLane) const {
950  if (to != prohibitorTo) {
951  return true;
952  }
953  // since we know that the edge2edge connections are in conflict, the only
954  // situation in which the lane2lane connections can be conflict-free is, if
955  // they target the same edge but do not cross each other
956  double angle = NBHelpers::relAngle(
957  from->getAngleAtNode(from->getToNode()), to->getAngleAtNode(to->getFromNode()));
958  if (angle == 180) {
959  angle = -180; // turnarounds are left turns
960  }
961  const double prohibitorAngle = NBHelpers::relAngle(
962  prohibitorFrom->getAngleAtNode(prohibitorFrom->getToNode()), to->getAngleAtNode(to->getFromNode()));
963  const bool rightOfProhibitor = prohibitorFrom->isTurningDirectionAt(to)
964  || (angle > prohibitorAngle && !from->isTurningDirectionAt(to));
965  return rightOfProhibitor ? toLane >= prohibitorToLane : toLane <= prohibitorToLane;
966 }
967 
968 int
969 NBRequest::getIndex(const NBEdge* const from, const NBEdge* const to) const {
970  EdgeVector::const_iterator fp = std::find(myIncoming.begin(), myIncoming.end(), from);
971  EdgeVector::const_iterator tp = std::find(myOutgoing.begin(), myOutgoing.end(), to);
972  if (fp == myIncoming.end() || tp == myOutgoing.end()) {
973  return -1;
974  }
975  // compute the index
976  return (int)(distance(myIncoming.begin(), fp) * myOutgoing.size() + distance(myOutgoing.begin(), tp));
977 }
978 
979 
980 std::ostream&
981 operator<<(std::ostream& os, const NBRequest& r) {
982  int variations = r.numLinks();
983  for (int i = 0; i < variations; i++) {
984  os << i << ' ';
985  for (int j = 0; j < variations; j++) {
986  if (r.myForbids[i][j]) {
987  os << '1';
988  } else {
989  os << '0';
990  }
991  }
992  os << std::endl;
993  }
994  os << std::endl;
995  return os;
996 }
997 
998 
999 bool
1000 NBRequest::mustBrake(const NBEdge* const from, const NBEdge* const to, int fromLane, int toLane, bool includePedCrossings) const {
1001  NBEdge::Connection con(fromLane, const_cast<NBEdge*>(to), toLane);
1002  const int linkIndex = myJunction->getConnectionIndex(from, con);
1003  if (linkIndex >= 0 && (int)myResponse.size() > linkIndex) {
1004  std::string response = getResponse(linkIndex);
1005  if (!includePedCrossings) {
1006  response = response.substr(0, response.size() - myJunction->getCrossings().size());
1007  }
1008  if (response.find_first_of("1") == std::string::npos) {
1009  return false;
1010  } else if (!myJunction->isTLControlled()) {
1011  return true;
1012  }
1013  // if the link must respond it could also be due to a tlsConflict. This
1014  // must not carry over the the off-state response so we continue with
1015  // the regular check
1016  }
1017  // get the indices
1018  int idx2 = getIndex(from, to);
1019  if (idx2 == -1) {
1020  return false;
1021  }
1022  // go through all (existing) connections;
1023  // check whether any of these forbids the one to determine
1024  assert(idx2 < (int)(myIncoming.size()*myOutgoing.size()));
1025  for (int idx1 = 0; idx1 < numLinks(); idx1++) {
1026  //assert(myDone[idx1][idx2]);
1027  if (myDone[idx1][idx2] && myForbids[idx1][idx2]) {
1028  return true;
1029  }
1030  }
1031  // maybe we need to brake for a pedestrian crossing
1032  if (includePedCrossings) {
1033  auto crossings = myJunction->getCrossings();
1034  for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = crossings.rbegin(); i != crossings.rend(); i++) {
1035  if (mustBrakeForCrossing(myJunction, from, to, **i)) {
1036  return true;
1037  }
1038  }
1039  }
1040  // maybe we need to brake due to a right-turn conflict with straight-going
1041  // bicycles
1042  const NBEdge::Connection& queryCon = from->getConnection(fromLane, to, toLane);
1043  LinkDirection dir = myJunction->getDirection(from, to);
1044  if (dir == LinkDirection::RIGHT || dir == LinkDirection::PARTRIGHT) {
1045  for (const NBEdge::Connection& fromCon : from->getConnections()) {
1046  if (rightTurnConflict(from, queryCon, from, fromCon)) {
1047  return true;
1048  }
1049  }
1050  }
1051  // maybe we need to brake due to a merge conflict
1052  for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
1053  int noLanes = (*i)->getNumLanes();
1054  for (int j = noLanes; j-- > 0;) {
1055  std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
1056  const int size = (int) connected.size();
1057  for (int k = size; k-- > 0;) {
1058  if ((*i) == from && fromLane != j
1059  && mergeConflict(from, queryCon, *i, connected[k], myJunction->getType() == SumoXMLNodeType::ZIPPER)) {
1060  return true;
1061  }
1062  }
1063  }
1064  }
1065  // maybe we need to brake due to a zipper conflict
1067  for (int idx1 = 0; idx1 < numLinks(); idx1++) {
1068  //assert(myDone[idx1][idx2]);
1069  if (myDone[idx1][idx2] && myForbids[idx2][idx1]) {
1070  return true;
1071  }
1072  }
1073  }
1074  return false;
1075 }
1076 
1077 
1078 bool
1079 NBRequest::mustBrakeForCrossing(const NBNode* node, const NBEdge* const from, const NBEdge* const to, const NBNode::Crossing& crossing) {
1080  const LinkDirection dir = node->getDirection(from, to);
1081  const bool mustYield = dir == LinkDirection::LEFT || dir == LinkDirection::RIGHT;
1082  if (crossing.priority || mustYield) {
1083  for (const NBEdge* const e : crossing.edges) {
1084  // left and right turns must yield to unprioritized crossings only on their destination edge
1085  if ((e == from && crossing.priority) || e == to) {
1086  return true;
1087  }
1088  }
1089  }
1090  return false;
1091 }
1092 
1093 
1094 bool
1095 NBRequest::mustBrake(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
1096  const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo) const {
1097  // get the indices
1098  int idx1 = getIndex(possProhibitorFrom, possProhibitorTo);
1099  int idx2 = getIndex(possProhibitedFrom, possProhibitedTo);
1100  return (myForbids[idx2][idx1]);
1101 }
1102 
1103 
1104 void
1106  // check if any errors occurred on build the link prohibitions
1107  if (myNotBuild != 0) {
1108  WRITE_WARNING(toString(myNotBuild) + " of " + toString(myNotBuild + myGoodBuilds) + " prohibitions were not build.");
1109  }
1110 }
1111 
1112 
1113 void
1115  // map from edge to number of incoming connections
1116  std::map<const NBEdge*, int> incomingCount; // initialized to 0
1117  // map from edge to indices of approached lanes
1118  std::map<const NBEdge*, std::set<int> > approachedLanes;
1119  // map from edge to list of incoming edges
1120  std::map<const NBEdge*, std::vector<const NBEdge*> > incomingEdges;
1121  for (const NBEdge* const e : myIncoming) {
1122  for (const NBEdge::Connection& con : e->getConnections()) {
1123  incomingCount[con.toEdge]++;
1124  approachedLanes[con.toEdge].insert(con.toLane);
1125  incomingEdges[con.toEdge].push_back(e);
1126  }
1127  }
1128  for (std::map<const NBEdge*, int>::iterator it = incomingCount.begin(); it != incomingCount.end(); ++it) {
1129  const NBEdge* const to = it->first;
1130  // we cannot test against to->getNumLanes() since not all lanes may be used
1131  if ((int)approachedLanes[to].size() >= it->second) {
1132  const std::vector<const NBEdge*>& incoming = incomingEdges[to];
1133  // make these connections mutually unconflicting
1134  for (const NBEdge* const e1 : incoming) {
1135  for (const NBEdge* const e2 : incoming) {
1136  myForbids[getIndex(e1, to)][getIndex(e2, to)] = false;
1137  }
1138  }
1139  }
1140  }
1141 }
1142 
1143 
1144 bool
1146  for (int i = 0; i < (int)myFoes.size(); i++) {
1147  if (hasConflictAtLink(i)) {
1148  return true;
1149  }
1150  }
1151  return false;
1152 }
1153 
1154 bool
1155 NBRequest::hasConflictAtLink(int linkIndex) const {
1156  return myFoes[linkIndex].find_first_of("1") != std::string::npos;
1157 }
1158 
1159 int
1161  return (int)(myIncoming.size() * myOutgoing.size() + myJunction->getCrossings().size());
1162 }
1163 
1164 
1165 /****************************************************************************/
#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:35
#define DEBUGCOND
Definition: NBRequest.cpp:44
std::ostream & operator<<(std::ostream &os, const NBRequest &r)
Definition: NBRequest.cpp:981
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission 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:4306
double getLaneWidth() const
Returns the default width of lanes of this edge.
Definition: NBEdge.h:638
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:1266
const std::string & getID() const
Definition: NBEdge.h:1522
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:542
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:3592
bool hasSignalisedConnectionTo(const NBEdge *const e) const
Check if edge has signalised connections.
Definition: NBEdge.cpp:3924
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:516
std::vector< Connection > getConnectionsFromLane(int lane, const NBEdge *to=nullptr, int toLane=-1) const
Returns connections from a given lane.
Definition: NBEdge.cpp:1252
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:1999
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:1296
const NBEdge * getBidiEdge() const
Definition: NBEdge.h:1508
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
Definition: NBEdge.cpp:2082
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
Definition: NBEdge.cpp:2108
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:1035
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
Definition: NBEdge.cpp:967
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:535
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:2349
int getConnectionIndex(const NBEdge *from, const NBEdge::Connection &con) const
return the index of the given connection
Definition: NBNode.cpp:3921
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:3997
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:2034
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
Definition: NBNode.cpp:2918
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:2114
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
Definition: NBRequest.cpp:570
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
Definition: NBRequest.cpp:921
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
Definition: NBRequest.cpp:369
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
Definition: NBRequest.cpp:874
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.
Definition: NBRequest.cpp:539
bool hasConflictAtLink(int linkIndex) const
whether there are conflicting streams of traffic for the given link index
Definition: NBRequest.cpp:1155
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
Definition: NBRequest.cpp:1160
const std::string & getFoes(int linkIndex) const
Definition: NBRequest.cpp:383
bool hasConflict() const
whether there are conflicting streams of traffic at this node
Definition: NBRequest.cpp:1145
std::string getFoesString(NBEdge *from, NBEdge *to, int fromLane, int toLane, const bool checkLaneFoes) const
Definition: NBRequest.cpp:715
void buildBitfieldLogic()
builds the bitset-representation of the logic
Definition: NBRequest.cpp:145
bool oppositeLeftTurnConflict(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon, bool foes) const
whether opposite left turns intersect
Definition: NBRequest.cpp:822
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...
Definition: NBRequest.cpp:948
void resetSignalised()
Definition: NBRequest.cpp:442
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
Definition: NBRequest.cpp:857
int getIndex(const NBEdge *const from, const NBEdge *const to) const
Returns the index to the internal combination container for the given edge combination.
Definition: NBRequest.cpp:969
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.
Definition: NBRequest.cpp:1079
void computeRightOutgoingLinkCrossings(NBEdge *from, NBEdge *to)
computes the relationships between links outgoing right of the given link *‍/
Definition: NBRequest.cpp:161
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
Definition: NBRequest.cpp:777
void writeLogic(OutputDevice &into) const
Definition: NBRequest.cpp:399
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
Definition: NBRequest.cpp:421
std::string getResponseString(const NBEdge *const from, const NBEdge::Connection &c, const bool checkLaneFoes) const
Writes the response of a certain link.
Definition: NBRequest.cpp:617
std::pair< int, int > getSizes() const
returns the number of the junction's lanes and the number of the junction's links in respect.
Definition: NBRequest.cpp:502
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.
Definition: NBRequest.cpp:1095
const std::string & getResponse(int linkIndex) const
Definition: NBRequest.cpp:391
int computeCrossingResponse(const NBNode::Crossing &crossing, int pos)
computes the response of a certain crossing Returns the next link index within the junction
Definition: NBRequest.cpp:585
void setBlocking(NBEdge *from1, NBEdge *to1, NBEdge *from2, NBEdge *to2)
Definition: NBRequest.cpp:197
void computeLeftOutgoingLinkCrossings(NBEdge *from, NBEdge *to)
computes the relationships between links outgoing left of the given link
Definition: NBRequest.cpp:179
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
Definition: NBRequest.cpp:906
void resetCooperating()
reset foes it the number of lanes matches (or exceeds) the number of incoming connections for an edge
Definition: NBRequest.cpp:1114
~NBRequest()
destructor
Definition: NBRequest.cpp:141
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.
Definition: NBRequest.cpp:520
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
Definition: NBRequest.cpp:764
static void reportWarnings()
reports warnings if any occurred
Definition: NBRequest.cpp:1105
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.
Definition: OptionsCont.cpp:60
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
OutputDevice & writePadding(const std::string &val)
writes padding (ignored for binary output)
Definition: OutputDevice.h:325
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:97
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