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