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.org/sumo
3 // Copyright (C) 2001-2017 German Aerospace Center (DLR) and others.
4 /****************************************************************************/
5 //
6 // This program and the accompanying materials
7 // are made available under the terms of the Eclipse Public License v2.0
8 // which accompanies this distribution, and is available at
9 // http://www.eclipse.org/legal/epl-v20.html
10 //
11 /****************************************************************************/
20 // This class computes the logic of a junction
21 /****************************************************************************/
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 
33 #include <string>
34 #include <vector>
35 #include <set>
36 #include <algorithm>
37 #include <bitset>
38 #include <sstream>
39 #include <map>
40 #include <cassert>
42 #include <utils/common/ToString.h>
45 #include "NBEdge.h"
46 #include "NBContHelper.h"
47 #include "NBNode.h"
48 #include "NBRequest.h"
49 
50 
51 // ===========================================================================
52 // static member variables
53 // ===========================================================================
55 int NBRequest::myNotBuild = 0;
56 
57 
58 // ===========================================================================
59 // method definitions
60 // ===========================================================================
62  NBNode* junction,
63  const EdgeVector& all,
64  const EdgeVector& incoming,
65  const EdgeVector& outgoing,
66  const NBConnectionProhibits& loadedProhibits) :
67  myJunction(junction),
68  myAll(all),
69  myIncoming(incoming),
70  myOutgoing(outgoing),
71  myCrossings(junction->getCrossings()) {
72  const int variations = numLinks();
73  // build maps with information which forbidding connection were
74  // computed and what's in there
75  myForbids.reserve(variations);
76  myDone.reserve(variations);
77  for (int i = 0; i < variations; i++) {
78  myForbids.push_back(LinkInfoCont(variations, false));
79  myDone.push_back(LinkInfoCont(variations, false));
80  }
81  // insert loaded prohibits
82  for (NBConnectionProhibits::const_iterator j = loadedProhibits.begin(); j != loadedProhibits.end(); j++) {
83  NBConnection prohibited = (*j).first;
84  bool ok1 = prohibited.check(ec);
85  if (find(myIncoming.begin(), myIncoming.end(), prohibited.getFrom()) == myIncoming.end()) {
86  ok1 = false;
87  }
88  if (find(myOutgoing.begin(), myOutgoing.end(), prohibited.getTo()) == myOutgoing.end()) {
89  ok1 = false;
90  }
91  int idx1 = 0;
92  if (ok1) {
93  idx1 = getIndex(prohibited.getFrom(), prohibited.getTo());
94  if (idx1 < 0) {
95  ok1 = false;
96  }
97  }
98  const NBConnectionVector& prohibiting = (*j).second;
99  for (NBConnectionVector::const_iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
100  NBConnection sprohibiting = *k;
101  bool ok2 = sprohibiting.check(ec);
102  if (find(myIncoming.begin(), myIncoming.end(), sprohibiting.getFrom()) == myIncoming.end()) {
103  ok2 = false;
104  }
105  if (find(myOutgoing.begin(), myOutgoing.end(), sprohibiting.getTo()) == myOutgoing.end()) {
106  ok2 = false;
107  }
108  if (ok1 && ok2) {
109  int idx2 = getIndex(sprohibiting.getFrom(), sprohibiting.getTo());
110  if (idx2 < 0) {
111  ok2 = false;
112  } else {
113  myForbids[idx2][idx1] = true;
114  myDone[idx2][idx1] = true;
115  myDone[idx1][idx2] = true;
116  myGoodBuilds++;
117  }
118  } else {
119  std::string pfID = prohibited.getFrom() != 0 ? prohibited.getFrom()->getID() : "UNKNOWN";
120  std::string ptID = prohibited.getTo() != 0 ? prohibited.getTo()->getID() : "UNKNOWN";
121  std::string bfID = sprohibiting.getFrom() != 0 ? sprohibiting.getFrom()->getID() : "UNKNOWN";
122  std::string btID = sprohibiting.getTo() != 0 ? sprohibiting.getTo()->getID() : "UNKNOWN";
123  WRITE_WARNING("could not prohibit " + pfID + "->" + ptID + " by " + bfID + "->" + btID);
124  myNotBuild++;
125  }
126  }
127  }
128  // ok, check whether someone has prohibited two links vice versa
129  // (this happens also in some Vissim-networks, when edges are joined)
130  for (int s1 = 0; s1 < variations; s1++) {
131  for (int s2 = s1 + 1; s2 < variations; s2++) {
132  // not set, yet
133  if (!myDone[s1][s2]) {
134  continue;
135  }
136  // check whether both prohibit vice versa
137  if (myForbids[s1][s2] && myForbids[s2][s1]) {
138  // mark unset - let our algorithm fix it later
139  myDone[s1][s2] = false;
140  myDone[s2][s1] = false;
141  }
142  }
143  }
144 }
145 
146 
148 
149 
150 void
152  EdgeVector::const_iterator i, j;
153  for (i = myIncoming.begin(); i != myIncoming.end(); i++) {
154  for (j = myOutgoing.begin(); j != myOutgoing.end(); j++) {
157  }
158  }
159  // reset signalised/non-signalised dependencies
160  resetSignalised();
161  // reset foes it the number of lanes matches (or exceeds) the number of incoming connections
163 }
164 
165 
166 void
168  EdgeVector::const_iterator pfrom = find(myAll.begin(), myAll.end(), from);
169  while (*pfrom != to) {
171  if ((*pfrom)->getToNode() == myJunction) {
172  EdgeVector::const_iterator pto = find(myAll.begin(), myAll.end(), to);
173  while (*pto != from) {
174  if (!((*pto)->getToNode() == myJunction)) {
175  setBlocking(from, to, *pfrom, *pto);
176  }
178  }
179  }
180  }
181 }
182 
183 
184 void
186  EdgeVector::const_iterator pfrom = find(myAll.begin(), myAll.end(), from);
187  while (*pfrom != to) {
188  NBContHelper::nextCW(myAll, pfrom);
189  if ((*pfrom)->getToNode() == myJunction) {
190  EdgeVector::const_iterator pto = find(myAll.begin(), myAll.end(), to);
191  while (*pto != from) {
192  if (!((*pto)->getToNode() == myJunction)) {
193  setBlocking(from, to, *pfrom, *pto);
194  }
196  }
197  }
198  }
199 }
200 
201 
202 void
204  NBEdge* from2, NBEdge* to2) {
205  // check whether one of the links has a dead end
206  if (to1 == 0 || to2 == 0) {
207  return;
208  }
209  // get the indices of both links
210  int idx1 = getIndex(from1, to1);
211  int idx2 = getIndex(from2, to2);
212  if (idx1 < 0 || idx2 < 0) {
213  return; // !!! error output? did not happend, yet
214  }
215  // check whether the link crossing has already been checked
216  assert(idx1 < (int)(myIncoming.size() * myOutgoing.size()));
217  if (myDone[idx1][idx2]) {
218  return;
219  }
220  // mark the crossings as done
221  myDone[idx1][idx2] = true;
222  myDone[idx2][idx1] = true;
223  // special case all-way stop
225  // all ways forbid each other. Conflict resolution happens via arrival time
226  myForbids[idx1][idx2] = true;
227  myForbids[idx2][idx1] = true;
228  return;
229  }
230  // check if one of the links is a turn; this link is always not priorised
231  // true for right-before-left and priority
232  if (from1->isTurningDirectionAt(to1)) {
233  myForbids[idx2][idx1] = true;
234  return;
235  }
236  if (from2->isTurningDirectionAt(to2)) {
237  myForbids[idx1][idx2] = true;
238  return;
239  }
240  // check the priorities if required by node type
242  int from1p = from1->getJunctionPriority(myJunction);
243  int from2p = from2->getJunctionPriority(myJunction);
244  // check if one of the connections is higher priorised when incoming into
245  // the junction, the connection road will yield
246  if (from1p > from2p) {
247  myForbids[idx1][idx2] = true;
248  return;
249  }
250  if (from2p > from1p) {
251  myForbids[idx2][idx1] = true;
252  return;
253  }
254  }
255 
256  // check whether one of the connections is higher priorised on
257  // the outgoing edge when both roads are high priorised
258  // the connection with the lower priorised outgoing edge will lead
259  // should be valid for priority junctions only
260  /*
261  if (from1p > 0 && from2p > 0) {
262  assert(myJunction->getType() != NODETYPE_RIGHT_BEFORE_LEFT);
263  int to1p = to1->getJunctionPriority(myJunction);
264  int to2p = to2->getJunctionPriority(myJunction);
265  if (to1p > to2p) {
266  myForbids[idx1][idx2] = true;
267  return;
268  }
269  if (to2p > to1p) {
270  myForbids[idx2][idx1] = true;
271  return;
272  }
273  }
274  */
275 
276  // compute the yielding due to the right-before-left rule
277  // get the position of the incoming lanes in the junction-wheel
278  EdgeVector::const_iterator c1 = find(myAll.begin(), myAll.end(), from1);
280  // go through next edges clockwise...
281  while (*c1 != from1 && *c1 != from2) {
282  if (*c1 == to2) {
283  // if we encounter to2 the second one prohibits the first
284  myForbids[idx2][idx1] = true;
285  return;
286  }
288  }
289  // get the position of the incoming lanes in the junction-wheel
290  EdgeVector::const_iterator c2 = find(myAll.begin(), myAll.end(), from2);
292  // go through next edges clockwise...
293  while (*c2 != from2 && *c2 != from1) {
294  if (*c2 == to1) {
295  // if we encounter to1 the second one prohibits the first
296  myForbids[idx1][idx2] = true;
297  return;
298  }
300  }
301 }
302 
303 
304 int
306  EdgeVector::const_iterator p = find(myAll.begin(), myAll.end(), from);
307  int ret = 0;
308  do {
309  ret++;
310  if (p == myAll.begin()) {
311  p = myAll.end();
312  }
313  p--;
314  } while (*p != to);
315  return ret;
316 }
317 
318 
319 void
320 NBRequest::writeLogic(std::string /* key */, OutputDevice& into, const bool checkLaneFoes) const {
321  int pos = 0;
322  EdgeVector::const_iterator i;
323  // normal connections
324  for (i = myIncoming.begin(); i != myIncoming.end(); i++) {
325  int noLanes = (*i)->getNumLanes();
326  for (int k = 0; k < noLanes; k++) {
327  pos = writeLaneResponse(into, *i, k, pos, checkLaneFoes);
328  }
329  }
330  // crossings
331  for (auto c : myCrossings) {
332  pos = writeCrossingResponse(into, *c, pos);
333  }
334 }
335 
336 
337 void
339  // go through possible prohibitions
340  for (EdgeVector::const_iterator i11 = myIncoming.begin(); i11 != myIncoming.end(); i11++) {
341  int noLanesEdge1 = (*i11)->getNumLanes();
342  for (int j1 = 0; j1 < noLanesEdge1; j1++) {
343  std::vector<NBEdge::Connection> el1 = (*i11)->getConnectionsFromLane(j1);
344  for (std::vector<NBEdge::Connection>::iterator i12 = el1.begin(); i12 != el1.end(); ++i12) {
345  int idx1 = getIndex((*i11), (*i12).toEdge);
346  if (idx1 < 0) {
347  continue;
348  }
349  // go through possibly prohibited
350  for (EdgeVector::const_iterator i21 = myIncoming.begin(); i21 != myIncoming.end(); i21++) {
351  int noLanesEdge2 = (*i21)->getNumLanes();
352  for (int j2 = 0; j2 < noLanesEdge2; j2++) {
353  std::vector<NBEdge::Connection> el2 = (*i21)->getConnectionsFromLane(j2);
354  for (std::vector<NBEdge::Connection>::iterator i22 = el2.begin(); i22 != el2.end(); i22++) {
355  int idx2 = getIndex((*i21), (*i22).toEdge);
356  if (idx2 < 0) {
357  continue;
358  }
359  // check
360  // same incoming connections do not prohibit each other
361  if ((*i11) == (*i21)) {
362  myForbids[idx1][idx2] = false;
363  myForbids[idx2][idx1] = false;
364  continue;
365  }
366  // check other
367  // if both are non-signalised or both are signalised
368  if (((*i12).tlID == "" && (*i22).tlID == "")
369  ||
370  ((*i12).tlID != "" && (*i22).tlID != "")) {
371  // do nothing
372  continue;
373  }
374  // supposing, we don not have to
375  // brake if we are no foes
376  if (!foes(*i11, (*i12).toEdge, *i21, (*i22).toEdge)) {
377  continue;
378  }
379  // otherwise:
380  // the non-signalised must break
381  if ((*i12).tlID != "") {
382  myForbids[idx1][idx2] = true;
383  myForbids[idx2][idx1] = false;
384  } else {
385  myForbids[idx1][idx2] = false;
386  myForbids[idx2][idx1] = true;
387  }
388  }
389  }
390  }
391  }
392  }
393  }
394 }
395 
396 
397 std::pair<int, int>
399  int noLanes = 0;
400  int noLinks = 0;
401  for (EdgeVector::const_iterator i = myIncoming.begin();
402  i != myIncoming.end(); i++) {
403  int noLanesEdge = (*i)->getNumLanes();
404  for (int j = 0; j < noLanesEdge; j++) {
405  int numConnections = (int)(*i)->getConnectionsFromLane(j).size();
406  noLinks += numConnections;
407  if (numConnections > 0) {
408  noLanes++;
409  }
410  }
411  }
412  return std::make_pair(noLanes, noLinks);
413 }
414 
415 
416 bool
417 NBRequest::foes(const NBEdge* const from1, const NBEdge* const to1,
418  const NBEdge* const from2, const NBEdge* const to2) const {
419  // unconnected edges do not forbid other edges
420  if (to1 == 0 || to2 == 0) {
421  return false;
422  }
423  // get the indices
424  int idx1 = getIndex(from1, to1);
425  int idx2 = getIndex(from2, to2);
426  if (idx1 < 0 || idx2 < 0) {
427  return false; // sure? (The connection does not exist within this junction)
428  }
429  assert(idx1 < (int)(myIncoming.size() * myOutgoing.size()));
430  assert(idx2 < (int)(myIncoming.size()*myOutgoing.size()));
431  return myForbids[idx1][idx2] || myForbids[idx2][idx1];
432 }
433 
434 
435 bool
436 NBRequest::forbids(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
437  const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo,
438  bool regardNonSignalisedLowerPriority) const {
439  // unconnected edges do not forbid other edges
440  if (possProhibitorTo == 0 || possProhibitedTo == 0) {
441  return false;
442  }
443  // get the indices
444  int possProhibitorIdx = getIndex(possProhibitorFrom, possProhibitorTo);
445  int possProhibitedIdx = getIndex(possProhibitedFrom, possProhibitedTo);
446  if (possProhibitorIdx < 0 || possProhibitedIdx < 0) {
447  return false; // sure? (The connection does not exist within this junction)
448  }
449  assert(possProhibitorIdx < (int)(myIncoming.size() * myOutgoing.size()));
450  assert(possProhibitedIdx < (int)(myIncoming.size() * myOutgoing.size()));
451  // check simple right-of-way-rules
452  if (!regardNonSignalisedLowerPriority) {
453  return myForbids[possProhibitorIdx][possProhibitedIdx];
454  }
455  // if its not forbidden, report
456  if (!myForbids[possProhibitorIdx][possProhibitedIdx]) {
457  return false;
458  }
459  // do not forbid a signalised stream by a non-signalised
460  if (!possProhibitorFrom->hasSignalisedConnectionTo(possProhibitorTo)) {
461  return false;
462  }
463  return true;
464 }
465 
466 
467 int
469  int fromLane, int pos, const bool checkLaneFoes) const {
470  std::vector<NBEdge::Connection> connected = from->getConnectionsFromLane(fromLane);
471  for (std::vector<NBEdge::Connection>::iterator j = connected.begin(); j != connected.end(); j++) {
472  assert((*j).toEdge != 0);
474  od.writeAttr(SUMO_ATTR_INDEX, pos++);
475  const std::string foes = getFoesString(from, (*j).toEdge, fromLane, (*j).toLane, checkLaneFoes);
476  const std::string response = (myJunction->getType() == NODETYPE_ZIPPER ? foes
477  : getResponseString((*j).tlLinkNo, from, (*j).toEdge, fromLane, (*j).toLane, (*j).mayDefinitelyPass, checkLaneFoes));
478  od.writeAttr(SUMO_ATTR_RESPONSE, response);
479  od.writeAttr(SUMO_ATTR_FOES, foes);
480  if (!OptionsCont::getOptions().getBool("no-internal-links")) {
481  od.writeAttr(SUMO_ATTR_CONT, j->haveVia);
482  }
483  od.closeTag();
484  }
485  return pos;
486 }
487 
488 
489 int
490 NBRequest::writeCrossingResponse(OutputDevice& od, const NBNode::Crossing& crossing, int pos) const {
491  std::string foes(myCrossings.size(), '0');
492  std::string response(myCrossings.size(), '0');
493  // conflicts with normal connections
494  for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
495  //const std::vector<NBEdge::Connection> &allConnections = (*i)->getConnections();
496  const NBEdge* from = *i;
497  int noLanes = from->getNumLanes();
498  for (int j = noLanes; j-- > 0;) {
499  std::vector<NBEdge::Connection> connected = from->getConnectionsFromLane(j);
500  int size = (int) connected.size();
501  for (int k = size; k-- > 0;) {
502  const NBEdge* to = connected[k].toEdge;
503  bool foe = false;
504  for (EdgeVector::const_iterator it_e = crossing.edges.begin(); it_e != crossing.edges.end(); ++it_e) {
505  if ((*it_e) == from || (*it_e) == to) {
506  foe = true;
507  break;
508  }
509  }
510  foes += foe ? '1' : '0';
511  response += mustBrakeForCrossing(myJunction, from, to, crossing) || !foe ? '0' : '1';
512  }
513  }
514  }
516  od.writeAttr(SUMO_ATTR_INDEX, pos++);
517  od.writeAttr(SUMO_ATTR_RESPONSE, response);
519  od.writeAttr(SUMO_ATTR_CONT, false);
520  od.closeTag();
521  return pos;
522 }
523 
524 
525 std::string
526 NBRequest::getResponseString(int tlIndex, const NBEdge* const from, const NBEdge* const to,
527  int fromLane, int toLane, bool mayDefinitelyPass, const bool checkLaneFoes) const {
528  const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
529  int idx = 0;
530  if (to != 0) {
531  idx = getIndex(from, to);
532  }
533  std::string result;
534  // crossings
535  for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = myCrossings.rbegin(); i != myCrossings.rend(); i++) {
536  result += mustBrakeForCrossing(myJunction, from, to, **i) ? '1' : '0';
537  }
538  NBEdge::Connection queryCon = from->getConnection(fromLane, to, toLane);
539  // normal connections
540  for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
541  //const std::vector<NBEdge::Connection> &allConnections = (*i)->getConnections();
542  int noLanes = (*i)->getNumLanes();
543  for (int j = noLanes; j-- > 0;) {
544  std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
545  int size = (int) connected.size();
546  for (int k = size; k-- > 0;) {
547  if (mayDefinitelyPass) {
548  result += '0';
549  } else if ((*i) == from && fromLane == j) {
550  // do not prohibit a connection by others from same lane
551  result += '0';
552  } else {
553  assert(k < (int) connected.size());
554  assert(idx < (int)(myIncoming.size() * myOutgoing.size()));
555  assert(connected[k].toEdge != 0);
556  assert(getIndex(*i, connected[k].toEdge) < (int)(myIncoming.size() * myOutgoing.size()));
557  // check whether the connection is prohibited by another one
558  if ((myForbids[getIndex(*i, connected[k].toEdge)][idx] &&
559  (!checkLaneFoes || laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane)))
560  || NBNode::rightTurnConflict(from, to, fromLane, *i, connected[k].toEdge, connected[k].fromLane, lefthand)
561  || mergeConflict(from, queryCon, *i, connected[k], false)
562  || myJunction->rightOnRedConflict(tlIndex, connected[k].tlLinkNo)
563  ) {
564  result += '1';
565  } else {
566  result += '0';
567  }
568  }
569  }
570  }
571  }
572  return result;
573 }
574 
575 
576 std::string
577 NBRequest::getFoesString(NBEdge* from, NBEdge* to, int fromLane, int toLane, const bool checkLaneFoes) const {
578  // remember the case when the lane is a "dead end" in the meaning that
579  // vehicles must choose another lane to move over the following
580  // junction
581  // !!! move to forbidden
582  std::string result;
583  // crossings
584  for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = myCrossings.rbegin(); i != myCrossings.rend(); i++) {
585  bool foes = false;
586  for (EdgeVector::const_iterator it_e = (**i).edges.begin(); it_e != (**i).edges.end(); ++it_e) {
587  if ((*it_e) == from || (*it_e) == to) {
588  foes = true;
589  break;
590  }
591  }
592  result += foes ? '1' : '0';
593  }
594  NBEdge::Connection queryCon = from->getConnection(fromLane, to, toLane);
595  // normal connections
596  for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin();
597  i != myIncoming.rend(); i++) {
598 
599  for (int j = (int)(*i)->getNumLanes() - 1; j >= 0; --j) {
600  std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
601  int size = (int) connected.size();
602  for (int k = size; k-- > 0;) {
603  if ((foes(from, to, (*i), connected[k].toEdge) &&
604  (!checkLaneFoes || laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane)))
605  || NBNode::rightTurnConflict(from, to, fromLane, *i, connected[k].toEdge, connected[k].fromLane)
606  || mergeConflict(from, queryCon, *i, connected[k], true)) {
607  result += '1';
608  } else {
609  result += '0';
610  }
611  }
612  }
613  }
614  return result;
615 }
616 
617 
618 bool
620  const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) {
621  return (from == prohibitorFrom
622  && con.toEdge == prohibitorCon.toEdge
623  && con.toLane == prohibitorCon.toLane
624  && con.fromLane != prohibitorCon.fromLane
625  && (foes ||
626  // merging bicycles should yield
627  ((((con.fromLane > prohibitorCon.fromLane && prohibitorFrom->getPermissions(prohibitorCon.fromLane) != SVC_BICYCLE)
628  || (con.fromLane < prohibitorCon.fromLane && from->getPermissions(con.fromLane) == SVC_BICYCLE)
629  ) && !con.mayDefinitelyPass)
630  || prohibitorCon.mayDefinitelyPass)));
631 }
632 
633 
634 bool
635 NBRequest::laneConflict(const NBEdge* from, const NBEdge* to, int toLane,
636  const NBEdge* prohibitorFrom, const NBEdge* prohibitorTo, int prohibitorToLane) const {
637  if (to != prohibitorTo) {
638  return true;
639  }
640  // since we know that the edge2edge connections are in conflict, the only
641  // situation in which the lane2lane connections can be conflict-free is, if
642  // they target the same edge but do not cross each other
643  double angle = NBHelpers::relAngle(
644  from->getAngleAtNode(from->getToNode()), to->getAngleAtNode(to->getFromNode()));
645  if (angle == 180) {
646  angle = -180; // turnarounds are left turns
647  }
648  const double prohibitorAngle = NBHelpers::relAngle(
649  prohibitorFrom->getAngleAtNode(prohibitorFrom->getToNode()), to->getAngleAtNode(to->getFromNode()));
650  const bool rightOfProhibitor = prohibitorFrom->isTurningDirectionAt(to)
651  || (angle > prohibitorAngle && !from->isTurningDirectionAt(to));
652  return rightOfProhibitor ? toLane >= prohibitorToLane : toLane <= prohibitorToLane;
653 }
654 
655 
656 int
657 NBRequest::getIndex(const NBEdge* const from, const NBEdge* const to) const {
658  EdgeVector::const_iterator fp = find(myIncoming.begin(), myIncoming.end(), from);
659  EdgeVector::const_iterator tp = find(myOutgoing.begin(), myOutgoing.end(), to);
660  if (fp == myIncoming.end() || tp == myOutgoing.end()) {
661  return -1;
662  }
663  // compute the index
664  return (int)(distance(myIncoming.begin(), fp) * myOutgoing.size() + distance(myOutgoing.begin(), tp));
665 }
666 
667 
668 std::ostream&
669 operator<<(std::ostream& os, const NBRequest& r) {
670  int variations = r.numLinks();
671  for (int i = 0; i < variations; i++) {
672  os << i << ' ';
673  for (int j = 0; j < variations; j++) {
674  if (r.myForbids[i][j]) {
675  os << '1';
676  } else {
677  os << '0';
678  }
679  }
680  os << std::endl;
681  }
682  os << std::endl;
683  return os;
684 }
685 
686 
687 bool
688 NBRequest::mustBrake(const NBEdge* const from, const NBEdge* const to, int fromLane, int toLane, bool includePedCrossings) const {
689  // vehicles which do not have a following lane must always decelerate to the end
690  if (to == 0) {
691  return true;
692  }
693  // get the indices
694  int idx2 = getIndex(from, to);
695  if (idx2 == -1) {
696  return false;
697  }
698  // go through all (existing) connections;
699  // check whether any of these forbids the one to determine
700  assert(idx2 < (int)(myIncoming.size()*myOutgoing.size()));
701  for (int idx1 = 0; idx1 < numLinks(); idx1++) {
702  //assert(myDone[idx1][idx2]);
703  if (myDone[idx1][idx2] && myForbids[idx1][idx2]) {
704  return true;
705  }
706  }
707  // maybe we need to brake for a pedestrian crossing
708  if (includePedCrossings) {
709  for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = myCrossings.rbegin(); i != myCrossings.rend(); i++) {
710  if (mustBrakeForCrossing(myJunction, from, to, **i)) {
711  return true;
712  }
713  }
714  }
715  // maybe we need to brake due to a right-turn conflict with straight-going
716  // bicycles
717  LinkDirection dir = myJunction->getDirection(from, to);
718  if (dir == LINKDIR_RIGHT || dir == LINKDIR_PARTRIGHT) {
719  const std::vector<NBEdge::Connection>& cons = from->getConnections();
720  for (std::vector<NBEdge::Connection>::const_iterator i = cons.begin(); i != cons.end(); i++) {
721  if (NBNode::rightTurnConflict(from, to, fromLane,
722  from, (*i).toEdge, (*i).fromLane)) {
723  return true;
724  }
725  }
726  }
727  // maybe we need to brake due to a merge conflict
728  NBEdge::Connection queryCon = from->getConnection(fromLane, to, toLane);
729  for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
730  int noLanes = (*i)->getNumLanes();
731  for (int j = noLanes; j-- > 0;) {
732  std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
733  const int size = (int) connected.size();
734  for (int k = size; k-- > 0;) {
735  if ((*i) == from && fromLane != j
736  && mergeConflict(from, queryCon, *i, connected[k], myJunction->getType() == NODETYPE_ZIPPER)) {
737  return true;
738  }
739  }
740  }
741  }
742 
743  return false;
744 }
745 
746 bool
747 NBRequest::mustBrakeForCrossing(const NBNode* node, const NBEdge* const from, const NBEdge* const to, const NBNode::Crossing& crossing) {
748  const LinkDirection dir = node->getDirection(from, to);
749  const bool mustYield = dir == LINKDIR_LEFT || dir == LINKDIR_RIGHT;
750  if (crossing.priority || mustYield) {
751  for (EdgeVector::const_iterator it_e = crossing.edges.begin(); it_e != crossing.edges.end(); ++it_e) {
752  // left and right turns must yield to unprioritized crossings only on their destination edge
753  if (((*it_e) == from && crossing.priority) || (*it_e) == to) {
754  return true;
755  }
756  }
757  }
758  return false;
759 }
760 
761 
762 bool
763 NBRequest::mustBrake(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
764  const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo) const {
765  // get the indices
766  int idx1 = getIndex(possProhibitorFrom, possProhibitorTo);
767  int idx2 = getIndex(possProhibitedFrom, possProhibitedTo);
768  return (myForbids[idx2][idx1]);
769 }
770 
771 
772 void
774  // check if any errors occured on build the link prohibitions
775  if (myNotBuild != 0) {
776  WRITE_WARNING(toString(myNotBuild) + " of " + toString(myNotBuild + myGoodBuilds) + " prohibitions were not build.");
777  }
778 }
779 
780 
781 void
783  // map from edge to number of incoming connections
784  std::map<NBEdge*, int> incomingCount; // initialized to 0
785  // map from edge to indices of approached lanes
786  std::map<NBEdge*, std::set<int> > approachedLanes;
787  // map from edge to list of incoming edges
788  std::map<NBEdge*, EdgeVector> incomingEdges;
789  for (EdgeVector::const_iterator it_e = myIncoming.begin(); it_e != myIncoming.end(); it_e++) {
790  const std::vector<NBEdge::Connection> connections = (*it_e)->getConnections();
791  for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); ++it_c) {
792  incomingCount[it_c->toEdge]++;
793  approachedLanes[it_c->toEdge].insert(it_c->toLane);
794  incomingEdges[it_c->toEdge].push_back(*it_e);
795  }
796  }
797  for (std::map<NBEdge*, int>::iterator it = incomingCount.begin(); it != incomingCount.end(); ++it) {
798  NBEdge* to = it->first;
799  // we cannot test against to->getNumLanes() since not all lanes may be used
800  if ((int)approachedLanes[to].size() >= it->second) {
801  EdgeVector& incoming = incomingEdges[to];
802  // make these connections mutually unconflicting
803  for (EdgeVector::iterator it_e1 = incoming.begin(); it_e1 != incoming.end(); ++it_e1) {
804  for (EdgeVector::iterator it_e2 = incoming.begin(); it_e2 != incoming.end(); ++it_e2) {
805  myForbids[getIndex(*it_e1, to)][getIndex(*it_e2, to)] = false;
806  }
807  }
808  }
809  }
810 }
811 
812 
813 int
815  return (int)(myIncoming.size() * myOutgoing.size() + myCrossings.size());
816 }
817 
818 /****************************************************************************/
819 
static double relAngle(double angle1, double angle2)
computes the relative angle between the two angles
Definition: NBHelpers.cpp:53
std::pair< int, int > getSizes() const
returns the number of the junction&#39;s lanes and the number of the junction&#39;s links in respect...
Definition: NBRequest.cpp:398
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:260
void computeLeftOutgoingLinkCrossings(NBEdge *from, NBEdge *to)
Definition: NBRequest.cpp:185
bool check(const NBEdgeCont &ec)
checks whether the edges are still valid
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:161
int toLane
The lane the connections yields in.
Definition: NBEdge.h:189
std::vector< bool > LinkInfoCont
Definition: NBRequest.h:255
static int myNotBuild
Definition: NBRequest.h:271
NBEdge * toEdge
The edge the connections yields in.
Definition: NBEdge.h:186
bool hasSignalisedConnectionTo(const NBEdge *const e) const
Check if edge has signalised connections.
Definition: NBEdge.cpp:2763
NBRequest(const NBEdgeCont &ec, NBNode *junction, const EdgeVector &all, const EdgeVector &incoming, const EdgeVector &outgoing, const NBConnectionProhibits &loadedProhibits)
Definition: NBRequest.cpp:61
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
Definition: NBEdge.cpp:1591
vehicle is a bicycle
The representation of a single edge during network building.
Definition: NBEdge.h:70
NBNode * myJunction
the node the request is assigned to
Definition: NBRequest.h:239
static int myGoodBuilds
Definition: NBRequest.h:271
void buildBitfieldLogic()
Definition: NBRequest.cpp:151
const EdgeVector & myOutgoing
Definition: NBRequest.h:248
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:2801
static bool mergeConflict(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon, bool foes)
whether multple connections from the same edge target the same lane
Definition: NBRequest.cpp:619
bool mayDefinitelyPass
Information about being definitely free to drive (on-ramps)
Definition: NBEdge.h:198
NBEdge * getFrom() const
returns the from-edge (start of the connection)
void setBlocking(NBEdge *from1, NBEdge *to1, NBEdge *from2, NBEdge *to2)
Definition: NBRequest.cpp:203
static void nextCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const std::string & getID() const
Returns the id.
Definition: Named.h:74
The link is a (hard) left direction.
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:199
const EdgeVector & myIncoming
Definition: NBRequest.h:245
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:64
int numLinks() const
return to total number of edge-to-edge connections of this request-logic
Definition: NBRequest.cpp:814
static bool rightTurnConflict(const NBEdge *from, const NBEdge *to, int fromLane, const NBEdge *prohibitorFrom, const NBEdge *prohibitorTo, int prohibitorFromLane, bool lefthand=false)
return whether the given laneToLane connection is a right turn which must yield to a bicycle crossing...
Definition: NBNode.cpp:1375
CombinationsCont myDone
Definition: NBRequest.h:268
bool priority
whether the pedestrians have priority
Definition: NBNode.h:151
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)...
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:657
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:763
static void reportWarnings()
reports warnings if any occured
Definition: NBRequest.cpp:773
std::vector< Connection > getConnectionsFromLane(int lane) const
Returns connections from a given lane.
Definition: NBEdge.cpp:1037
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:747
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:55
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:436
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:412
int fromLane
The lane the connections starts at.
Definition: NBEdge.h:183
std::vector< NBNode::Crossing * > myCrossings
Definition: NBRequest.h:251
void computeRightOutgoingLinkCrossings(NBEdge *from, NBEdge *to)
Definition: NBRequest.cpp:167
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:66
std::string getResponseString(int tlIndex, const NBEdge *const from, const NBEdge *const to, int fromLane, int toLane, bool mayDefinitelyPass, const bool checkLaneFoes) const
Writes the response of a certain link.
Definition: NBRequest.cpp:526
The link is a (hard) right direction.
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge&#39;s geometry at the given node.
Definition: NBEdge.cpp:1611
int writeCrossingResponse(OutputDevice &od, const NBNode::Crossing &crossing, int pos) const
writes the response of a certain crossing Returns the next link index within the junction ...
Definition: NBRequest.cpp:490
The link is a partial right direction.
description of a logic request within the junction
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:3025
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:417
const EdgeVector & myAll
Definition: NBRequest.h:242
std::vector< NBConnection > NBConnectionVector
Definition of a connection vector.
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing, bool leftHand=false) const
Returns the representation of the described stream&#39;s direction.
Definition: NBNode.cpp:1539
NBEdge * getTo() const
returns the to-edge (end of the connection)
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:635
Connection getConnection(int fromLane, const NBEdge *to, int toLane) const
Returns the specified connection This method goes through "myConnections" and returns the specified o...
Definition: NBEdge.cpp:1049
std::map< NBConnection, NBConnectionVector > NBConnectionProhibits
Definition of a container for connection block dependencies Includes a list of all connections which ...
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:845
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:40
void writeLogic(std::string key, OutputDevice &into, const bool checkLaneFoes) const
Definition: NBRequest.cpp:320
friend std::ostream & operator<<(std::ostream &os, const NBRequest &r)
prints the request
Definition: NBRequest.cpp:669
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:266
int writeLaneResponse(OutputDevice &od, NBEdge *from, int lane, int pos, const bool checkLaneFoes) const
writes the response of a certain lane Returns the next link index within the junction ...
Definition: NBRequest.cpp:468
std::string getFoesString(NBEdge *from, NBEdge *to, int fromLane, int toLane, const bool checkLaneFoes) const
Definition: NBRequest.cpp:577
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:2450
EdgeVector edges
The edges being crossed.
Definition: NBNode.h:137
Represents a single node (junction) during network building.
Definition: NBNode.h:74
A definition of a pedestrian crossing.
Definition: NBNode.h:131
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:70
bool closeTag()
Closes the most recently opened tag.
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:426
int distanceCounterClockwise(NBEdge *from, NBEdge *to)
Definition: NBRequest.cpp:305
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:433
void resetCooperating()
reset foes it the number of lanes matches (or exceeds) the number of incoming connections for an edge...
Definition: NBRequest.cpp:782
static void nextCCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
CombinationsCont myForbids
Definition: NBRequest.h:265
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
void resetSignalised()
Definition: NBRequest.cpp:338