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