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-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++) {
160  computeRightOutgoingLinkCrossings(leftHanded, *i, *j);
161  computeLeftOutgoingLinkCrossings(leftHanded, *i, *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(leftHanded, 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(leftHanded, from, to, *pfrom, *pto);
199  }
201  }
202  }
203  }
204 }
205 
206 
207 void
208 NBRequest::setBlocking(bool leftHanded,
209  NBEdge* from1, NBEdge* to1,
210  NBEdge* from2, NBEdge* to2) {
211  // check whether one of the links has a dead end
212  if (to1 == 0 || to2 == 0) {
213  return;
214  }
215  // get the indices of both links
216  int idx1 = getIndex(from1, to1);
217  int idx2 = getIndex(from2, to2);
218  if (idx1 < 0 || idx2 < 0) {
219  return; // !!! error output? did not happend, yet
220  }
221  // check whether the link crossing has already been checked
222  assert((size_t) idx1 < myIncoming.size()*myOutgoing.size());
223  if (myDone[idx1][idx2]) {
224  return;
225  }
226  // mark the crossings as done
227  myDone[idx1][idx2] = true;
228  myDone[idx2][idx1] = true;
229  // special case all-way stop
231  // all ways forbid each other. Conflict resolution happens via arrival time
232  myForbids[idx1][idx2] = true;
233  myForbids[idx2][idx1] = true;
234  return;
235  }
236  // check if one of the links is a turn; this link is always not priorised
237  // true for right-before-left and priority
238  if (from1->isTurningDirectionAt(to1)) {
239  myForbids[idx2][idx1] = true;
240  return;
241  }
242  if (from2->isTurningDirectionAt(to2)) {
243  myForbids[idx1][idx2] = true;
244  return;
245  }
246  // check the priorities if required by node type
248  int from1p = from1->getJunctionPriority(myJunction);
249  int from2p = from2->getJunctionPriority(myJunction);
250  // check if one of the connections is higher priorised when incoming into
251  // the junction, the connection road will yield
252  if (from1p > from2p) {
253  myForbids[idx1][idx2] = true;
254  return;
255  }
256  if (from2p > from1p) {
257  myForbids[idx2][idx1] = true;
258  return;
259  }
260  }
261 
262  // check whether one of the connections is higher priorised on
263  // the outgoing edge when both roads are high priorised
264  // the connection with the lower priorised outgoing edge will lead
265  // should be valid for priority junctions only
266  /*
267  if (from1p > 0 && from2p > 0) {
268  assert(myJunction->getType() != NODETYPE_RIGHT_BEFORE_LEFT);
269  int to1p = to1->getJunctionPriority(myJunction);
270  int to2p = to2->getJunctionPriority(myJunction);
271  if (to1p > to2p) {
272  myForbids[idx1][idx2] = true;
273  return;
274  }
275  if (to2p > to1p) {
276  myForbids[idx2][idx1] = true;
277  return;
278  }
279  }
280  */
281 
282  // compute the yielding due to the right-before-left rule
283  // get the position of the incoming lanes in the junction-wheel
284  EdgeVector::const_iterator c1 = find(myAll.begin(), myAll.end(), from1);
286  // go through next edges clockwise...
287  while (*c1 != from1 && *c1 != from2) {
288  if (*c1 == to2) {
289  // if we encounter to2 the second one prohibits the first
290  if (!leftHanded) {
291  myForbids[idx2][idx1] = true;
292  } else {
293  myForbids[idx1][idx2] = true;
294  }
295  return;
296  }
298  }
299  // get the position of the incoming lanes in the junction-wheel
300  EdgeVector::const_iterator c2 = find(myAll.begin(), myAll.end(), from2);
302  // go through next edges clockwise...
303  while (*c2 != from2 && *c2 != from1) {
304  if (*c2 == to1) {
305  // if we encounter to1 the second one prohibits the first
306  if (!leftHanded) {
307  myForbids[idx1][idx2] = true;
308  } else {
309  myForbids[idx2][idx1] = true;
310  }
311  return;
312  }
314  }
315 }
316 
317 
318 size_t
320  EdgeVector::const_iterator p = find(myAll.begin(), myAll.end(), from);
321  size_t ret = 0;
322  do {
323  ret++;
324  if (p == myAll.begin()) {
325  p = myAll.end();
326  }
327  p--;
328  } while (*p != to);
329  return ret;
330 }
331 
332 
333 void
334 NBRequest::writeLogic(std::string /* key */, OutputDevice& into, const bool checkLaneFoes) const {
335  int pos = 0;
336  EdgeVector::const_iterator i;
337  // normal connections
338  for (i = myIncoming.begin(); i != myIncoming.end(); i++) {
339  unsigned int noLanes = (*i)->getNumLanes();
340  for (unsigned int k = 0; k < noLanes; k++) {
341  pos = writeLaneResponse(into, *i, k, pos, checkLaneFoes);
342  }
343  }
344  // crossings
345  for (std::vector<NBNode::Crossing>::const_iterator i = myCrossings.begin(); i != myCrossings.end(); i++) {
346  pos = writeCrossingResponse(into, *i, pos);
347  }
348 }
349 
350 
351 void
353  // go through possible prohibitions
354  for (EdgeVector::const_iterator i11 = myIncoming.begin(); i11 != myIncoming.end(); i11++) {
355  unsigned int noLanesEdge1 = (*i11)->getNumLanes();
356  for (unsigned int j1 = 0; j1 < noLanesEdge1; j1++) {
357  std::vector<NBEdge::Connection> el1 = (*i11)->getConnectionsFromLane(j1);
358  for (std::vector<NBEdge::Connection>::iterator i12 = el1.begin(); i12 != el1.end(); ++i12) {
359  int idx1 = getIndex((*i11), (*i12).toEdge);
360  if (idx1 < 0) {
361  continue;
362  }
363  // go through possibly prohibited
364  for (EdgeVector::const_iterator i21 = myIncoming.begin(); i21 != myIncoming.end(); i21++) {
365  unsigned int noLanesEdge2 = (*i21)->getNumLanes();
366  for (unsigned int j2 = 0; j2 < noLanesEdge2; j2++) {
367  std::vector<NBEdge::Connection> el2 = (*i21)->getConnectionsFromLane(j2);
368  for (std::vector<NBEdge::Connection>::iterator i22 = el2.begin(); i22 != el2.end(); i22++) {
369  int idx2 = getIndex((*i21), (*i22).toEdge);
370  if (idx2 < 0) {
371  continue;
372  }
373  // check
374  // same incoming connections do not prohibit each other
375  if ((*i11) == (*i21)) {
376  myForbids[idx1][idx2] = false;
377  myForbids[idx2][idx1] = false;
378  continue;
379  }
380  // check other
381  // if both are non-signalised or both are signalised
382  if (((*i12).tlID == "" && (*i22).tlID == "")
383  ||
384  ((*i12).tlID != "" && (*i22).tlID != "")) {
385  // do nothing
386  continue;
387  }
388  // supposing, we don not have to
389  // brake if we are no foes
390  if (!foes(*i11, (*i12).toEdge, *i21, (*i22).toEdge)) {
391  continue;
392  }
393  // otherwise:
394  // the non-signalised must break
395  if ((*i12).tlID != "") {
396  myForbids[idx1][idx2] = true;
397  myForbids[idx2][idx1] = false;
398  } else {
399  myForbids[idx1][idx2] = false;
400  myForbids[idx2][idx1] = true;
401  }
402  }
403  }
404  }
405  }
406  }
407  }
408 }
409 
410 
411 std::pair<unsigned int, unsigned int>
413  unsigned int noLanes = 0;
414  unsigned int noLinks = 0;
415  for (EdgeVector::const_iterator i = myIncoming.begin();
416  i != myIncoming.end(); i++) {
417  unsigned int noLanesEdge = (*i)->getNumLanes();
418  for (unsigned int j = 0; j < noLanesEdge; j++) {
419  unsigned int numConnections = (unsigned int)(*i)->getConnectionsFromLane(j).size();
420  noLinks += numConnections;
421  if (numConnections > 0) {
422  noLanes++;
423  }
424  }
425  }
426  return std::make_pair(noLanes, noLinks);
427 }
428 
429 
430 bool
431 NBRequest::foes(const NBEdge* const from1, const NBEdge* const to1,
432  const NBEdge* const from2, const NBEdge* const to2) const {
433  // unconnected edges do not forbid other edges
434  if (to1 == 0 || to2 == 0) {
435  return false;
436  }
437  // get the indices
438  int idx1 = getIndex(from1, to1);
439  int idx2 = getIndex(from2, to2);
440  if (idx1 < 0 || idx2 < 0) {
441  return false; // sure? (The connection does not exist within this junction)
442  }
443  assert((size_t) idx1 < myIncoming.size()*myOutgoing.size());
444  assert((size_t) idx2 < myIncoming.size()*myOutgoing.size());
445  return myForbids[idx1][idx2] || myForbids[idx2][idx1];
446 }
447 
448 
449 bool
450 NBRequest::forbids(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
451  const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo,
452  bool regardNonSignalisedLowerPriority) const {
453  // unconnected edges do not forbid other edges
454  if (possProhibitorTo == 0 || possProhibitedTo == 0) {
455  return false;
456  }
457  // get the indices
458  int possProhibitorIdx = getIndex(possProhibitorFrom, possProhibitorTo);
459  int possProhibitedIdx = getIndex(possProhibitedFrom, possProhibitedTo);
460  if (possProhibitorIdx < 0 || possProhibitedIdx < 0) {
461  return false; // sure? (The connection does not exist within this junction)
462  }
463  assert((size_t) possProhibitorIdx < myIncoming.size()*myOutgoing.size());
464  assert((size_t) possProhibitedIdx < myIncoming.size()*myOutgoing.size());
465  // check simple right-of-way-rules
466  if (!regardNonSignalisedLowerPriority) {
467  return myForbids[possProhibitorIdx][possProhibitedIdx];
468  }
469  // if its not forbidden, report
470  if (!myForbids[possProhibitorIdx][possProhibitedIdx]) {
471  return false;
472  }
473  // do not forbid a signalised stream by a non-signalised
474  if (!possProhibitorFrom->hasSignalisedConnectionTo(possProhibitorTo)) {
475  return false;
476  }
477  return true;
478 }
479 
480 
481 int
483  int fromLane, int pos, const bool checkLaneFoes) const {
484  std::vector<NBEdge::Connection> connected = from->getConnectionsFromLane(fromLane);
485  for (std::vector<NBEdge::Connection>::iterator j = connected.begin(); j != connected.end(); j++) {
486  assert((*j).toEdge != 0);
488  od.writeAttr(SUMO_ATTR_INDEX, pos++);
489  od.writeAttr(SUMO_ATTR_RESPONSE, getResponseString(from, (*j).toEdge, fromLane, (*j).toLane, (*j).mayDefinitelyPass, checkLaneFoes));
490  od.writeAttr(SUMO_ATTR_FOES, getFoesString(from, (*j).toEdge, fromLane, (*j).toLane, checkLaneFoes));
491  if (!OptionsCont::getOptions().getBool("no-internal-links")) {
492  od.writeAttr(SUMO_ATTR_CONT, j->haveVia);
493  }
494  od.closeTag();
495  }
496  return pos;
497 }
498 
499 
500 int
501 NBRequest::writeCrossingResponse(OutputDevice& od, const NBNode::Crossing& crossing, int pos) const {
502  std::string foes(myCrossings.size(), '0');
503  std::string response(myCrossings.size(), '0');
504  // conflicts with normal connections
505  for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
506  //const std::vector<NBEdge::Connection> &allConnections = (*i)->getConnections();
507  const NBEdge* from = *i;
508  unsigned int noLanes = from->getNumLanes();
509  for (int j = noLanes; j-- > 0;) {
510  std::vector<NBEdge::Connection> connected = from->getConnectionsFromLane(j);
511  int size = (int) connected.size();
512  for (int k = size; k-- > 0;) {
513  const NBEdge* to = connected[k].toEdge;
514  bool foe = false;
515  for (EdgeVector::const_iterator it_e = crossing.edges.begin(); it_e != crossing.edges.end(); ++it_e) {
516  if ((*it_e) == from || (*it_e) == to) {
517  foe = true;
518  break;
519  }
520  }
521  foes += foe ? '1' : '0';
522  response += mustBrakeForCrossing(from, to, crossing) || !foe ? '0' : '1';
523  }
524  }
525  }
527  od.writeAttr(SUMO_ATTR_INDEX, pos++);
528  od.writeAttr(SUMO_ATTR_RESPONSE, response);
530  od.writeAttr(SUMO_ATTR_CONT, false);
531  od.closeTag();
532  return pos;
533 }
534 
535 
536 std::string
537 NBRequest::getResponseString(const NBEdge* const from, const NBEdge* const to,
538  int fromLane, int toLane, bool mayDefinitelyPass, const bool checkLaneFoes) const {
539  int idx = 0;
540  if (to != 0) {
541  idx = getIndex(from, to);
542  }
543  std::string result;
544  // crossings
545  for (std::vector<NBNode::Crossing>::const_reverse_iterator i = myCrossings.rbegin(); i != myCrossings.rend(); i++) {
546  result += mustBrakeForCrossing(from, to, *i) ? '1' : '0';
547  }
548  // normal connections
549  for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
550  //const std::vector<NBEdge::Connection> &allConnections = (*i)->getConnections();
551  unsigned int noLanes = (*i)->getNumLanes();
552  for (int j = noLanes; j-- > 0;) {
553  std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
554  int size = (int) connected.size();
555  for (int k = size; k-- > 0;) {
556  if (mayDefinitelyPass) {
557  result += '0';
558  } else if ((*i) == from && fromLane == j) {
559  // do not prohibit a connection by others from same lane
560  result += '0';
561  } else {
562  assert(k < (int) connected.size());
563  assert((size_t) idx < myIncoming.size()*myOutgoing.size());
564  assert(connected[k].toEdge != 0);
565  assert((size_t) getIndex(*i, connected[k].toEdge) < myIncoming.size()*myOutgoing.size());
566  // check whether the connection is prohibited by another one
567  if ((myForbids[getIndex(*i, connected[k].toEdge)][idx] &&
568  (!checkLaneFoes || laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane)))
569  || rightTurnConflict(from, to, fromLane, *i, connected[k].toEdge, connected[k].fromLane)) {
570  result += '1';
571  } else {
572  result += '0';
573  }
574  }
575  }
576  }
577  }
578  return result;
579 }
580 
581 
582 std::string
583 NBRequest::getFoesString(NBEdge* from, NBEdge* to, int fromLane, int toLane, const bool checkLaneFoes) const {
584  // remember the case when the lane is a "dead end" in the meaning that
585  // vehicles must choose another lane to move over the following
586  // junction
587  // !!! move to forbidden
588  std::string result;
589  // crossings
590  for (std::vector<NBNode::Crossing>::const_reverse_iterator i = myCrossings.rbegin(); i != myCrossings.rend(); i++) {
591  bool foes = false;
592  for (EdgeVector::const_iterator it_e = (*i).edges.begin(); it_e != (*i).edges.end(); ++it_e) {
593  if ((*it_e) == from || (*it_e) == to) {
594  foes = true;
595  break;
596  }
597  }
598  result += foes ? '1' : '0';
599  }
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  || rightTurnConflict(from, to, fromLane, *i, connected[k].toEdge, connected[k].fromLane)) {
611  result += '1';
612  } else {
613  result += '0';
614  }
615  }
616  }
617  }
618  return result;
619 }
620 
621 
622 bool
623 NBRequest::laneConflict(const NBEdge* from, const NBEdge* to, int toLane,
624  const NBEdge* prohibitorFrom, const NBEdge* prohibitorTo, int prohibitorToLane) const {
625  if (to != prohibitorTo) {
626  return true;
627  }
628  // since we know that the edge2edge connections are in conflict, the only
629  // situation in which the lane2lane connections can be conflict-free is, if
630  // they target the same edge but do not cross each other
632  from->getAngleAtNode(from->getToNode()), to->getAngleAtNode(to->getFromNode()));
633  if (angle == 180) {
634  angle = -180; // turnarounds are left turns
635  }
636  const SUMOReal prohibitorAngle = NBHelpers::relAngle(
637  prohibitorFrom->getAngleAtNode(prohibitorFrom->getToNode()), to->getAngleAtNode(to->getFromNode()));
638  const bool rightOfProhibitor = prohibitorFrom->isTurningDirectionAt(to)
639  || (angle > prohibitorAngle && !from->isTurningDirectionAt(to));
640  return rightOfProhibitor ? toLane >= prohibitorToLane : toLane <= prohibitorToLane;
641 }
642 
643 
644 bool
645 NBRequest::rightTurnConflict(const NBEdge* from, const NBEdge* to, int fromLane,
646  const NBEdge* prohibitorFrom, const NBEdge* prohibitorTo, int prohibitorFromLane) const {
647  if (from != prohibitorFrom) {
648  return false;
649  }
650  if (from->isTurningDirectionAt(to)
651  || prohibitorFrom->isTurningDirectionAt(prohibitorTo)) {
652  // XXX should warn if there are any non-turning connections left of this
653  return false;
654  }
655  const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
656  if ((!lefthand && fromLane <= prohibitorFromLane) ||
657  (lefthand && fromLane >= prohibitorFromLane)) {
658  return false;
659  }
660  // conflict if to is between prohibitorTo and from when going clockwise
661  if (to->getStartAngle() == prohibitorTo->getStartAngle()) {
662  // reduce rounding errors
663  return false;
664  }
665  const SUMOReal toAngleAtNode = fmod(to->getStartAngle() + 180, (SUMOReal)360.0);
666  const SUMOReal prohibitorToAngleAtNode = fmod(prohibitorTo->getStartAngle() + 180, (SUMOReal)360.0);
667  return (lefthand != (GeomHelper::getCWAngleDiff(from->getEndAngle(), toAngleAtNode) <
668  GeomHelper::getCWAngleDiff(from->getEndAngle(), prohibitorToAngleAtNode)));
669 }
670 
671 
672 int
673 NBRequest::getIndex(const NBEdge* const from, const NBEdge* const to) const {
674  EdgeVector::const_iterator fp = find(myIncoming.begin(), myIncoming.end(), from);
675  EdgeVector::const_iterator tp = find(myOutgoing.begin(), myOutgoing.end(), to);
676  if (fp == myIncoming.end() || tp == myOutgoing.end()) {
677  return -1;
678  }
679  // compute the index
680  return (int)(distance(myIncoming.begin(), fp) * myOutgoing.size() + distance(myOutgoing.begin(), tp));
681 }
682 
683 
684 std::ostream&
685 operator<<(std::ostream& os, const NBRequest& r) {
686  size_t variations = r.numLinks();
687  for (size_t i = 0; i < variations; i++) {
688  os << i << ' ';
689  for (size_t j = 0; j < variations; j++) {
690  if (r.myForbids[i][j]) {
691  os << '1';
692  } else {
693  os << '0';
694  }
695  }
696  os << std::endl;
697  }
698  os << std::endl;
699  return os;
700 }
701 
702 
703 bool
704 NBRequest::mustBrake(const NBEdge* const from, const NBEdge* const to, int fromLane, bool includePedCrossings) const {
705  // vehicles which do not have a following lane must always decelerate to the end
706  if (to == 0) {
707  return true;
708  }
709  // get the indices
710  int idx2 = getIndex(from, to);
711  if (idx2 == -1) {
712  return false;
713  }
714  // go through all (existing) connections;
715  // check whether any of these forbids the one to determine
716  assert((size_t) idx2 < myIncoming.size()*myOutgoing.size());
717  for (size_t idx1 = 0; idx1 < numLinks(); idx1++) {
718  //assert(myDone[idx1][idx2]);
719  if (myDone[idx1][idx2] && myForbids[idx1][idx2]) {
720  return true;
721  }
722  }
723  // maybe we need to brake for a pedestrian crossing
724  if (includePedCrossings) {
725  for (std::vector<NBNode::Crossing>::const_reverse_iterator i = myCrossings.rbegin(); i != myCrossings.rend(); i++) {
726  if (mustBrakeForCrossing(from, to, *i)) {
727  return true;
728  }
729  }
730  }
731  // maybe we need to brake due to a right-turn conflict with straight-going
732  // bicycles
733  LinkDirection dir = myJunction->getDirection(from, to);
734  if (dir == LINKDIR_RIGHT || dir == LINKDIR_PARTRIGHT) {
735  const std::vector<NBEdge::Connection>& cons = from->getConnections();
736  for (std::vector<NBEdge::Connection>::const_iterator i = cons.begin(); i != cons.end(); i++) {
737  if (rightTurnConflict(from, to, fromLane,
738  from, (*i).toEdge, (*i).fromLane)) {
739  return true;
740  }
741  }
742  }
743  return false;
744 }
745 
746 bool
747 NBRequest::mustBrakeForCrossing(const NBEdge* const from, const NBEdge* const to, const NBNode::Crossing& crossing) const {
748  const LinkDirection dir = myJunction->getDirection(from, to);
749  const bool mustYield = dir == LINKDIR_LEFT || dir == LINKDIR_RIGHT;
750  if (crossing.priority || mustYield) {
751  for (EdgeVector::const_iterator it_e = crossing.edges.begin(); it_e != crossing.edges.end(); ++it_e) {
752  // left and right turns must yield to unprioritized crossings only on their destination edge
753  if (((*it_e) == from && crossing.priority) || (*it_e) == to) {
754  return true;
755  }
756  }
757  }
758  return false;
759 }
760 
761 
762 bool
763 NBRequest::mustBrake(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
764  const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo) const {
765  // get the indices
766  int idx1 = getIndex(possProhibitorFrom, possProhibitorTo);
767  int idx2 = getIndex(possProhibitedFrom, possProhibitedTo);
768  return (myForbids[idx2][idx1]);
769 }
770 
771 
772 void
774  // check if any errors occured on build the link prohibitions
775  if (myNotBuild != 0) {
776  WRITE_WARNING(toString(myNotBuild) + " of " + toString(myNotBuild + myGoodBuilds) + " prohibitions were not build.");
777  }
778 }
779 
780 
781 void
783  // map from edge to number of incoming connections
784  std::map<NBEdge*, size_t> incomingCount; // initialized to 0
785  // map from edge to indices of approached lanes
786  std::map<NBEdge*, std::set<int> > approachedLanes;
787  // map from edge to list of incoming edges
788  std::map<NBEdge*, EdgeVector> incomingEdges;
789  for (EdgeVector::const_iterator it_e = myIncoming.begin(); it_e != myIncoming.end(); it_e++) {
790  const std::vector<NBEdge::Connection> connections = (*it_e)->getConnections();
791  for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); ++it_c) {
792  incomingCount[it_c->toEdge]++;
793  approachedLanes[it_c->toEdge].insert(it_c->toLane);
794  incomingEdges[it_c->toEdge].push_back(*it_e);
795  }
796  }
797  for (std::map<NBEdge*, size_t>::iterator it = incomingCount.begin(); it != incomingCount.end(); ++it) {
798  NBEdge* to = it->first;
799  // we cannot test against to->getNumLanes() since not all lanes may be used
800  if (approachedLanes[to].size() >= it->second) {
801  EdgeVector& incoming = incomingEdges[to];
802  // make these connections mutually unconflicting
803  for (EdgeVector::iterator it_e1 = incoming.begin(); it_e1 != incoming.end(); ++it_e1) {
804  for (EdgeVector::iterator it_e2 = incoming.begin(); it_e2 != incoming.end(); ++it_e2) {
805  myForbids[getIndex(*it_e1, to)][getIndex(*it_e2, to)] = false;
806  }
807  }
808  }
809  }
810 }
811 
812 
813 size_t
815  return myIncoming.size() * myOutgoing.size() + myCrossings.size();
816 }
817 
818 /****************************************************************************/
819 
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:673
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:257
bool check(const NBEdgeCont &ec)
checks whether the edges are still valid
static SUMOReal getCWAngleDiff(SUMOReal angle1, SUMOReal angle2)
Returns the distance of second angle from first angle clockwise.
Definition: GeomHelper.cpp:395
void computeLeftOutgoingLinkCrossings(bool leftHanded, NBEdge *from, NBEdge *to)
Definition: NBRequest.cpp:190
std::vector< bool > LinkInfoCont
Definition: NBRequest.h:254
bool mustBrakeForCrossing(const NBEdge *const from, const NBEdge *const to, const NBNode::Crossing &crossing) const
Returns the information whether the described flow must brake for the given crossing.
Definition: NBRequest.cpp:747
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:501
NBRequest(const NBEdgeCont &ec, NBNode *junction, const EdgeVector &all, const EdgeVector &incoming, const EdgeVector &outgoing, const NBConnectionProhibits &loadedProhibits)
Definition: NBRequest.cpp:66
std::ostream & operator<<(std::ostream &os, const NBRequest &r)
Definition: NBRequest.cpp:685
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:450
SUMOReal getEndAngle() const
Returns the angle at the end of the edge The angle is computed in computeAngle()
Definition: NBEdge.h:389
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:238
const EdgeVector & myOutgoing
Definition: NBRequest.h:247
static void nextCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
void writeLogic(std::string key, OutputDevice &into, const bool checkLaneFoes) const
Definition: NBRequest.cpp:334
std::vector< Connection > getConnectionsFromLane(unsigned int lane) const
Returns connections from a given lane.
Definition: NBEdge.cpp:747
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:537
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:319
const EdgeVector & myIncoming
Definition: NBRequest.h:244
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:67
CombinationsCont myDone
Definition: NBRequest.h:267
bool priority
whether the pedestrians have priority
Definition: NBNode.h:153
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:773
const std::string & getID() const
Returns the id.
Definition: Named.h:60
bool rightTurnConflict(const NBEdge *from, const NBEdge *to, int fromLane, const NBEdge *prohibitorFrom, const NBEdge *prohibitorTo, int prohibitorFromLane) const
return whether the given laneToLane connection is a right turn which must yield to a bicycle crossing...
Definition: NBRequest.cpp:645
void buildBitfieldLogic(bool leftHanded)
Definition: NBRequest.cpp:156
bool mustBrake(const NBEdge *const possProhibitorFrom, const NBEdge *const possProhibitorTo, const NBEdge *const possProhibitedFrom, const NBEdge *const possProhibitedTo) const
Returns the information whether "prohibited" flow must let "prohibitor" flow pass.
Definition: NBRequest.cpp:763
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:623
unsigned int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:347
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:276
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:1756
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:583
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:241
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:1225
void setBlocking(bool leftHanded, NBEdge *from1, NBEdge *to1, NBEdge *from2, NBEdge *to2)
Definition: NBRequest.cpp:208
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:371
size_t numLinks() const
return to total number of edge-to-edge connections of this request-logic
Definition: NBRequest.cpp:814
static size_t myNotBuild
Definition: NBRequest.h:270
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:482
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:250
EdgeVector edges
The edges being crossed.
Definition: NBNode.h:141
Represents a single node (junction) during network building.
Definition: NBNode.h:75
bool hasSignalisedConnectionTo(const NBEdge *const e) const
Definition: NBEdge.cpp:2028
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:431
A definition of a pedestrian crossing.
Definition: NBNode.h:134
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:218
static size_t myGoodBuilds
Definition: NBRequest.h:270
static SUMOReal relAngle(SUMOReal angle1, SUMOReal angle2)
Definition: NBHelpers.cpp:63
SUMOReal getStartAngle() const
Returns the angle at the start of the edge The angle is computed in computeAngle() ...
Definition: NBEdge.h:380
Information whether the detector shall be continued on the folowing lanes.
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:761
void resetCooperating()
reset foes it the number of lanes matches (or exceeds) the number of incoming connections for an edge...
Definition: NBRequest.cpp:782
static void nextCCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
CombinationsCont myForbids
Definition: NBRequest.h:264
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
std::pair< unsigned int, unsigned int > getSizes() const
returns the number of the junction's lanes and the number of the junction's links in respect...
Definition: NBRequest.cpp:412
void computeRightOutgoingLinkCrossings(bool leftHanded, NBEdge *from, NBEdge *to)
Definition: NBRequest.cpp:172
SUMOReal getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
Definition: NBEdge.cpp:1245
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing) const
Returns the representation of the described stream's direction.
Definition: NBNode.cpp:1311
void resetSignalised()
Definition: NBRequest.cpp:352
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:363