SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules 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-2016 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 // ===========================================================================
60 int 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 int 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 (int 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 (int s1 = 0; s1 < variations; s1++) {
136  for (int 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(idx1 < (int)(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 int
311  EdgeVector::const_iterator p = find(myAll.begin(), myAll.end(), from);
312  int 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  int noLanes = (*i)->getNumLanes();
331  for (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  int noLanesEdge1 = (*i11)->getNumLanes();
347  for (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  int noLanesEdge2 = (*i21)->getNumLanes();
357  for (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<int, int>
404  int noLanes = 0;
405  int noLinks = 0;
406  for (EdgeVector::const_iterator i = myIncoming.begin();
407  i != myIncoming.end(); i++) {
408  int noLanesEdge = (*i)->getNumLanes();
409  for (int j = 0; j < noLanesEdge; j++) {
410  int numConnections = (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(idx1 < (int)(myIncoming.size() * myOutgoing.size()));
435  assert(idx2 < (int)(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(possProhibitorIdx < (int)(myIncoming.size() * myOutgoing.size()));
455  assert(possProhibitedIdx < (int)(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  const std::string foes = getFoesString(from, (*j).toEdge, fromLane, (*j).toLane, checkLaneFoes);
481  const std::string response = (myJunction->getType() == NODETYPE_ZIPPER ? foes
482  : getResponseString((*j).tlLinkNo, from, (*j).toEdge, fromLane, (*j).toLane, (*j).mayDefinitelyPass, checkLaneFoes));
483  od.writeAttr(SUMO_ATTR_RESPONSE, response);
484  od.writeAttr(SUMO_ATTR_FOES, foes);
485  if (!OptionsCont::getOptions().getBool("no-internal-links")) {
486  od.writeAttr(SUMO_ATTR_CONT, j->haveVia);
487  }
488  od.closeTag();
489  }
490  return pos;
491 }
492 
493 
494 int
495 NBRequest::writeCrossingResponse(OutputDevice& od, const NBNode::Crossing& crossing, int pos) const {
496  std::string foes(myCrossings.size(), '0');
497  std::string response(myCrossings.size(), '0');
498  // conflicts with normal connections
499  for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
500  //const std::vector<NBEdge::Connection> &allConnections = (*i)->getConnections();
501  const NBEdge* from = *i;
502  int noLanes = from->getNumLanes();
503  for (int j = noLanes; j-- > 0;) {
504  std::vector<NBEdge::Connection> connected = from->getConnectionsFromLane(j);
505  int size = (int) connected.size();
506  for (int k = size; k-- > 0;) {
507  const NBEdge* to = connected[k].toEdge;
508  bool foe = false;
509  for (EdgeVector::const_iterator it_e = crossing.edges.begin(); it_e != crossing.edges.end(); ++it_e) {
510  if ((*it_e) == from || (*it_e) == to) {
511  foe = true;
512  break;
513  }
514  }
515  foes += foe ? '1' : '0';
516  response += mustBrakeForCrossing(myJunction, from, to, crossing) || !foe ? '0' : '1';
517  }
518  }
519  }
521  od.writeAttr(SUMO_ATTR_INDEX, pos++);
522  od.writeAttr(SUMO_ATTR_RESPONSE, response);
524  od.writeAttr(SUMO_ATTR_CONT, false);
525  od.closeTag();
526  return pos;
527 }
528 
529 
530 std::string
531 NBRequest::getResponseString(int tlIndex, const NBEdge* const from, const NBEdge* const to,
532  int fromLane, int toLane, bool mayDefinitelyPass, const bool checkLaneFoes) const {
533  const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
534  int idx = 0;
535  if (to != 0) {
536  idx = getIndex(from, to);
537  }
538  std::string result;
539  // crossings
540  for (std::vector<NBNode::Crossing>::const_reverse_iterator i = myCrossings.rbegin(); i != myCrossings.rend(); i++) {
541  result += mustBrakeForCrossing(myJunction, from, to, *i) ? '1' : '0';
542  }
543  NBEdge::Connection queryCon = from->getConnection(fromLane, to, toLane);
544  // normal connections
545  for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
546  //const std::vector<NBEdge::Connection> &allConnections = (*i)->getConnections();
547  int noLanes = (*i)->getNumLanes();
548  for (int j = noLanes; j-- > 0;) {
549  std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
550  int size = (int) connected.size();
551  for (int k = size; k-- > 0;) {
552  if (mayDefinitelyPass) {
553  result += '0';
554  } else if ((*i) == from && fromLane == j) {
555  // do not prohibit a connection by others from same lane
556  result += '0';
557  } else {
558  assert(k < (int) connected.size());
559  assert(idx < (int)(myIncoming.size() * myOutgoing.size()));
560  assert(connected[k].toEdge != 0);
561  assert(getIndex(*i, connected[k].toEdge) < (int)(myIncoming.size() * myOutgoing.size()));
562  // check whether the connection is prohibited by another one
563  if ((myForbids[getIndex(*i, connected[k].toEdge)][idx] &&
564  (!checkLaneFoes || laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane)))
565  || NBNode::rightTurnConflict(from, to, fromLane, *i, connected[k].toEdge, connected[k].fromLane, lefthand)
566  || mergeConflict(from, queryCon, *i, connected[k], false)
567  || myJunction->rightOnRedConflict(tlIndex, connected[k].tlLinkNo)
568  ) {
569  result += '1';
570  } else {
571  result += '0';
572  }
573  }
574  }
575  }
576  }
577  return result;
578 }
579 
580 
581 std::string
582 NBRequest::getFoesString(NBEdge* from, NBEdge* to, int fromLane, int toLane, const bool checkLaneFoes) const {
583  // remember the case when the lane is a "dead end" in the meaning that
584  // vehicles must choose another lane to move over the following
585  // junction
586  // !!! move to forbidden
587  std::string result;
588  // crossings
589  for (std::vector<NBNode::Crossing>::const_reverse_iterator i = myCrossings.rbegin(); i != myCrossings.rend(); i++) {
590  bool foes = false;
591  for (EdgeVector::const_iterator it_e = (*i).edges.begin(); it_e != (*i).edges.end(); ++it_e) {
592  if ((*it_e) == from || (*it_e) == to) {
593  foes = true;
594  break;
595  }
596  }
597  result += foes ? '1' : '0';
598  }
599  NBEdge::Connection queryCon = from->getConnection(fromLane, to, toLane);
600  // normal connections
601  for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin();
602  i != myIncoming.rend(); i++) {
603 
604  for (int j = (int)(*i)->getNumLanes() - 1; j >= 0; --j) {
605  std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
606  int size = (int) connected.size();
607  for (int k = size; k-- > 0;) {
608  if ((foes(from, to, (*i), connected[k].toEdge) &&
609  (!checkLaneFoes || laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane)))
610  || NBNode::rightTurnConflict(from, to, fromLane, *i, connected[k].toEdge, connected[k].fromLane)
611  || mergeConflict(from, queryCon, *i, connected[k], true)) {
612  result += '1';
613  } else {
614  result += '0';
615  }
616  }
617  }
618  }
619  return result;
620 }
621 
622 
623 bool
625  const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) {
626  return (from == prohibitorFrom
627  && con.toEdge == prohibitorCon.toEdge
628  && con.toLane == prohibitorCon.toLane
629  && con.fromLane != prohibitorCon.fromLane
630  && (foes ||
631  // merging bicycles should yield
632  ((((con.fromLane > prohibitorCon.fromLane && prohibitorFrom->getPermissions(prohibitorCon.fromLane) != SVC_BICYCLE)
633  || (con.fromLane < prohibitorCon.fromLane && from->getPermissions(con.fromLane) == SVC_BICYCLE)
634  ) && !con.mayDefinitelyPass)
635  || prohibitorCon.mayDefinitelyPass)));
636 }
637 
638 
639 bool
640 NBRequest::laneConflict(const NBEdge* from, const NBEdge* to, int toLane,
641  const NBEdge* prohibitorFrom, const NBEdge* prohibitorTo, int prohibitorToLane) const {
642  if (to != prohibitorTo) {
643  return true;
644  }
645  // since we know that the edge2edge connections are in conflict, the only
646  // situation in which the lane2lane connections can be conflict-free is, if
647  // they target the same edge but do not cross each other
649  from->getAngleAtNode(from->getToNode()), to->getAngleAtNode(to->getFromNode()));
650  if (angle == 180) {
651  angle = -180; // turnarounds are left turns
652  }
653  const SUMOReal prohibitorAngle = NBHelpers::relAngle(
654  prohibitorFrom->getAngleAtNode(prohibitorFrom->getToNode()), to->getAngleAtNode(to->getFromNode()));
655  const bool rightOfProhibitor = prohibitorFrom->isTurningDirectionAt(to)
656  || (angle > prohibitorAngle && !from->isTurningDirectionAt(to));
657  return rightOfProhibitor ? toLane >= prohibitorToLane : toLane <= prohibitorToLane;
658 }
659 
660 
661 int
662 NBRequest::getIndex(const NBEdge* const from, const NBEdge* const to) const {
663  EdgeVector::const_iterator fp = find(myIncoming.begin(), myIncoming.end(), from);
664  EdgeVector::const_iterator tp = find(myOutgoing.begin(), myOutgoing.end(), to);
665  if (fp == myIncoming.end() || tp == myOutgoing.end()) {
666  return -1;
667  }
668  // compute the index
669  return (int)(distance(myIncoming.begin(), fp) * myOutgoing.size() + distance(myOutgoing.begin(), tp));
670 }
671 
672 
673 std::ostream&
674 operator<<(std::ostream& os, const NBRequest& r) {
675  int variations = r.numLinks();
676  for (int i = 0; i < variations; i++) {
677  os << i << ' ';
678  for (int j = 0; j < variations; j++) {
679  if (r.myForbids[i][j]) {
680  os << '1';
681  } else {
682  os << '0';
683  }
684  }
685  os << std::endl;
686  }
687  os << std::endl;
688  return os;
689 }
690 
691 
692 bool
693 NBRequest::mustBrake(const NBEdge* const from, const NBEdge* const to, int fromLane, int toLane, bool includePedCrossings) const {
694  // vehicles which do not have a following lane must always decelerate to the end
695  if (to == 0) {
696  return true;
697  }
698  // get the indices
699  int idx2 = getIndex(from, to);
700  if (idx2 == -1) {
701  return false;
702  }
703  // go through all (existing) connections;
704  // check whether any of these forbids the one to determine
705  assert(idx2 < (int)(myIncoming.size()*myOutgoing.size()));
706  for (int idx1 = 0; idx1 < numLinks(); idx1++) {
707  //assert(myDone[idx1][idx2]);
708  if (myDone[idx1][idx2] && myForbids[idx1][idx2]) {
709  return true;
710  }
711  }
712  // maybe we need to brake for a pedestrian crossing
713  if (includePedCrossings) {
714  for (std::vector<NBNode::Crossing>::const_reverse_iterator i = myCrossings.rbegin(); i != myCrossings.rend(); i++) {
715  if (mustBrakeForCrossing(myJunction, from, to, *i)) {
716  return true;
717  }
718  }
719  }
720  // maybe we need to brake due to a right-turn conflict with straight-going
721  // bicycles
722  LinkDirection dir = myJunction->getDirection(from, to);
723  if (dir == LINKDIR_RIGHT || dir == LINKDIR_PARTRIGHT) {
724  const std::vector<NBEdge::Connection>& cons = from->getConnections();
725  for (std::vector<NBEdge::Connection>::const_iterator i = cons.begin(); i != cons.end(); i++) {
726  if (NBNode::rightTurnConflict(from, to, fromLane,
727  from, (*i).toEdge, (*i).fromLane)) {
728  return true;
729  }
730  }
731  }
732  // maybe we need to brake due to a merge conflict
733  NBEdge::Connection queryCon = from->getConnection(fromLane, to, toLane);
734  for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
735  int noLanes = (*i)->getNumLanes();
736  for (int j = noLanes; j-- > 0;) {
737  std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
738  const int size = (int) connected.size();
739  for (int k = size; k-- > 0;) {
740  if ((*i) == from && fromLane != j
741  && mergeConflict(from, queryCon, *i, connected[k], myJunction->getType() == NODETYPE_ZIPPER)) {
742  return true;
743  }
744  }
745  }
746  }
747 
748  return false;
749 }
750 
751 bool
752 NBRequest::mustBrakeForCrossing(const NBNode* node, const NBEdge* const from, const NBEdge* const to, const NBNode::Crossing& crossing) {
753  const LinkDirection dir = node->getDirection(from, to);
754  const bool mustYield = dir == LINKDIR_LEFT || dir == LINKDIR_RIGHT;
755  if (crossing.priority || mustYield) {
756  for (EdgeVector::const_iterator it_e = crossing.edges.begin(); it_e != crossing.edges.end(); ++it_e) {
757  // left and right turns must yield to unprioritized crossings only on their destination edge
758  if (((*it_e) == from && crossing.priority) || (*it_e) == to) {
759  return true;
760  }
761  }
762  }
763  return false;
764 }
765 
766 
767 bool
768 NBRequest::mustBrake(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
769  const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo) const {
770  // get the indices
771  int idx1 = getIndex(possProhibitorFrom, possProhibitorTo);
772  int idx2 = getIndex(possProhibitedFrom, possProhibitedTo);
773  return (myForbids[idx2][idx1]);
774 }
775 
776 
777 void
779  // check if any errors occured on build the link prohibitions
780  if (myNotBuild != 0) {
781  WRITE_WARNING(toString(myNotBuild) + " of " + toString(myNotBuild + myGoodBuilds) + " prohibitions were not build.");
782  }
783 }
784 
785 
786 void
788  // map from edge to number of incoming connections
789  std::map<NBEdge*, int> incomingCount; // initialized to 0
790  // map from edge to indices of approached lanes
791  std::map<NBEdge*, std::set<int> > approachedLanes;
792  // map from edge to list of incoming edges
793  std::map<NBEdge*, EdgeVector> incomingEdges;
794  for (EdgeVector::const_iterator it_e = myIncoming.begin(); it_e != myIncoming.end(); it_e++) {
795  const std::vector<NBEdge::Connection> connections = (*it_e)->getConnections();
796  for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); ++it_c) {
797  incomingCount[it_c->toEdge]++;
798  approachedLanes[it_c->toEdge].insert(it_c->toLane);
799  incomingEdges[it_c->toEdge].push_back(*it_e);
800  }
801  }
802  for (std::map<NBEdge*, int>::iterator it = incomingCount.begin(); it != incomingCount.end(); ++it) {
803  NBEdge* to = it->first;
804  // we cannot test against to->getNumLanes() since not all lanes may be used
805  if ((int)approachedLanes[to].size() >= it->second) {
806  EdgeVector& incoming = incomingEdges[to];
807  // make these connections mutually unconflicting
808  for (EdgeVector::iterator it_e1 = incoming.begin(); it_e1 != incoming.end(); ++it_e1) {
809  for (EdgeVector::iterator it_e2 = incoming.begin(); it_e2 != incoming.end(); ++it_e2) {
810  myForbids[getIndex(*it_e1, to)][getIndex(*it_e2, to)] = false;
811  }
812  }
813  }
814  }
815 }
816 
817 
818 int
820  return (int)(myIncoming.size() * myOutgoing.size() + myCrossings.size());
821 }
822 
823 /****************************************************************************/
824 
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:662
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
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:157
int toLane
The lane the connections yields in.
Definition: NBEdge.h:178
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:175
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:495
NBRequest(const NBEdgeCont &ec, NBNode *junction, const EdgeVector &all, const EdgeVector &incoming, const EdgeVector &outgoing, const NBConnectionProhibits &loadedProhibits)
Definition: NBRequest.cpp:66
std::vector< Connection > getConnectionsFromLane(int lane) const
Returns connections from a given lane.
Definition: NBEdge.cpp:912
std::ostream & operator<<(std::ostream &os, const NBRequest &r)
Definition: NBRequest.cpp:674
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:441
vehicle is a bicycle
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:240
static int myGoodBuilds
Definition: NBRequest.h:272
void buildBitfieldLogic()
Definition: NBRequest.cpp:156
const EdgeVector & myOutgoing
Definition: NBRequest.h:249
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:624
bool mayDefinitelyPass
Information about being definitely free to drive (on-ramps)
Definition: NBEdge.h:187
void setBlocking(NBEdge *from1, NBEdge *to1, NBEdge *from2, NBEdge *to2)
Definition: NBRequest.cpp:208
static void nextCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
int numLinks() const
return to total number of edge-to-edge connections of this request-logic
Definition: NBRequest.cpp:819
void writeLogic(std::string key, OutputDevice &into, const bool checkLaneFoes) const
Definition: NBRequest.cpp:325
NBEdge * getFrom() const
returns the from-edge (start of the connection)
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: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:1391
CombinationsCont myDone
Definition: NBRequest.h:269
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)...
static void reportWarnings()
reports warnings if any occured
Definition: NBRequest.cpp:778
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:752
const std::string & getID() const
Returns the id.
Definition: Named.h:66
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:924
int fromLane
The lane the connections starts at.
Definition: NBEdge.h:172
std::pair< int, int > getSizes() const
returns the number of the junction's lanes and the number of the junction's links in respect...
Definition: NBRequest.cpp:403
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:768
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:640
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:265
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:395
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:2189
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:582
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:2662
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing, bool leftHand=false) const
Returns the representation of the described stream's direction.
Definition: NBNode.cpp:1555
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:55
The link is a partial right direction.
const EdgeVector & myAll
Definition: NBRequest.h:243
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:1429
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:2726
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:416
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:531
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:252
EdgeVector edges
The edges being crossed.
Definition: NBNode.h:139
Represents a single node (junction) during network building.
Definition: NBNode.h:74
bool hasSignalisedConnectionTo(const NBEdge *const e) const
Check if edge has signalised connections.
Definition: NBEdge.cpp:2479
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:132
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:214
static SUMOReal relAngle(SUMOReal angle1, SUMOReal angle2)
Definition: NBHelpers.cpp:56
int distanceCounterClockwise(NBEdge *from, NBEdge *to)
Definition: NBRequest.cpp:310
Information whether the detector shall be continued on the folowing lanes.
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:803
void resetCooperating()
reset foes it the number of lanes matches (or exceeds) the number of incoming connections for an edge...
Definition: NBRequest.cpp:787
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.
SUMOReal getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
Definition: NBEdge.cpp:1449
void resetSignalised()
Definition: NBRequest.cpp:343
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:409