Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file NBRequest.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @author Laura Bieker
19 : /// @date Tue, 20 Nov 2001
20 : ///
21 : // This class computes the logic of a junction
22 : /****************************************************************************/
23 : #include <config.h>
24 :
25 : #include <string>
26 : #include <vector>
27 : #include <set>
28 : #include <algorithm>
29 : #include <bitset>
30 : #include <sstream>
31 : #include <map>
32 : #include <cassert>
33 : #include <utils/common/MsgHandler.h>
34 : #include <utils/common/ToString.h>
35 : #include <utils/options/OptionsCont.h>
36 : #include <utils/iodevices/OutputDevice.h>
37 : #include "NBEdge.h"
38 : #include "NBContHelper.h"
39 : #include "NBNode.h"
40 : #include "NBRequest.h"
41 :
42 : //#define DEBUG_RESPONSE
43 : //#define DEBUG_SETBLOCKING
44 : #define DEBUGCOND (myJunction->getID() == "C")
45 :
46 : // ===========================================================================
47 : // static member variables
48 : // ===========================================================================
49 : int NBRequest::myGoodBuilds = 0;
50 : int NBRequest::myNotBuild = 0;
51 :
52 :
53 : // ===========================================================================
54 : // method definitions
55 : // ===========================================================================
56 48659 : NBRequest::NBRequest(const NBEdgeCont& ec,
57 : NBNode* junction,
58 : const EdgeVector& all,
59 : const EdgeVector& incoming,
60 : const EdgeVector& outgoing,
61 48659 : const NBConnectionProhibits& loadedProhibits) :
62 48659 : myJunction(junction),
63 48659 : myAll(all),
64 48659 : myIncoming(incoming),
65 48659 : myOutgoing(outgoing) {
66 48659 : const int variations = numLinks();
67 : // build maps with information which forbidding connection were
68 : // computed and what's in there
69 48659 : myForbids.reserve(variations);
70 48659 : myDone.reserve(variations);
71 296067 : for (int i = 0; i < variations; i++) {
72 247408 : myForbids.push_back(LinkInfoCont(variations, false));
73 494816 : myDone.push_back(LinkInfoCont(variations, false));
74 : }
75 : // insert loaded prohibits
76 48761 : for (NBConnectionProhibits::const_iterator j = loadedProhibits.begin(); j != loadedProhibits.end(); j++) {
77 102 : NBConnection prohibited = (*j).first;
78 102 : bool ok1 = prohibited.check(ec);
79 102 : if (find(myIncoming.begin(), myIncoming.end(), prohibited.getFrom()) == myIncoming.end()) {
80 : ok1 = false;
81 : }
82 102 : if (find(myOutgoing.begin(), myOutgoing.end(), prohibited.getTo()) == myOutgoing.end()) {
83 : ok1 = false;
84 : }
85 : int idx1 = 0;
86 102 : if (ok1) {
87 102 : idx1 = getIndex(prohibited.getFrom(), prohibited.getTo());
88 102 : if (idx1 < 0) {
89 : ok1 = false;
90 : }
91 : }
92 : const NBConnectionVector& prohibiting = (*j).second;
93 301 : for (NBConnectionVector::const_iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
94 199 : NBConnection sprohibiting = *k;
95 199 : bool ok2 = sprohibiting.check(ec);
96 199 : if (find(myIncoming.begin(), myIncoming.end(), sprohibiting.getFrom()) == myIncoming.end()) {
97 : ok2 = false;
98 : }
99 199 : if (find(myOutgoing.begin(), myOutgoing.end(), sprohibiting.getTo()) == myOutgoing.end()) {
100 : ok2 = false;
101 : }
102 199 : if (ok1 && ok2) {
103 199 : int idx2 = getIndex(sprohibiting.getFrom(), sprohibiting.getTo());
104 199 : if (idx2 < 0) {
105 : ok2 = false;
106 : } else {
107 199 : myForbids[idx2][idx1] = true;
108 : myDone[idx2][idx1] = true;
109 199 : myDone[idx1][idx2] = true;
110 199 : myGoodBuilds++;
111 : }
112 : } else {
113 0 : std::string pfID = prohibited.getFrom() != nullptr ? prohibited.getFrom()->getID() : "UNKNOWN";
114 0 : std::string ptID = prohibited.getTo() != nullptr ? prohibited.getTo()->getID() : "UNKNOWN";
115 0 : std::string bfID = sprohibiting.getFrom() != nullptr ? sprohibiting.getFrom()->getID() : "UNKNOWN";
116 0 : std::string btID = sprohibiting.getTo() != nullptr ? sprohibiting.getTo()->getID() : "UNKNOWN";
117 0 : WRITE_WARNING("could not prohibit " + pfID + "->" + ptID + " by " + bfID + "->" + btID);
118 0 : myNotBuild++;
119 : }
120 199 : }
121 102 : }
122 : // ok, check whether someone has prohibited two links vice versa
123 : // (this happens also in some Vissim-networks, when edges are joined)
124 296067 : for (int s1 = 0; s1 < variations; s1++) {
125 1888381 : for (int s2 = s1 + 1; s2 < variations; s2++) {
126 : // not set, yet
127 1640973 : if (!myDone[s1][s2]) {
128 1640861 : continue;
129 : }
130 : // check whether both prohibit vice versa
131 112 : if (myForbids[s1][s2] && myForbids[s2][s1]) {
132 : // mark unset - let our algorithm fix it later
133 : myDone[s1][s2] = false;
134 : myDone[s2][s1] = false;
135 : }
136 : }
137 : }
138 48659 : }
139 :
140 :
141 48659 : NBRequest::~NBRequest() {}
142 :
143 :
144 : void
145 42230 : NBRequest::buildBitfieldLogic() {
146 : EdgeVector::const_iterator i, j;
147 129077 : for (i = myIncoming.begin(); i != myIncoming.end(); i++) {
148 311699 : for (j = myOutgoing.begin(); j != myOutgoing.end(); j++) {
149 224852 : computeRightOutgoingLinkCrossings(*i, *j);
150 224852 : computeLeftOutgoingLinkCrossings(*i, *j);
151 : }
152 : }
153 : // reset signalised/non-signalised dependencies
154 42230 : resetSignalised();
155 : // reset foes it the number of lanes matches (or exceeds) the number of incoming connections
156 42230 : resetCooperating();
157 42230 : }
158 :
159 :
160 : void
161 224852 : NBRequest::computeRightOutgoingLinkCrossings(NBEdge* from, NBEdge* to) {
162 224852 : EdgeVector::const_iterator pfrom = std::find(myAll.begin(), myAll.end(), from);
163 965694 : while (*pfrom != to) {
164 740842 : NBContHelper::nextCCW(myAll, pfrom);
165 740842 : if ((*pfrom)->getToNode() == myJunction) {
166 258619 : EdgeVector::const_iterator pto = std::find(myAll.begin(), myAll.end(), to);
167 1042034 : while (*pto != from) {
168 783415 : if (!((*pto)->getToNode() == myJunction)) {
169 523423 : setBlocking(from, to, *pfrom, *pto);
170 : }
171 783415 : NBContHelper::nextCCW(myAll, pto);
172 : }
173 : }
174 : }
175 224852 : }
176 :
177 :
178 : void
179 224852 : NBRequest::computeLeftOutgoingLinkCrossings(NBEdge* from, NBEdge* to) {
180 224852 : EdgeVector::const_iterator pfrom = std::find(myAll.begin(), myAll.end(), from);
181 965694 : while (*pfrom != to) {
182 740842 : NBContHelper::nextCW(myAll, pfrom);
183 740842 : if ((*pfrom)->getToNode() == myJunction) {
184 258619 : EdgeVector::const_iterator pto = std::find(myAll.begin(), myAll.end(), to);
185 1042034 : while (*pto != from) {
186 783415 : if (!((*pto)->getToNode() == myJunction)) {
187 523423 : setBlocking(from, to, *pfrom, *pto);
188 : }
189 783415 : NBContHelper::nextCW(myAll, pto);
190 : }
191 : }
192 : }
193 224852 : }
194 :
195 :
196 : void
197 1046846 : NBRequest::setBlocking(NBEdge* from1, NBEdge* to1,
198 : NBEdge* from2, NBEdge* to2) {
199 : // check whether one of the links has a dead end
200 1046846 : if (to1 == nullptr || to2 == nullptr) {
201 1046846 : return;
202 : }
203 : // get the indices of both links
204 1046846 : int idx1 = getIndex(from1, to1);
205 1046846 : int idx2 = getIndex(from2, to2);
206 1046846 : if (idx1 < 0 || idx2 < 0) {
207 : return; // !!! error output? did not happend, yet
208 : }
209 : // check whether the link crossing has already been checked
210 : assert(idx1 < (int)(myIncoming.size() * myOutgoing.size()));
211 1046846 : if (myDone[idx1][idx2]) {
212 : return;
213 : }
214 : // mark the crossings as done
215 : myDone[idx1][idx2] = true;
216 523333 : myDone[idx2][idx1] = true;
217 : // special case all-way stop
218 523333 : if (myJunction->getType() == SumoXMLNodeType::ALLWAY_STOP) {
219 : // all ways forbid each other. Conflict resolution happens via arrival time
220 : myForbids[idx1][idx2] = true;
221 : myForbids[idx2][idx1] = true;
222 40 : return;
223 : }
224 : // check if one of the links is a turn; this link is always not priorised
225 : // true for right-before-left and priority
226 523293 : if (from1->isTurningDirectionAt(to1)) {
227 : myForbids[idx2][idx1] = true;
228 66939 : return;
229 : }
230 456354 : if (from2->isTurningDirectionAt(to2)) {
231 : myForbids[idx1][idx2] = true;
232 63309 : return;
233 : }
234 : // if there are no connections, there are no prohibitions
235 393045 : if (from1->isConnectedTo(to1)) {
236 242276 : if (!from2->isConnectedTo(to2)) {
237 : myForbids[idx1][idx2] = true;
238 : myForbids[idx2][idx1] = false;
239 27465 : return;
240 : }
241 : } else {
242 150769 : if (!from2->isConnectedTo(to2)) {
243 : myForbids[idx1][idx2] = false;
244 : myForbids[idx2][idx1] = false;
245 122692 : return;
246 : } else {
247 : myForbids[idx1][idx2] = false;
248 : myForbids[idx2][idx1] = true;
249 28077 : return;
250 : }
251 : }
252 : #ifdef DEBUG_SETBLOCKING
253 : if (DEBUGCOND) std::cout << "setBlocking type=" << toString(myJunction->getType())
254 : << " bentPrio=" << myJunction->isBentPriority()
255 : << " 1:" << from1->getID() << "->" << to1->getID()
256 : << " 2:" << from2->getID() << "->" << to2->getID() << "\n";
257 : #endif
258 : // check the priorities if required by node type
259 214811 : const bool typeEqual = myJunction->getType() == SumoXMLNodeType::RIGHT_BEFORE_LEFT || myJunction->getType() == SumoXMLNodeType::LEFT_BEFORE_RIGHT;
260 : if (!typeEqual) {
261 191382 : int from1p = from1->getJunctionPriority(myJunction);
262 191382 : int from2p = from2->getJunctionPriority(myJunction);
263 : #ifdef DEBUG_SETBLOCKING
264 : if (DEBUGCOND) {
265 : std::cout << " p1=" << from1p << " p2=" << from2p << "\n";
266 : }
267 : #endif
268 : // check if one of the connections is higher priorised when incoming into
269 : // the junction, the connection road will yield
270 191382 : if (from1p > from2p) {
271 : myForbids[idx1][idx2] = true;
272 67227 : return;
273 : }
274 124155 : if (from2p > from1p) {
275 : myForbids[idx2][idx1] = true;
276 54772 : return;
277 : }
278 : }
279 : // straight connections prohibit turning connections if the priorities are equal
280 : // (unless the junction is a bent priority junction)
281 92812 : LinkDirection ld1 = myJunction->getDirection(from1, to1);
282 92812 : LinkDirection ld2 = myJunction->getDirection(from2, to2);
283 92812 : if (!typeEqual && !myJunction->isBentPriority()) {
284 : #ifdef DEBUG_SETBLOCKING
285 : if (DEBUGCOND) std::cout << "setBlocking"
286 : << " 1:" << from1->getID() << "->" << to1->getID()
287 : << " 2:" << from2->getID() << "->" << to2->getID()
288 : << " dir1=" << toString(ld1) << " dir2=" << toString(ld2) << "\n";
289 : #endif
290 45168 : if (ld1 == LinkDirection::STRAIGHT) {
291 11170 : if (ld2 != LinkDirection::STRAIGHT) {
292 : myForbids[idx1][idx2] = true;
293 : myForbids[idx2][idx1] = false;
294 10283 : return;
295 : }
296 : } else {
297 33998 : if (ld2 == LinkDirection::STRAIGHT) {
298 : myForbids[idx1][idx2] = false;
299 : myForbids[idx2][idx1] = true;
300 10935 : return;
301 : }
302 : }
303 : }
304 :
305 : // check whether one of the connections is higher priorised on
306 : // the outgoing edge when both roads are high priorised
307 : // the connection with the lower priorised outgoing edge will lead
308 : // should be valid for priority junctions only
309 : /*
310 : if (from1p > 0 && from2p > 0) {
311 : assert(myJunction->getType() != SumoXMLNodeType::RIGHT_BEFORE_LEFT);
312 : int to1p = to1->getJunctionPriority(myJunction);
313 : int to2p = to2->getJunctionPriority(myJunction);
314 : if (to1p > to2p) {
315 : myForbids[idx1][idx2] = true;
316 : return;
317 : }
318 : if (to2p > to1p) {
319 : myForbids[idx2][idx1] = true;
320 : return;
321 : }
322 : }
323 : */
324 : #ifdef DEBUG_SETBLOCKING
325 : if (DEBUGCOND) std::cout << "setBlocking1"
326 : << " 1:" << from1->getID() << "->" << to1->getID()
327 : << " 2:" << from2->getID() << "->" << to2->getID();
328 : << " relAngle=" << NBHelpers::relAngle(from1->getAngleAtNode(myJunction), from2->getAngleAtNode(myJunction))
329 : #endif
330 :
331 : // compute the yielding due to the right-before-left rule
332 : // (or left-before-right rule)
333 : // get the position of the incoming lanes in the junction-wheel
334 71594 : EdgeVector::const_iterator c1 = std::find(myAll.begin(), myAll.end(), from1);
335 71594 : NBContHelper::nextCW(myAll, c1);
336 : // go through next edges clockwise...
337 218792 : while (*c1 != from1 && *c1 != from2) {
338 172300 : if (*c1 == to2) {
339 : // if we encounter to2 the second one prohibits the first
340 25102 : if (myJunction->getType() == SumoXMLNodeType::LEFT_BEFORE_RIGHT
341 25102 : && (ld1 != LinkDirection::LEFT || ld2 == LinkDirection::LEFT || (from1->getTurnDestination(true) != to2 &&
342 7 : (ld2 != LinkDirection::RIGHT ||
343 7 : fabs(NBHelpers::relAngle(from1->getAngleAtNode(myJunction),
344 7 : from2->getAngleAtNode(myJunction))) < 150))
345 : )) {
346 : myForbids[idx1][idx2] = true;
347 : #ifdef DEBUG_SETBLOCKING
348 : if (DEBUGCOND) {
349 : std::cout << " case1: 2 yields\n";
350 : }
351 : #endif
352 : } else {
353 : myForbids[idx2][idx1] = true;
354 : #ifdef DEBUG_SETBLOCKING
355 : if (DEBUGCOND) {
356 : std::cout << " case1: 1 yields\n";
357 : }
358 : #endif
359 : }
360 25102 : return;
361 : }
362 147198 : NBContHelper::nextCW(myAll, c1);
363 : }
364 : // get the position of the incoming lanes in the junction-wheel
365 46492 : EdgeVector::const_iterator c2 = std::find(myAll.begin(), myAll.end(), from2);
366 46492 : NBContHelper::nextCW(myAll, c2);
367 : // go through next edges clockwise...
368 151535 : while (*c2 != from2 && *c2 != from1) {
369 151535 : if (*c2 == to1) {
370 : // if we encounter to1 the second one prohibits the first
371 46492 : if (myJunction->getType() == SumoXMLNodeType::LEFT_BEFORE_RIGHT
372 46492 : && (ld2 != LinkDirection::LEFT || ld1 == LinkDirection::LEFT || (from2->getTurnDestination(true) != to1 &&
373 9 : (ld1 != LinkDirection::RIGHT ||
374 9 : fabs(NBHelpers::relAngle(from1->getAngleAtNode(myJunction),
375 9 : from2->getAngleAtNode(myJunction))) < 150))
376 : )) {
377 : myForbids[idx2][idx1] = true;
378 : #ifdef DEBUG_SETBLOCKING
379 : if (DEBUGCOND) {
380 : std::cout << " case2: 1 yields\n";
381 : }
382 : #endif
383 : } else {
384 : myForbids[idx1][idx2] = true;
385 : #ifdef DEBUG_SETBLOCKING
386 : if (DEBUGCOND) {
387 : std::cout << " case2: 2 yields\n";
388 : }
389 : #endif
390 : }
391 46492 : return;
392 : }
393 105043 : NBContHelper::nextCW(myAll, c2);
394 : }
395 : #ifdef DEBUG_SETBLOCKING
396 : if (DEBUGCOND) {
397 : std::cout << " noDecision\n";
398 : }
399 : #endif
400 : }
401 :
402 :
403 : int
404 0 : NBRequest::distanceCounterClockwise(NBEdge* from, NBEdge* to) {
405 0 : EdgeVector::const_iterator p = std::find(myAll.begin(), myAll.end(), from);
406 : int ret = 0;
407 : do {
408 0 : ret++;
409 0 : if (p == myAll.begin()) {
410 : p = myAll.end();
411 : }
412 : p--;
413 0 : } while (*p != to);
414 0 : return ret;
415 : }
416 :
417 : const std::string&
418 0 : NBRequest::getFoes(int linkIndex) const {
419 : assert(linkIndex >= 0);
420 : assert(linkIndex < (int)myFoes.size());
421 0 : return myFoes[linkIndex];
422 : }
423 :
424 :
425 : const std::string&
426 205806 : NBRequest::getResponse(int linkIndex) const {
427 : assert(linkIndex >= 0);
428 : assert(linkIndex < (int)myResponse.size());
429 205806 : return myResponse[linkIndex];
430 : }
431 :
432 :
433 : void
434 41238 : NBRequest::writeLogic(OutputDevice& into) const {
435 41238 : int numLinks = (int)myResponse.size();
436 : assert((int)myFoes.size() == numLinks);
437 : assert((int)myHaveVia.size() == numLinks);
438 : const bool padding = numLinks > 10;
439 238856 : for (int i = 0; i < numLinks; i++) {
440 197618 : into.openTag(SUMO_TAG_REQUEST);
441 197618 : into.writeAttr(SUMO_ATTR_INDEX, i);
442 197618 : if (padding && i < 10) {
443 95120 : into.writePadding(" ");
444 : }
445 197618 : into.writeAttr(SUMO_ATTR_RESPONSE, myResponse[i]);
446 197618 : into.writeAttr(SUMO_ATTR_FOES, myFoes[i]);
447 395236 : if (!OptionsCont::getOptions().getBool("no-internal-links")) {
448 92643 : into.writeAttr(SUMO_ATTR_CONT, myHaveVia[i]);
449 : }
450 395236 : into.closeTag();
451 : }
452 41238 : }
453 :
454 :
455 : void
456 42230 : NBRequest::computeLogic(const bool checkLaneFoes) {
457 : myResponse.clear();
458 : myFoes.clear();
459 : myHaveVia.clear();
460 : int pos = 0;
461 : EdgeVector::const_iterator i;
462 : // normal connections
463 129077 : for (i = myIncoming.begin(); i != myIncoming.end(); i++) {
464 86847 : int noLanes = (*i)->getNumLanes();
465 201475 : for (int k = 0; k < noLanes; k++) {
466 116392 : pos = computeLaneResponse(*i, k, pos, checkLaneFoes || myJunction->getType() == SumoXMLNodeType::ZIPPER);
467 : }
468 : }
469 : // crossings
470 42230 : auto crossings = myJunction->getCrossings();
471 43842 : for (auto c : crossings) {
472 1612 : pos = computeCrossingResponse(*c, pos);
473 : }
474 42230 : }
475 :
476 : void
477 42230 : NBRequest::resetSignalised() {
478 : // go through possible prohibitions
479 129077 : for (EdgeVector::const_iterator i11 = myIncoming.begin(); i11 != myIncoming.end(); i11++) {
480 86847 : int noLanesEdge1 = (*i11)->getNumLanes();
481 201475 : for (int j1 = 0; j1 < noLanesEdge1; j1++) {
482 114628 : std::vector<NBEdge::Connection> el1 = (*i11)->getConnectionsFromLane(j1);
483 317382 : for (std::vector<NBEdge::Connection>::iterator i12 = el1.begin(); i12 != el1.end(); ++i12) {
484 202754 : int idx1 = getIndex((*i11), (*i12).toEdge);
485 202754 : if (idx1 < 0) {
486 0 : continue;
487 : }
488 : // go through possibly prohibited
489 825045 : for (EdgeVector::const_iterator i21 = myIncoming.begin(); i21 != myIncoming.end(); i21++) {
490 622291 : int noLanesEdge2 = (*i21)->getNumLanes();
491 1498995 : for (int j2 = 0; j2 < noLanesEdge2; j2++) {
492 876704 : std::vector<NBEdge::Connection> el2 = (*i21)->getConnectionsFromLane(j2);
493 3006852 : for (std::vector<NBEdge::Connection>::iterator i22 = el2.begin(); i22 != el2.end(); i22++) {
494 2130148 : int idx2 = getIndex((*i21), (*i22).toEdge);
495 2130148 : if (idx2 < 0) {
496 0 : continue;
497 : }
498 : // check
499 : // same incoming connections do not prohibit each other
500 2130148 : if ((*i11) == (*i21)) {
501 638464 : myForbids[idx1][idx2] = false;
502 638464 : myForbids[idx2][idx1] = false;
503 : #ifdef DEBUG_SETBLOCKING
504 : if (DEBUGCOND) std::cout << "resetSignalised both"
505 : << " 1:" << (*i11)->getID() << "->" << (*i12).toEdge->getID()
506 : << " 2:" << (*i21)->getID() << "->" << (*i22).toEdge->getID()
507 : << "\n";
508 : #endif
509 638464 : continue;
510 : }
511 : // check other
512 : // if both are non-signalised or both are signalised
513 1259994 : if (((*i12).tlID == "" && (*i22).tlID == "")
514 1492886 : ||
515 231690 : ((*i12).tlID != "" && (*i22).tlID != "")) {
516 : // do nothing
517 1489280 : continue;
518 : }
519 : // supposing, we don not have to
520 : // brake if we are no foes
521 2404 : if (!foes(*i11, (*i12).toEdge, *i21, (*i22).toEdge)) {
522 1888 : continue;
523 : }
524 : // otherwise:
525 : // the non-signalised must break
526 516 : if ((*i12).tlID != "") {
527 258 : myForbids[idx1][idx2] = true;
528 258 : myForbids[idx2][idx1] = false;
529 : #ifdef DEBUG_SETBLOCKING
530 : if (DEBUGCOND) std::cout << "resetSignalised:2 yields"
531 : << " 1:" << (*i11)->getID() << "->" << (*i12).toEdge->getID()
532 : << " 2:" << (*i21)->getID() << "->" << (*i22).toEdge->getID() << "\n";
533 : #endif
534 : } else {
535 258 : myForbids[idx1][idx2] = false;
536 258 : myForbids[idx2][idx1] = true;
537 : #ifdef DEBUG_SETBLOCKING
538 : if (DEBUGCOND) std::cout << "resetSignalised:1 yields"
539 : << " 1:" << (*i11)->getID() << "->" << (*i12).toEdge->getID()
540 : << " 2:" << (*i21)->getID() << "->" << (*i22).toEdge->getID() << "\n";
541 : #endif
542 : }
543 : }
544 876704 : }
545 : }
546 : }
547 114628 : }
548 : }
549 42230 : }
550 :
551 :
552 : std::pair<int, int>
553 49105 : NBRequest::getSizes() const {
554 : int numLanes = 0;
555 : int numLinks = 0;
556 147086 : for (const NBEdge* const e : myIncoming) {
557 : const int numLanesEdge = e->getNumLanes();
558 225556 : for (int j = 0; j < numLanesEdge; j++) {
559 127575 : int numConnections = (int)e->getConnectionsFromLane(j).size();
560 127575 : numLinks += numConnections;
561 127575 : if (numConnections > 0) {
562 107395 : numLanes++;
563 : }
564 : }
565 : }
566 49105 : return std::make_pair(numLanes, numLinks);
567 : }
568 :
569 :
570 : bool
571 3679250 : NBRequest::foes(const NBEdge* const from1, const NBEdge* const to1,
572 : const NBEdge* const from2, const NBEdge* const to2) const {
573 : // unconnected edges do not forbid other edges
574 3679250 : if (to1 == nullptr || to2 == nullptr) {
575 : return false;
576 : }
577 : // get the indices
578 3679250 : int idx1 = getIndex(from1, to1);
579 3679250 : int idx2 = getIndex(from2, to2);
580 3679250 : if (idx1 < 0 || idx2 < 0) {
581 : return false; // sure? (The connection does not exist within this junction)
582 : }
583 : assert(idx1 < (int)(myIncoming.size() * myOutgoing.size()));
584 : assert(idx2 < (int)(myIncoming.size()*myOutgoing.size()));
585 3524532 : return myForbids[idx1][idx2] || myForbids[idx2][idx1];
586 : }
587 :
588 :
589 : bool
590 1457067 : NBRequest::forbids(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
591 : const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo,
592 : bool regardNonSignalisedLowerPriority) const {
593 : // unconnected edges do not forbid other edges
594 1457067 : if (possProhibitorTo == nullptr || possProhibitedTo == nullptr) {
595 : return false;
596 : }
597 : // get the indices
598 1457067 : int possProhibitorIdx = getIndex(possProhibitorFrom, possProhibitorTo);
599 1457067 : int possProhibitedIdx = getIndex(possProhibitedFrom, possProhibitedTo);
600 1457067 : if (possProhibitorIdx < 0 || possProhibitedIdx < 0) {
601 : return false; // sure? (The connection does not exist within this junction)
602 : }
603 : assert(possProhibitorIdx < (int)(myIncoming.size() * myOutgoing.size()));
604 : assert(possProhibitedIdx < (int)(myIncoming.size() * myOutgoing.size()));
605 : // check simple right-of-way-rules
606 1457067 : if (!regardNonSignalisedLowerPriority) {
607 588935 : return myForbids[possProhibitorIdx][possProhibitedIdx];
608 : }
609 : // if its not forbidden, report
610 868132 : if (!myForbids[possProhibitorIdx][possProhibitedIdx]) {
611 : return false;
612 : }
613 : // do not forbid a signalised stream by a non-signalised
614 155993 : if (!possProhibitorFrom->hasSignalisedConnectionTo(possProhibitorTo)) {
615 : return false;
616 : }
617 : return true;
618 : }
619 :
620 : int
621 114628 : NBRequest::computeLaneResponse(NBEdge* from, int fromLane, int pos, const bool checkLaneFoes) {
622 317382 : for (const NBEdge::Connection& c : from->getConnectionsFromLane(fromLane)) {
623 : assert(c.toEdge != 0);
624 202754 : pos++;
625 202754 : const std::string foes = getFoesString(from, c, checkLaneFoes);
626 202754 : const std::string response = getResponseString(from, c, checkLaneFoes);
627 202754 : myFoes.push_back(foes);
628 202754 : myResponse.push_back(response);
629 202754 : myHaveVia.push_back(c.haveVia);
630 114628 : }
631 114628 : return pos;
632 : }
633 :
634 :
635 : int
636 1612 : NBRequest::computeCrossingResponse(const NBNode::Crossing& crossing, int pos) {
637 3224 : std::string foes(myJunction->getCrossings().size(), '0');
638 3224 : std::string response(myJunction->getCrossings().size(), '0');
639 : // conflicts with normal connections
640 7918 : for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
641 6306 : const NBEdge* from = *i;
642 20571 : for (int j = from->getNumLanes(); j-- > 0;) {
643 14265 : const std::vector<NBEdge::Connection>& connected = from->getConnectionsFromLane(j);
644 14265 : const int size = (int) connected.size();
645 32453 : for (int k = size; k-- > 0;) {
646 18188 : const NBEdge* to = connected[k].toEdge;
647 : bool foe = false;
648 38063 : for (const NBEdge* const e : crossing.edges) {
649 27897 : if (e == from || e == to) {
650 : foe = true;
651 : break;
652 : }
653 : }
654 18188 : foes += foe ? '1' : '0';
655 18188 : response += mustBrakeForCrossing(myJunction, from, to, crossing) || !foe ? '0' : '1';
656 : }
657 14265 : }
658 : }
659 1612 : pos++;
660 1612 : myResponse.push_back(response);
661 1612 : myFoes.push_back(foes);
662 1612 : myHaveVia.push_back(false);
663 1612 : return pos;
664 : }
665 :
666 :
667 : std::string
668 202754 : NBRequest::getResponseString(const NBEdge* const from, const NBEdge::Connection& c, const bool checkLaneFoes) const {
669 202754 : const NBEdge* const to = c.toEdge;
670 202754 : const int fromLane = c.fromLane;
671 202754 : const int toLane = c.toLane;
672 : int idx = 0;
673 202754 : if (to != nullptr) {
674 202754 : idx = getIndex(from, to);
675 : }
676 : std::string result;
677 202754 : const bool zipper = myJunction->getType() == SumoXMLNodeType::ZIPPER;
678 : // crossings
679 202754 : auto crossings = myJunction->getCrossings();
680 220942 : for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = crossings.rbegin(); i != crossings.rend(); i++) {
681 18188 : result += mustBrakeForCrossing(myJunction, from, to, **i) ? '1' : '0';
682 : }
683 : // normal connections
684 825045 : for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
685 : //const std::vector<NBEdge::Connection> &allConnections = (*i)->getConnections();
686 622291 : int noLanes = (*i)->getNumLanes();
687 1498995 : for (int j = noLanes; j-- > 0;) {
688 876704 : std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
689 876704 : int size = (int) connected.size();
690 3006852 : for (int k = size; k-- > 0;) {
691 2130148 : if (c.mayDefinitelyPass) {
692 : result += '0';
693 : #ifdef DEBUG_RESPONSE
694 : if (DEBUGCOND) {
695 : std::cout << " c=" << c.getDescription(from) << " pass\n";
696 : }
697 : #endif
698 2130027 : } else if ((*i) == from && fromLane == j) {
699 : // do not prohibit a connection by others from same lane
700 : // except for indirect turns
701 : #ifdef DEBUG_RESPONSE
702 : if (DEBUGCOND) {
703 : std::cout << " c=" << c.getDescription(from) << " prohibitC=" << connected[k].getDescription(*i)
704 : << " itc=" << indirectLeftTurnConflict(from, c, *i, connected[k], false)
705 : << "\n";
706 : }
707 : #endif
708 513483 : if (indirectLeftTurnConflict(from, c, *i, connected[k], false)) {
709 : result += '1';
710 : } else {
711 : result += '0';
712 : }
713 : } else {
714 : assert(connected[k].toEdge != 0);
715 1616544 : const int idx2 = getIndex(*i, connected[k].toEdge);
716 : assert(k < (int) connected.size());
717 : assert(idx < (int)(myIncoming.size() * myOutgoing.size()));
718 : assert(idx2 < (int)(myIncoming.size() * myOutgoing.size()));
719 : // check whether the connection is prohibited by another one
720 : #ifdef DEBUG_RESPONSE
721 : if (DEBUGCOND) {
722 : std::cout << " c=" << c.getDescription(from) << " prohibitC=" << connected[k].getDescription(*i)
723 : << " idx=" << idx << " idx2=" << idx2
724 : << " f=" << myForbids[idx2][idx]
725 : << " clf=" << checkLaneFoes
726 : << " clfbc=" << checkLaneFoesByClass(c, *i, connected[k])
727 : << " clfbcoop=" << checkLaneFoesByCooperation(from, c, *i, connected[k])
728 : << " lc=" << laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane)
729 : << " rtc=" << NBNode::rightTurnConflict(from, to, fromLane, *i, connected[k].toEdge, connected[k].fromLane)
730 : << " rtc2=" << rightTurnConflict(from, c, *i, connected[k])
731 : << " mc=" << mergeConflict(from, c, *i, connected[k], false)
732 : << " oltc=" << oppositeLeftTurnConflict(from, c, *i, connected[k], false)
733 : << " itc=" << indirectLeftTurnConflict(from, c, *i, connected[k], zipper)
734 : << " bc=" << bidiConflict(from, c, *i, connected[k], false)
735 : << " ec=" << (myJunction->extraConflict(c.tlLinkIndex, connected[k].tlLinkIndex) && (myForbids[idx2][idx] || myForbids[idx][idx2]))
736 : << " tlscc=" << myJunction->tlsStrandedConflict(from, c, *i, connected[k])
737 : << "\n";
738 : }
739 : #endif
740 3188002 : const bool hasLaneConflict = (!(checkLaneFoes || checkLaneFoesByClass(c, *i, connected[k])
741 1581732 : || checkLaneFoesByCooperation(from, c, *i, connected[k]))
742 1657789 : || laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane));
743 3233088 : if (((myForbids[idx2][idx] || (zipper && myForbids[idx][idx2])) && hasLaneConflict && !bidiConflict(*i, connected[k], from, c, false))
744 1286666 : || rightTurnConflict(from, c, *i, connected[k])
745 1286065 : || mergeConflict(from, c, *i, connected[k], zipper)
746 1285861 : || oppositeLeftTurnConflict(from, c, *i, connected[k], zipper)
747 1283199 : || indirectLeftTurnConflict(from, c, *i, connected[k], zipper)
748 1283199 : || bidiConflict(from, c, *i, connected[k], false)
749 : // the extra conflict could be specific to another connection within the same signal group
750 1283224 : || (myJunction->extraConflict(c.tlLinkIndex, connected[k].tlLinkIndex) && (myForbids[idx2][idx] || myForbids[idx][idx2]))
751 2899687 : || (myJunction->tlsStrandedConflict(from, c, *i, connected[k])
752 8312 : && laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane)
753 1629982 : && !OptionsCont::getOptions().getBool("tls.ignore-internal-junction-jam"))
754 : ) {
755 : result += '1';
756 : } else {
757 : result += '0';
758 : }
759 : }
760 : }
761 876704 : }
762 : }
763 202754 : return result;
764 202754 : }
765 :
766 :
767 : std::string
768 202754 : NBRequest::getFoesString(NBEdge* from, const NBEdge::Connection& c, const bool checkLaneFoes) const {
769 405508 : const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
770 : // remember the case when the lane is a "dead end" in the meaning that
771 : // vehicles must choose another lane to move over the following
772 : // junction
773 : // !!! move to forbidden
774 : std::string result;
775 : // crossings
776 202754 : auto crossings = myJunction->getCrossings();
777 220942 : for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = crossings.rbegin(); i != crossings.rend(); i++) {
778 : bool foes = false;
779 38063 : for (EdgeVector::const_iterator it_e = (**i).edges.begin(); it_e != (**i).edges.end(); ++it_e) {
780 27897 : if ((*it_e) == from || (*it_e) == c.toEdge) {
781 : foes = true;
782 : break;
783 : }
784 : }
785 18188 : result += foes ? '1' : '0';
786 : }
787 : // normal connections
788 825045 : for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
789 1498995 : for (int j = (*i)->getNumLanes() - 1; j >= 0; --j) {
790 876704 : const std::vector<NBEdge::Connection>& connected = (*i)->getConnectionsFromLane(j);
791 876704 : int size = (int) connected.size();
792 3006852 : for (int k = size; k-- > 0;) {
793 4199703 : const bool hasLaneConflict = (!(checkLaneFoes || checkLaneFoesByClass(c, *i, connected[k])
794 2083321 : || checkLaneFoesByCooperation(from, c, *i, connected[k]))
795 2179942 : || laneConflict(from, c.toEdge, c.toLane, *i, connected[k].toEdge, connected[k].toLane));
796 2811038 : if ((foes(from, c.toEdge, (*i), connected[k].toEdge) && hasLaneConflict)
797 1470619 : || rightTurnConflict(from, c, *i, connected[k])
798 1470018 : || myJunction->turnFoes(from, c.toEdge, c.fromLane, *i, connected[k].toEdge, connected[k].fromLane, lefthand)
799 1469351 : || mergeConflict(from, c, *i, connected[k], true)
800 1468955 : || oppositeLeftTurnConflict(from, c, *i, connected[k], true)
801 1463637 : || indirectLeftTurnConflict(from, c, *i, connected[k], true)
802 3593763 : || bidiConflict(from, c, *i, connected[k], true)
803 : ) {
804 : result += '1';
805 : } else {
806 : result += '0';
807 : }
808 : }
809 876704 : }
810 : }
811 202754 : return result;
812 202754 : }
813 :
814 :
815 : bool
816 2757849 : NBRequest::rightTurnConflict(const NBEdge* from, const NBEdge::Connection& con,
817 : const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon) const {
818 5515583 : return (!con.mayDefinitelyPass &&
819 2757734 : (NBNode::rightTurnConflict(from, con.toEdge, con.fromLane, prohibitorFrom, prohibitorCon.toEdge, prohibitorCon.fromLane)
820 : // reverse conflicht (override)
821 2756503 : || (prohibitorCon.mayDefinitelyPass &&
822 72 : NBNode::rightTurnConflict(prohibitorFrom, prohibitorCon.toEdge, prohibitorCon.fromLane, from, con.toEdge, con.fromLane))));
823 :
824 :
825 : }
826 :
827 :
828 : bool
829 4234039 : NBRequest::mergeConflict(const NBEdge* from, const NBEdge::Connection& con,
830 : const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
831 : if (from == prohibitorFrom
832 1186917 : && con.toEdge == prohibitorCon.toEdge
833 4679074 : && ((con.toLane == prohibitorCon.toLane
834 325487 : && con.fromLane != prohibitorCon.fromLane
835 1461 : && !myJunction->isConstantWidthTransition())
836 : // this is actually a crossing rather than a merger
837 443578 : || (con.fromLane > prohibitorCon.fromLane && con.toLane < prohibitorCon.toLane)
838 443570 : || (con.fromLane < prohibitorCon.fromLane && con.toLane > prohibitorCon.toLane))) {
839 1473 : if (foes) {
840 : return true;
841 : }
842 881 : if (prohibitorCon.mayDefinitelyPass) {
843 : return true;
844 : }
845 878 : if (con.mayDefinitelyPass) {
846 : return false;
847 : }
848 878 : const bool bike = from->getPermissions(con.fromLane) == SVC_BICYCLE;
849 878 : const bool prohibitorBike = prohibitorFrom->getPermissions(prohibitorCon.fromLane) == SVC_BICYCLE;
850 878 : if (myOutgoing.size() == 1) {
851 : // at on-ramp like situations, right lane should yield
852 51 : return bike || (con.fromLane < prohibitorCon.fromLane && !prohibitorBike);
853 : } else {
854 : // priority depends on direction:
855 : // for right turns the rightmost lane gets priority
856 : // otherwise the left lane
857 844 : LinkDirection dir = myJunction->getDirection(from, con.toEdge);
858 844 : if (dir == LinkDirection::RIGHT || dir == LinkDirection::PARTRIGHT) {
859 535 : return con.fromLane > prohibitorCon.fromLane;
860 : } else {
861 309 : if (myIncoming.size() == 1) {
862 : // at off-ramp like situations, right lane should pass unless it's a bicycle lane
863 6 : return bike || (con.fromLane > prohibitorCon.fromLane && !prohibitorBike);
864 : } else {
865 305 : return con.fromLane < prohibitorCon.fromLane;
866 : }
867 : }
868 : }
869 :
870 : } else {
871 4232566 : return false;
872 : }
873 : }
874 :
875 :
876 : bool
877 2754816 : NBRequest::oppositeLeftTurnConflict(const NBEdge* from, const NBEdge::Connection& con,
878 : const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
879 2754816 : LinkDirection dir = myJunction->getDirection(from, con.toEdge);
880 : // XXX lefthand issue (solve via #4256)
881 2754816 : if (dir != LinkDirection::LEFT && dir != LinkDirection::PARTLEFT) {
882 : return false;
883 : }
884 562129 : dir = myJunction->getDirection(prohibitorFrom, prohibitorCon.toEdge);
885 562129 : if (dir != LinkDirection::LEFT && dir != LinkDirection::PARTLEFT) {
886 : return false;
887 : }
888 155359 : if (from == prohibitorFrom || NBRequest::foes(from, con.toEdge, prohibitorFrom, prohibitorCon.toEdge)) {
889 : // not an opposite pair
890 87363 : return false;
891 : }
892 :
893 67996 : const double width1 = MIN2(from->getLaneWidth(con.fromLane) / 2, OptionsCont::getOptions().getFloat("internal-junctions.vehicle-width") / 2);
894 67996 : const double width2 = prohibitorCon.toEdge->getLaneWidth(prohibitorCon.toLane) / 2;
895 : PositionVector shape = con.shape;
896 67996 : shape.append(con.viaShape);
897 : PositionVector otherShape = prohibitorCon.shape;
898 67996 : otherShape.append(prohibitorCon.viaShape);
899 67996 : if (shape.size() == 0 || otherShape.size() == 0) {
900 : // no internal lanes built
901 : return false;
902 : }
903 21908 : const double minDV = NBEdge::firstIntersection(shape, otherShape, width1, width2);
904 21908 : if (minDV < shape.length() - POSITION_EPS && minDV > POSITION_EPS) {
905 : // break symmetry using edge id
906 10636 : return foes || from->getID() < prohibitorFrom->getID();
907 : }
908 : return false;
909 67996 : }
910 :
911 : bool
912 3696139 : NBRequest::indirectLeftTurnConflict(const NBEdge* from, const NBEdge::Connection& con,
913 : const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
914 3696139 : if (from == prohibitorFrom) {
915 1397871 : if (con.toEdge == prohibitorCon.toEdge) {
916 : return false;
917 837168 : } else if (con.indirectLeft) {
918 126 : LinkDirection dir = myJunction->getDirection(prohibitorFrom, prohibitorCon.toEdge);
919 126 : return (dir == LinkDirection::STRAIGHT);
920 837042 : } else if (foes && prohibitorCon.indirectLeft) {
921 27 : LinkDirection dir = myJunction->getDirection(from, con.toEdge);
922 27 : return (dir == LinkDirection::STRAIGHT);
923 : }
924 : }
925 : return false;
926 : }
927 :
928 : bool
929 3814070 : NBRequest::bidiConflict(const NBEdge* from, const NBEdge::Connection& con,
930 : const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
931 3814070 : if (from == prohibitorFrom) {
932 : return false;
933 : }
934 2842417 : if (isRailway(from->getPermissions())) {
935 : // railways manage right-of-way via signals
936 : return false;
937 : }
938 1344183 : if ((foes && (from->getBidiEdge() == prohibitorCon.toEdge))
939 4163023 : || prohibitorFrom->getBidiEdge() == con.toEdge) {
940 1044 : const bool fromBidi = from->getLaneShape(con.fromLane).reverse().almostSame(
941 522 : prohibitorCon.toEdge->getLaneShape(prohibitorCon.toLane), POSITION_EPS);
942 1044 : const bool prohibitorFromBidi = prohibitorFrom->getLaneShape(prohibitorCon.fromLane).reverse().almostSame(
943 522 : con.toEdge->getLaneShape(con.toLane), POSITION_EPS);
944 522 : if (!foes && fromBidi && prohibitorFromBidi) {
945 : // do not create a symmetrical conflict
946 : return false;
947 : }
948 506 : if (prohibitorFromBidi &&
949 613 : prohibitorFrom->getLaneShape(prohibitorCon.fromLane).reverse().almostSame(
950 107 : prohibitorCon.toEdge->getLaneShape(prohibitorCon.toLane), POSITION_EPS)) {
951 : // prohibitor has a bidi-turnaround
952 : return false;
953 : }
954 :
955 461 : return fromBidi || prohibitorFromBidi;
956 : }
957 : return false;
958 : }
959 :
960 : bool
961 3722652 : NBRequest::checkLaneFoesByClass(const NBEdge::Connection& con,
962 : const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon) const {
963 3722652 : if (con.toEdge != prohibitorCon.toEdge) {
964 : return false;
965 : }
966 1056632 : SVCPermissions svc = con.toEdge->getPermissions(con.toLane);
967 1056632 : SVCPermissions svc2 = prohibitorFrom->getPermissions(prohibitorCon.fromLane) & prohibitorCon.toEdge->getPermissions(prohibitorCon.toLane);
968 : // check for lane level conflict if the only common classes are bicycles or pedestrians
969 1056632 : return ((svc & svc2 & ~(SVC_BICYCLE | SVC_PEDESTRIAN)) == 0
970 : // or if the connection is to a dedicated lane whereas the prohibitor is a "general" lane
971 1056632 : || (((svc & SVC_PASSENGER) == 0) && ((svc2 & SVC_PASSENGER) != 0)));
972 : }
973 :
974 :
975 : bool
976 3665053 : NBRequest::checkLaneFoesByCooperation(const NBEdge* from, const NBEdge::Connection& con,
977 : const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon) const {
978 3665053 : if (con.toEdge != prohibitorCon.toEdge) {
979 : return false;
980 : }
981 : // if from and prohibitorFrom target distinct lanes for all their
982 : // connections to the common target edge, cooperation is possible
983 : // (and should always happen unless the connections cross for some byzantine reason)
984 :
985 : std::set<int> fromTargetLanes;
986 4865709 : for (const NBEdge::Connection& c : from->getConnections()) {
987 3866676 : if (c.toEdge == con.toEdge) {
988 1452422 : fromTargetLanes.insert(c.toLane);
989 : }
990 : }
991 2364282 : for (const NBEdge::Connection& c : prohibitorFrom->getConnections()) {
992 2330842 : if (c.toEdge == con.toEdge && fromTargetLanes.count(c.toLane) != 0) {
993 : //std::cout << " con=" << con->getDescription(from) << " foe=" << prohibitorCon.getDescription(prohibitorFrom)
994 : // << " no cooperation (targets=" << joinToString(fromTargetLanes, ' ') << " index=" << c.toLane << "\n";
995 : return false;
996 : }
997 : }
998 : return true;
999 : }
1000 :
1001 :
1002 : bool
1003 123391 : NBRequest::laneConflict(const NBEdge* from, const NBEdge* to, int toLane,
1004 : const NBEdge* prohibitorFrom, const NBEdge* prohibitorTo, int prohibitorToLane) const {
1005 123391 : if (to != prohibitorTo) {
1006 : return true;
1007 : }
1008 : // since we know that the edge2edge connections are in conflict, the only
1009 : // situation in which the lane2lane connections can be conflict-free is, if
1010 : // they target the same edge but do not cross each other
1011 106440 : double angle = NBHelpers::relAngle(
1012 : from->getAngleAtNode(from->getToNode()), to->getAngleAtNode(to->getFromNode()));
1013 106440 : if (angle == 180) {
1014 : angle = -180; // turnarounds are left turns
1015 : }
1016 106440 : const double prohibitorAngle = NBHelpers::relAngle(
1017 : prohibitorFrom->getAngleAtNode(prohibitorFrom->getToNode()), to->getAngleAtNode(to->getFromNode()));
1018 106440 : const bool rightOfProhibitor = prohibitorFrom->isTurningDirectionAt(to)
1019 106440 : || (angle > prohibitorAngle && !from->isTurningDirectionAt(to));
1020 106440 : return rightOfProhibitor ? toLane >= prohibitorToLane : toLane <= prohibitorToLane;
1021 : }
1022 :
1023 : int
1024 16711916 : NBRequest::getIndex(const NBEdge* const from, const NBEdge* const to) const {
1025 16711916 : EdgeVector::const_iterator fp = std::find(myIncoming.begin(), myIncoming.end(), from);
1026 16711916 : EdgeVector::const_iterator tp = std::find(myOutgoing.begin(), myOutgoing.end(), to);
1027 16711916 : if (fp == myIncoming.end() || tp == myOutgoing.end()) {
1028 : return -1;
1029 : }
1030 : // compute the index
1031 16557198 : return (int)(distance(myIncoming.begin(), fp) * myOutgoing.size() + distance(myOutgoing.begin(), tp));
1032 : }
1033 :
1034 :
1035 : std::ostream&
1036 0 : operator<<(std::ostream& os, const NBRequest& r) {
1037 0 : int variations = r.numLinks();
1038 0 : for (int i = 0; i < variations; i++) {
1039 0 : os << i << ' ';
1040 0 : for (int j = 0; j < variations; j++) {
1041 0 : if (r.myForbids[i][j]) {
1042 0 : os << '1';
1043 : } else {
1044 0 : os << '0';
1045 : }
1046 : }
1047 : os << std::endl;
1048 : }
1049 : os << std::endl;
1050 0 : return os;
1051 : }
1052 :
1053 :
1054 : bool
1055 227648 : NBRequest::mustBrake(const NBEdge* const from, const NBEdge* const to, int fromLane, int toLane, bool includePedCrossings) const {
1056 227648 : NBEdge::Connection con(fromLane, const_cast<NBEdge*>(to), toLane);
1057 227648 : const int linkIndex = myJunction->getConnectionIndex(from, con);
1058 227648 : if (linkIndex >= 0 && (int)myResponse.size() > linkIndex) {
1059 205806 : std::string response = getResponse(linkIndex);
1060 205806 : if (!includePedCrossings) {
1061 220 : response = response.substr(0, response.size() - myJunction->getCrossings().size());
1062 : }
1063 205806 : if (response.find_first_of("1") == std::string::npos) {
1064 : return false;
1065 99701 : } else if (!myJunction->isTLControlled()) {
1066 : return true;
1067 : }
1068 : // if the link must respond it could also be due to a tlsConflict. This
1069 : // must not carry over the off-state response so we continue with
1070 : // the regular check
1071 : }
1072 : // get the indices
1073 36283 : int idx2 = getIndex(from, to);
1074 36283 : if (idx2 == -1) {
1075 : return false;
1076 : }
1077 : // go through all (existing) connections;
1078 : // check whether any of these forbids the one to determine
1079 : assert(idx2 < (int)(myIncoming.size()*myOutgoing.size()));
1080 239007 : for (int idx1 = 0; idx1 < numLinks(); idx1++) {
1081 : //assert(myDone[idx1][idx2]);
1082 329959 : if (myDone[idx1][idx2] && myForbids[idx1][idx2]) {
1083 : return true;
1084 : }
1085 : }
1086 : // maybe we need to brake for a pedestrian crossing
1087 2670 : if (includePedCrossings) {
1088 2278 : auto crossings = myJunction->getCrossings();
1089 2948 : for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = crossings.rbegin(); i != crossings.rend(); i++) {
1090 1488 : if (mustBrakeForCrossing(myJunction, from, to, **i)) {
1091 : return true;
1092 : }
1093 : }
1094 2278 : }
1095 : // maybe we need to brake due to a right-turn conflict with straight-going
1096 : // bicycles
1097 1852 : const NBEdge::Connection& queryCon = from->getConnection(fromLane, to, toLane);
1098 1852 : LinkDirection dir = myJunction->getDirection(from, to);
1099 1852 : if (dir == LinkDirection::RIGHT || dir == LinkDirection::PARTRIGHT) {
1100 631 : for (const NBEdge::Connection& fromCon : from->getConnections()) {
1101 564 : if (rightTurnConflict(from, queryCon, from, fromCon)) {
1102 : return true;
1103 : }
1104 : }
1105 : }
1106 : // maybe we need to brake due to a merge conflict
1107 9232 : for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
1108 7500 : int noLanes = (*i)->getNumLanes();
1109 22119 : for (int j = noLanes; j-- > 0;) {
1110 14632 : std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
1111 14632 : const int size = (int) connected.size();
1112 45669 : for (int k = size; k-- > 0;) {
1113 38946 : if ((*i) == from && fromLane != j
1114 34625 : && mergeConflict(from, queryCon, *i, connected[k], myJunction->getType() == SumoXMLNodeType::ZIPPER)) {
1115 : return true;
1116 : }
1117 : }
1118 14632 : }
1119 : }
1120 : // maybe we need to brake due to a zipper conflict
1121 1732 : if (myJunction->getType() == SumoXMLNodeType::ZIPPER) {
1122 0 : for (int idx1 = 0; idx1 < numLinks(); idx1++) {
1123 : //assert(myDone[idx1][idx2]);
1124 0 : if (myDone[idx1][idx2] && myForbids[idx2][idx1]) {
1125 : return true;
1126 : }
1127 : }
1128 : }
1129 : return false;
1130 227648 : }
1131 :
1132 :
1133 : bool
1134 44482 : NBRequest::mustBrakeForCrossing(const NBNode* node, const NBEdge* const from, const NBEdge* const to, const NBNode::Crossing& crossing) {
1135 44482 : const LinkDirection dir = node->getDirection(from, to);
1136 44482 : const bool mustYield = dir == LinkDirection::LEFT || dir == LinkDirection::RIGHT;
1137 44482 : if (crossing.priority || mustYield) {
1138 77466 : for (const NBEdge* const e : crossing.edges) {
1139 : // left and right turns must yield to unprioritized crossings only on their destination edge
1140 53801 : if ((e == from && crossing.priority) || e == to) {
1141 : return true;
1142 : }
1143 : }
1144 : }
1145 : return false;
1146 : }
1147 :
1148 :
1149 : bool
1150 0 : NBRequest::mustBrake(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
1151 : const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo) const {
1152 : // get the indices
1153 0 : int idx1 = getIndex(possProhibitorFrom, possProhibitorTo);
1154 0 : int idx2 = getIndex(possProhibitedFrom, possProhibitedTo);
1155 0 : return (myForbids[idx2][idx1]);
1156 : }
1157 :
1158 :
1159 : void
1160 1812 : NBRequest::reportWarnings() {
1161 : // check if any errors occurred on build the link prohibitions
1162 1812 : if (myNotBuild != 0) {
1163 0 : WRITE_WARNING(toString(myNotBuild) + " of " + toString(myNotBuild + myGoodBuilds) + " prohibitions were not build.");
1164 : }
1165 1812 : }
1166 :
1167 :
1168 : void
1169 42230 : NBRequest::resetCooperating() {
1170 : // map from edge to number of incoming connections
1171 : std::map<const NBEdge*, int> incomingCount; // initialized to 0
1172 : // map from edge to indices of approached lanes
1173 : std::map<const NBEdge*, std::set<int> > approachedLanes;
1174 : // map from edge to list of incoming edges
1175 : std::map<const NBEdge*, std::vector<const NBEdge*> > incomingEdges;
1176 129077 : for (const NBEdge* const e : myIncoming) {
1177 289601 : for (const NBEdge::Connection& con : e->getConnections()) {
1178 202754 : incomingCount[con.toEdge]++;
1179 202754 : approachedLanes[con.toEdge].insert(con.toLane);
1180 202754 : incomingEdges[con.toEdge].push_back(e);
1181 : }
1182 : }
1183 126883 : for (std::map<const NBEdge*, int>::iterator it = incomingCount.begin(); it != incomingCount.end(); ++it) {
1184 84653 : const NBEdge* const to = it->first;
1185 : // we cannot test against to->getNumLanes() since not all lanes may be used
1186 84653 : if ((int)approachedLanes[to].size() >= it->second) {
1187 35597 : const std::vector<const NBEdge*>& incoming = incomingEdges[to];
1188 : // make these connections mutually unconflicting
1189 81648 : for (const NBEdge* const e1 : incoming) {
1190 124454 : for (const NBEdge* const e2 : incoming) {
1191 78403 : myForbids[getIndex(e1, to)][getIndex(e2, to)] = false;
1192 : #ifdef DEBUG_SETBLOCKING
1193 : if (DEBUGCOND) std::cout << "resetCooperating"
1194 : << " 1:" << e1->getID() << "->" << to->getID()
1195 : << " 2:" << e2->getID() << "->" << to->getID()
1196 : << "\n";
1197 : #endif
1198 : }
1199 : }
1200 : }
1201 : }
1202 42230 : }
1203 :
1204 :
1205 : bool
1206 42412 : NBRequest::hasConflict() const {
1207 83488 : for (int i = 0; i < (int)myFoes.size(); i++) {
1208 60782 : if (hasConflictAtLink(i)) {
1209 : return true;
1210 : }
1211 : }
1212 : return false;
1213 : }
1214 :
1215 : bool
1216 61993 : NBRequest::hasConflictAtLink(int linkIndex) const {
1217 61993 : return myFoes[linkIndex].find_first_of("1") != std::string::npos;
1218 : }
1219 :
1220 : int
1221 287666 : NBRequest::numLinks() const {
1222 287666 : return (int)(myIncoming.size() * myOutgoing.size() + myJunction->getCrossings().size());
1223 : }
1224 :
1225 :
1226 : /****************************************************************************/
|