Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2002-2026 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 MSLink.h
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @date Sept 2002
19 : ///
20 : // A connection between lanes
21 : /****************************************************************************/
22 : #pragma once
23 : #include <config.h>
24 :
25 : #include <vector>
26 : #include <set>
27 : #include <utils/common/SUMOTime.h>
28 : #include <utils/common/SUMOVehicleClass.h>
29 : #include <utils/vehicle/SUMOVehicle.h>
30 : #include <utils/xml/SUMOXMLDefinitions.h>
31 : #include "MSLane.h"
32 :
33 :
34 : // ===========================================================================
35 : // class declarations
36 : // ===========================================================================
37 : class MSLane;
38 : class MSJunction;
39 : class MSVehicle;
40 : class MSPerson;
41 : class OutputDevice;
42 : class MSTrafficLightLogic;
43 :
44 :
45 : // ===========================================================================
46 : // class definitions
47 : // ===========================================================================
48 : /**
49 : * @class MSLinks
50 : * @brief A connection between lanes
51 : *
52 : * A link is basically a connection between two lanes, stored within the
53 : * originating (the one that is being left) lane and pointing to the
54 : * approached lane. When using inner-junction simulation, additionally
55 : * a "via-lane" is stored, the one that is used to cross the junction
56 : * and which represents the links shape.
57 : *
58 : * Because right-of-way rules are controlled by the junctions, the link
59 : * stores the information about where to write information about approaching
60 : * vehicles (the "request") and where to get the information whether the
61 : * vehicle really may drive (the "respond").
62 : *
63 : * Because a link is a connection over a junction, it basically also has a
64 : * length. This length is needed to assure that vehicles have the correct halting
65 : * distance before approaching the link. In the case of using internal lanes,
66 : * the link's length is 0.
67 : */
68 : class MSLink {
69 : public:
70 :
71 : /** @enum LinkLeaderFlag
72 : * @brief additional information for link leaders
73 : */
74 : enum LinkLeaderFlag {
75 : /// @brief vehicle is in the way
76 : LL_IN_THE_WAY = 1 << 0,
77 : /// @brief link leader is passing from left to right
78 : LL_FROM_LEFT = 1 << 1,
79 : /// @brief link leader is coming from the same (normal) lane
80 : LL_SAME_SOURCE = 1 << 2,
81 : /// @brief link leader is targeting the same outgoing lane
82 : LL_SAME_TARGET = 1 << 3
83 : };
84 :
85 : struct LinkLeader {
86 22269393 : LinkLeader(MSVehicle* _veh, double _gap, double _distToCrossing, int _llFlags = LL_FROM_LEFT, double _latOffst = 0) :
87 22269393 : vehAndGap(std::make_pair(_veh, _gap)),
88 22269393 : distToCrossing(_distToCrossing),
89 22269393 : llFlags(_llFlags),
90 22269393 : latOffset(_latOffst)
91 : { }
92 :
93 : inline bool fromLeft() const {
94 109620 : return (llFlags & LL_FROM_LEFT) != 0;
95 : }
96 : inline bool inTheWay() const {
97 67719 : return (llFlags & LL_IN_THE_WAY) != 0;
98 : }
99 : inline bool sameTarget() const {
100 863671 : return (llFlags & LL_SAME_TARGET) != 0;
101 : }
102 : inline bool sameSource() const {
103 520576 : return (llFlags & LL_SAME_SOURCE) != 0;
104 : }
105 :
106 : std::pair<MSVehicle*, double> vehAndGap;
107 : double distToCrossing;
108 : int llFlags;
109 : double latOffset;
110 :
111 : };
112 :
113 : typedef std::vector<LinkLeader> LinkLeaders;
114 :
115 : /** @struct ApproachingVehicleInformation
116 : * @brief A structure holding the information about vehicles approaching a link
117 : */
118 : struct ApproachingVehicleInformation {
119 : /** @brief Constructor
120 : * @param[in] waitingTime The time during which the vehicle is waiting at this link
121 : * this needs to be placed here because MSVehicle::myWaitingTime is updated in between
122 : * calls to opened() causing order dependencies
123 : **/
124 : ApproachingVehicleInformation(const SUMOTime _arrivalTime, const SUMOTime _leavingTime,
125 : const double _arrivalSpeed, const double _leaveSpeed,
126 : const bool _willPass,
127 : const double _arrivalSpeedBraking,
128 : const SUMOTime _waitingTime,
129 : const double _dist,
130 : const double _speed,
131 : const double _latOffset
132 875158448 : ) :
133 875158448 : arrivalTime(_arrivalTime), leavingTime(_leavingTime),
134 875158448 : arrivalSpeed(_arrivalSpeed), leaveSpeed(_leaveSpeed),
135 875158448 : willPass(_willPass),
136 875158448 : arrivalSpeedBraking(_arrivalSpeedBraking),
137 875158448 : waitingTime(_waitingTime),
138 875158448 : dist(_dist),
139 875158448 : speed(_speed),
140 872237891 : latOffset(_latOffset) {
141 2920557 : }
142 :
143 : /// @brief The time the vehicle's front arrives at the link
144 : const SUMOTime arrivalTime;
145 : /// @brief The estimated time at which the vehicle leaves the link
146 : const SUMOTime leavingTime;
147 : /// @brief The estimated speed with which the vehicle arrives at the link (for headway computation)
148 : const double arrivalSpeed;
149 : /// @brief The estimated speed with which the vehicle leaves the link (for headway computation)
150 : const double leaveSpeed;
151 : /// @brief Whether the vehicle wants to pass the link (@todo: check semantics)
152 : const bool willPass;
153 : /// @brief The estimated speed with which the vehicle arrives at the link if it starts braking(for headway computation)
154 : const double arrivalSpeedBraking;
155 : /// @brief The waiting duration at the current link
156 : const SUMOTime waitingTime;
157 : /// @brief The distance up to the current link
158 : const double dist;
159 : /// @brief The current speed
160 : const double speed;
161 : /// @brief The lateral offset from the center of the entering lane
162 : const double latOffset;
163 :
164 : };
165 :
166 : /** @struct ApproachingPersonInformation
167 : * @brief A structure holding the information about persons approaching a pedestrian crossing link
168 : */
169 : struct ApproachingPersonInformation {
170 : /** @brief Constructor
171 : * @param[in] waitingTime The time during which the vehicle is waiting at this link
172 : * this needs to be placed here because MSVehicle::myWaitingTime is updated in between
173 : * calls to opened() causing order dependencies
174 : **/
175 487479 : ApproachingPersonInformation(const SUMOTime _arrivalTime, const SUMOTime _leavingTime) :
176 487479 : arrivalTime(_arrivalTime), leavingTime(_leavingTime) {}
177 : /// @brief The time the vehicle's front arrives at the link
178 : const SUMOTime arrivalTime;
179 : /// @brief The estimated time at which the vehicle leaves the link
180 : const SUMOTime leavingTime;
181 : };
182 :
183 : typedef std::map<const SUMOVehicle*, const ApproachingVehicleInformation, ComparatorNumericalIdLess> ApproachInfos;
184 : typedef std::vector<const SUMOTrafficObject*> BlockingFoes;
185 : typedef std::map<const MSPerson*, ApproachingPersonInformation> PersonApproachInfos;
186 :
187 : enum ConflictFlag {
188 : CONFLICT_DEFAULT,
189 : CONFLICT_DUMMY_MERGE,
190 : CONFLICT_NO_INTERSECTION,
191 : CONFLICT_STOP_AT_INTERNAL_JUNCTION,
192 : CONFLICT_SIBLING_CONTINUATION
193 : };
194 :
195 : /// @brief pre-computed information for conflict points
196 : struct ConflictInfo {
197 :
198 4722243 : ConflictInfo(double lbc, double cs, ConflictFlag fl = CONFLICT_DEFAULT) :
199 4499784 : foeConflictIndex(-1),
200 4722243 : lengthBehindCrossing(lbc),
201 4722243 : conflictSize(cs),
202 4722243 : flag(fl)
203 : {}
204 : /// @brief the conflict from the perspective of the foe
205 : int foeConflictIndex;
206 : /// @brief length of internal lane after the crossing point
207 : double lengthBehindCrossing;
208 : /// @brief the length of the conflict space
209 : double conflictSize;
210 :
211 : ConflictFlag flag;
212 :
213 : double getFoeLengthBehindCrossing(const MSLink* foeExitLink) const;
214 : double getFoeConflictSize(const MSLink* foeExitLink) const;
215 : double getLengthBehindCrossing(const MSLink* exitLink) const;
216 : };
217 :
218 : /// @brief holds user defined conflict positions (must be interpreted for the correct exitLink)
219 : struct CustomConflict {
220 4 : CustomConflict(const MSLane* f, const MSLane* t, double s, double e) :
221 4 : from(f), to(t), startPos(s), endPos(e) {}
222 : const MSLane* from;
223 : const MSLane* to;
224 : double startPos;
225 : double endPos;
226 : };
227 :
228 : /// @brief Function-object for stable sorting MSLinks with numerical lane ids
229 : struct ComparatorNumericalLaneIdLess {
230 : bool operator()(const MSLink* const a, const MSLink* const b) const {
231 : return (a->getLane()->getNumericalID() < b->getLane()->getNumericalID())
232 27622 : || (a->getLane()->getNumericalID() == b->getLane()->getNumericalID() && a->getIndex() < b->getIndex());
233 : }
234 : };
235 :
236 :
237 : /** @brief Constructor for simulation which uses internal lanes
238 : *
239 : * @param[in] succLane The lane approached by this link
240 : * @param[in] via The lane to use within the junction
241 : * @param[in] dir The direction of this link
242 : * @param[in] state The state of this link
243 : * @param[in] length The length of this link
244 : */
245 : MSLink(MSLane* predLane,
246 : MSLane* succLane,
247 : MSLane* via,
248 : LinkDirection dir,
249 : LinkState state,
250 : double length,
251 : double foeVisibilityDistance,
252 : bool keepClear,
253 : MSTrafficLightLogic* logic,
254 : int tlLinkIdx,
255 : bool indirect);
256 :
257 :
258 : /// @brief Destructor
259 : ~MSLink();
260 :
261 : void addCustomConflict(const MSLane* from, const MSLane* to, double startPos, double endPos);
262 :
263 : /** @brief Sets the request information
264 : *
265 : * Because traffic lights and junction logics are loaded after links,
266 : * we have to assign the information about the right-of-way
267 : * requests and responses after the initialisation.
268 : * @todo Unsecure!
269 : */
270 : void setRequestInformation(int index, bool hasFoes, bool isCont,
271 : const std::vector<MSLink*>& foeLinks, const std::vector<MSLane*>& foeLanes,
272 : MSLane* internalLaneBefore = 0);
273 :
274 : /// @brief add walkingarea as foe (when entering the junction)
275 : void addWalkingAreaFoe(const MSLane* lane) {
276 5612 : myWalkingAreaFoe = lane;
277 5612 : }
278 :
279 : /// @brief add walkingarea as foe (when leaving the junction)
280 : void addWalkingAreaFoeExit(const MSLane* lane) {
281 5694 : myWalkingAreaFoeExit = lane;
282 5694 : }
283 :
284 : /// @brief get walkingarea as foes
285 : const MSLane* getWalkingAreaFoe() {
286 3000761 : return myWalkingAreaFoe;
287 : }
288 : const MSLane* getWalkingAreaFoeExit() {
289 2999853 : return myWalkingAreaFoeExit;
290 : }
291 :
292 : /** @brief Sets the information about an approaching vehicle
293 : *
294 : * The information is stored in myApproachingVehicles.
295 : */
296 : void setApproaching(const SUMOVehicle* approaching, const SUMOTime arrivalTime,
297 : const double arrivalSpeed, const double leaveSpeed, const bool setRequest,
298 : const double arrivalSpeedBraking,
299 : const SUMOTime waitingTime, double dist, double latOffset);
300 :
301 : /** @brief Sets the information about an approaching vehicle */
302 : void setApproaching(const SUMOVehicle* approaching, ApproachingVehicleInformation ai);
303 :
304 : /** @brief Sets the information about an approaching person (only for a pedestrian crossing) */
305 : void setApproachingPerson(const MSPerson* approaching, const SUMOTime arrivalTime, const SUMOTime leaveTime);
306 :
307 : /// @brief removes the vehicle from myApproachingVehicles
308 : void removeApproaching(const SUMOVehicle* veh);
309 :
310 : /// @brief removes the person from myApproachingPersons
311 : void removeApproachingPerson(const MSPerson* person);
312 :
313 : /* @brief return information about this vehicle if it is registered as
314 : * approaching (dummy values otherwise)
315 : * @note used for visualisation of link items */
316 : ApproachingVehicleInformation getApproaching(const SUMOVehicle* veh) const;
317 : const ApproachingVehicleInformation* getApproachingPtr(const SUMOVehicle* veh) const;
318 :
319 : /// @brief return all approaching vehicles
320 : const ApproachInfos& getApproaching() const {
321 : return myApproachingVehicles;
322 : }
323 :
324 : /// @brief return all approaching vehicles
325 : const PersonApproachInfos* getApproachingPersons() const {
326 81181 : return myApproachingPersons;
327 : }
328 :
329 : /** @brief Remove all approaching vehicles before quick-loading state */
330 : void clearState();
331 :
332 : /** @brief Returns the information whether the link may be passed
333 : *
334 : * Valid after the junctions have set their reponds
335 : *
336 : * @param[in] collectFoes If a vector is passed, all blocking foes are collected and inserted into this vector
337 : * @return Whether this link may be passed.
338 : */
339 : bool opened(SUMOTime arrivalTime, double arrivalSpeed, double leaveSpeed, double vehicleLength,
340 : double impatience, double decel, SUMOTime waitingTime,
341 : double posLat = 0,
342 : BlockingFoes* collectFoes = nullptr,
343 : bool ignoreRed = false,
344 : const SUMOTrafficObject* ego = nullptr,
345 : double dist = -1) const;
346 :
347 : /** @brief Returns the information whether this link is blocked
348 : * Valid after the vehicles have set their requests
349 : * @param[in] arrivalTime The arrivalTime of the vehicle who checks for an approaching foe
350 : * @param[in] leaveTime The leaveTime of the vehicle who checks for an approaching foe
351 : * @param[in] arrivalSpeed The speed with which the checking vehicle plans to arrive at the link
352 : * @param[in] leaveSpeed The speed with which the checking vehicle plans to leave the link
353 : * @param[in] sameTargetLane Whether the link that calls this method has the same target lane as this link
354 : * @param[in] impatience The impatience of the checking vehicle
355 : * @param[in] decel The maximum deceleration of the checking vehicle
356 : * @param[in] waitingTime The waiting time of the checking vehicle
357 : * @param[in] collectFoes If a vector is passed the return value is always False, instead all blocking foes are collected and inserted into this vector
358 : * @param[in] lastWasContRed Whether the link which is checked, is an internal junction link where the entry has red
359 : * @return Whether this link is blocked
360 : * @note Since this needs to be called without a SUMOVehicle (TraCI), we cannot simply pass the checking vehicle itself
361 : **/
362 : bool blockedAtTime(SUMOTime arrivalTime, SUMOTime leaveTime, double arrivalSpeed, double leaveSpeed,
363 : bool sameTargetLane, double impatience, double decel, SUMOTime waitingTime,
364 : BlockingFoes* collectFoes = nullptr, const SUMOTrafficObject* ego = nullptr, bool lastWasContRed = false, double dist = -1) const;
365 :
366 :
367 : /** @brief Returns the information whether a vehicle is approaching on one of the link's foe streams
368 : *
369 : * Valid after the vehicles have set their requests
370 : * @param[in] arrivalTime The arrivalTime of the vehicle who checks for an approaching foe
371 : * @param[in] leaveTime The leaveTime of the vehicle who checks for an approaching foe
372 : * @param[in] speed The speed with which the checking vehicle plans to leave the link
373 : * @param[in] decel The maximum deceleration of the checking vehicle
374 : * @return Whether a foe of this link is approaching
375 : */
376 : bool hasApproachingFoe(SUMOTime arrivalTime, SUMOTime leaveTime, double speed, double decel) const;
377 :
378 : /** @brief get the foe vehicle that is closest to the intersection or nullptr along with the foe link
379 : * This function is used for finding circular deadlock at right_before_left junctions
380 : * @param[in] wrapAround The link on which the ego vehicle wants to enter the junction
381 : */
382 : std::pair<const SUMOVehicle*, const MSLink*> getFirstApproachingFoe(const MSLink* wrapAround) const;
383 :
384 : MSJunction* getJunction() const {
385 5350997 : return myJunction;
386 : }
387 :
388 :
389 : /** @brief Returns the current state of the link
390 : *
391 : * @return The current state of this link
392 : */
393 : LinkState getState() const {
394 1698688916 : return myState;
395 : }
396 :
397 :
398 : /** @brief Returns the off-state for the link
399 : *
400 : * @return The current state of this link
401 : */
402 : LinkState getOffState() const {
403 3264289 : return myOffState;
404 : }
405 :
406 : /** @brief Returns the last green state of the link
407 : *
408 : * @return The last green state of this link
409 : */
410 : LinkState getLastGreenState() const {
411 1260708 : return myLastGreenState;
412 : }
413 :
414 :
415 : //@brief Returns the time of the last state change
416 : inline SUMOTime getLastStateChange() const {
417 122716 : return myLastStateChange;
418 : }
419 :
420 :
421 : /** @brief Returns the direction the vehicle passing this link take
422 : *
423 : * @return The direction of this link
424 : */
425 : inline LinkDirection getDirection() const {
426 200510423 : return myDirection;
427 : }
428 :
429 :
430 :
431 : /** @brief Sets the current tl-state
432 : *
433 : * @param[in] state The current state of the link
434 : * @param[in] t The time of the state change
435 : */
436 : void setTLState(LinkState state, SUMOTime t);
437 :
438 : /** @brief Sets the currently active tlLogic
439 : * @param[in] logic The currently active logic
440 : */
441 : void setTLLogic(const MSTrafficLightLogic* logic);
442 :
443 : /** @brief Returns the connected lane
444 : *
445 : * @return The lane approached by this link
446 : */
447 : inline MSLane* getLane() const {
448 4022149635 : return myLane;
449 : }
450 :
451 :
452 : /** @brief Returns the respond index (for visualization)
453 : *
454 : * @return The respond index for this link
455 : */
456 : inline int getIndex() const {
457 2687756 : return myIndex;
458 : }
459 :
460 : /** @brief Returns the TLS index */
461 : inline int getTLIndex() const {
462 34428119 : return myTLIndex;
463 : }
464 :
465 : /** @brief Returns the TLS index */
466 : inline const MSTrafficLightLogic* getTLLogic() const {
467 20362519 : return myLogic;
468 : }
469 :
470 : /** @brief Returns whether this link is a major link
471 : * @return Whether the link has a large priority
472 : */
473 : inline bool havePriority() const {
474 4421426037 : return myState >= 'A' && myState <= 'Z';
475 : }
476 :
477 : inline bool haveOffPriority() const {
478 40 : return myOffState >= 'A' && myOffState <= 'Z';
479 : }
480 :
481 : /** @brief Returns whether this link is blocked by a red (or redyellow) traffic light
482 : * @return Whether the link has a red light
483 : */
484 : inline bool haveRed() const {
485 1549371279 : return myState == LINKSTATE_TL_RED || myState == LINKSTATE_TL_REDYELLOW;
486 : }
487 :
488 : inline bool haveYellow() const {
489 1480149206 : return myState == LINKSTATE_TL_YELLOW_MINOR || myState == LINKSTATE_TL_YELLOW_MAJOR;
490 : }
491 :
492 : inline bool haveGreen() const {
493 105157215 : return myState == LINKSTATE_TL_GREEN_MAJOR || myState == LINKSTATE_TL_GREEN_MINOR;
494 : }
495 :
496 : inline bool mustStop() const {
497 635265358 : return myState == LINKSTATE_STOP || myState == LINKSTATE_ALLWAY_STOP;
498 : }
499 :
500 : inline bool isTLSControlled() const {
501 1976427 : return myLogic != 0;
502 : }
503 :
504 : inline bool isTurnaround() const {
505 83267163 : return myDirection == LinkDirection::TURN || myDirection == LinkDirection::TURN_LEFTHAND;
506 : }
507 :
508 : /** @brief Returns the length of this link
509 : *
510 : * @return The length of this link
511 : */
512 : double getLength() const {
513 2353280740 : return myLength;
514 : }
515 :
516 :
517 : /** @brief Returns the distance on the approaching lane from which an
518 : * approaching vehicle is able to see all relevant foes and
519 : * may accelerate if the link is minor and no foe is approaching.
520 : *
521 : * @return The foe-visibility-distance
522 : */
523 : double getFoeVisibilityDistance() const {
524 2327500899 : return myFoeVisibilityDistance;
525 : }
526 :
527 : double getDistToFoePedCrossing() const {
528 41557465 : return myDistToFoePedCrossing;
529 : }
530 :
531 : /** @brief Returns whether this link belongs to a junction where more than one edge is incoming
532 : *
533 : * @return Whether any foe links exist
534 : */
535 : bool hasFoes() const {
536 519071656 : return myHasFoes;
537 : }
538 :
539 : // @brief return whether the vehicle may continute past this link to wait within the intersection
540 : bool isCont() const;
541 :
542 :
543 : /// @brief whether the junction after this link must be kept clear
544 : bool keepClear() const {
545 165667168 : return myKeepClear;
546 : }
547 :
548 : /// @brief whether this link is the start of an indirect turn
549 : bool isIndirect() const {
550 1189766 : return myAmIndirect;
551 : }
552 :
553 : /// @brief whether this is a link past an internal junction which currently has priority
554 : bool lastWasContMajor() const;
555 :
556 : /// @brief whether this is a link past an internal junction where the entry to the junction currently has the given state
557 : bool lastWasContState(LinkState linkState) const;
558 :
559 : /** @brief Returns the cumulative length of all internal lanes after this link
560 : * @return sum of the lengths of all internal lanes following this link
561 : */
562 : double getInternalLengthsAfter() const;
563 :
564 : /** @brief Returns the cumulative length of all internal lanes before this link
565 : * @return sum of the lengths of all internal lanes before this link
566 : */
567 : double getInternalLengthsBefore() const;
568 :
569 : /** @brief Returns the sum of the lengths along internal lanes following this link
570 : * to the crossing with the given foe lane, if the lane is no foe
571 : * lane to any of the internal lanes, INVALID_DOUBLE is returned.
572 : * @see getLengthBeforeCrossing()
573 : */
574 : double getLengthsBeforeCrossing(const MSLane* foeLane) const;
575 :
576 :
577 : /** @brief Returns the internal length from the beginning of the link's internal lane before
578 : * to the crossing with the given foe lane if applicable, if the lane is no foe
579 : * lane to the link, INVALID_DOUBLE is returned.
580 : * @see getLengthsBeforeCrossing()
581 : */
582 : double getLengthBeforeCrossing(const MSLane* foeLane) const;
583 :
584 :
585 : /** @brief Returns the following inner lane
586 : *
587 : * @return The inner lane to use to cross the junction
588 : */
589 : inline MSLane* getViaLane() const {
590 3677963472 : return myInternalLane;
591 : }
592 :
593 : /** @brief Returns all potential link leaders (vehicles on foeLanes)
594 : * Valid during the planMove() phase
595 : * @param[in] ego The ego vehicle that is looking for leaders
596 : * @param[in] dist The distance of the vehicle who is asking about the leader to this link
597 : * @param[out] blocking Return blocking pedestrians if a vector is given
598 : * @param[in] isShadowLink whether this link is a shadowLink for ego
599 : * @return The all vehicles on foeLanes and their (virtual) distances to the asking vehicle
600 : */
601 : const LinkLeaders getLeaderInfo(const MSVehicle* ego, double dist, std::vector<const MSPerson*>* collectBlockers = 0, bool isShadowLink = false) const;
602 :
603 : /// @brief return the speed at which ego vehicle must approach the zipper link
604 : double getZipperSpeed(const MSVehicle* ego, const double dist, double vSafe,
605 : SUMOTime arrivalTime,
606 : const BlockingFoes* foes) const;
607 :
608 : /// @brief return the via lane if it exists and the lane otherwise
609 : inline MSLane* getViaLaneOrLane() const {
610 1934677119 : return myInternalLane != nullptr ? myInternalLane : myLane;
611 : }
612 :
613 :
614 : /// @brief return the internalLaneBefore if it exists and the laneBefore otherwise
615 : inline const MSLane* getLaneBefore() const {
616 : assert(myInternalLaneBefore == nullptr || myLaneBefore == myInternalLaneBefore); // lane before mismatch!
617 772253853 : return myLaneBefore;
618 : }
619 :
620 : /// @brief return myInternalLaneBefore (always 0 when compiled without internal lanes)
621 : inline const MSLane* getInternalLaneBefore() const {
622 756002673 : return myInternalLaneBefore;
623 : }
624 :
625 : /// @brief return the expected time at which the given vehicle will clear the link
626 : SUMOTime getLeaveTime(const SUMOTime arrivalTime, const double arrivalSpeed, const double leaveSpeed, const double vehicleLength) const;
627 :
628 : /// @brief write information about all approaching vehicles to the given output device
629 : void writeApproaching(OutputDevice& od, const std::string fromLaneID) const;
630 :
631 : /// @brief return the link that is parallel to this link or 0
632 : MSLink* getParallelLink(int direction) const;
633 :
634 : /// @brief return the link that is the opposite entry link to this one
635 : MSLink* getOppositeDirectionLink() const;
636 :
637 : /// @brief return whether the fromLane of this link is an internal lane
638 : inline bool fromInternalLane() const {
639 874640333 : return myInternalLaneBefore != nullptr;
640 : }
641 :
642 : /// @brief return whether the toLane of this link is an internal lane and fromLane is a normal lane
643 : bool isEntryLink() const;
644 :
645 : /// @brief return whether this link enters the conflict area (not a continuation link)
646 : bool isConflictEntryLink() const;
647 :
648 : /// @brief return whether the fromLane of this link is an internal lane and toLane is a normal lane
649 : bool isExitLink() const;
650 :
651 : /// @brief return whether the fromLane of this link is an internal lane and its incoming lane is also an internal lane
652 : bool isExitLinkAfterInternalJunction() const;
653 :
654 : /// @brief returns the corresponding exit link for entryLinks to a junction.
655 : const MSLink* getCorrespondingExitLink() const;
656 :
657 : /// @brief returns the corresponding entry link for exitLinks to a junction.
658 : const MSLink* getCorrespondingEntryLink() const;
659 :
660 : /// @brief return whether the fromLane and the toLane of this link are internal lanes
661 : bool isInternalJunctionLink() const;
662 :
663 : /** @brief Returns the time penalty for passing a tls-controlled link (meso) */
664 : SUMOTime getMesoTLSPenalty() const {
665 52022 : return myMesoTLSPenalty;
666 : }
667 :
668 : /** @brief Returns the average proportion of green time to cycle time */
669 : double getGreenFraction() const {
670 49540 : return myGreenFraction;
671 : }
672 :
673 : /** @brief Sets the time penalty for passing a tls-controlled link (meso) */
674 : void setMesoTLSPenalty(const SUMOTime penalty) {
675 182978 : myMesoTLSPenalty = penalty;
676 : }
677 :
678 : /** @brief Sets the green fraction for passing a tls-controlled link (meso) */
679 : void setGreenFraction(const double fraction) {
680 182818 : myGreenFraction = fraction;
681 : }
682 :
683 : const std::vector<const MSLane*>& getFoeLanes() const {
684 : return myFoeLanes;
685 : }
686 :
687 : const std::vector<ConflictInfo>& getConflicts() const {
688 : return myConflicts;
689 : }
690 :
691 : const std::vector<MSLink*>& getFoeLinks() const {
692 8056 : return myFoeLinks;
693 : }
694 :
695 : /// @brief who may use this link
696 : SVCPermissions getPermissions() const {
697 13452 : return myPermissions;
698 : }
699 :
700 : /// @brief initialize parallel links (to be called after all links are loaded)
701 : void initParallelLinks();
702 :
703 : /// @brief return lateral shift that must be applied when passing this link
704 : inline double getLateralShift() const {
705 984357533 : return myLateralShift;
706 : }
707 :
708 : /// @brief get string description for this link
709 : std::string getDescription() const;
710 :
711 : /// @brief get the closest vehicle approaching this link
712 : std::pair<const SUMOVehicle* const, const ApproachingVehicleInformation> getClosest() const;
713 :
714 : inline bool hasFoeCrossing() const {
715 89348 : return myHavePedestrianCrossingFoe;
716 : }
717 :
718 : /// @brief whether this link is for a railsignal that was passed in this step
719 : bool railSignalWasPassed() const;
720 :
721 : /// @brief post-processing for legacy networks
722 : static void recheckSetRequestInformation();
723 :
724 : static bool ignoreFoe(const SUMOTrafficObject* ego, const SUMOTrafficObject* foe);
725 :
726 : static const double NO_INTERSECTION;
727 :
728 : private:
729 : /// @brief return whether the given vehicles may NOT merge safely
730 : static inline bool unsafeMergeSpeeds(double leaderSpeed, double followerSpeed, double leaderDecel, double followerDecel) {
731 : // XXX mismatch between continuous an discrete deceleration
732 23849669 : return (leaderSpeed * leaderSpeed / leaderDecel) <= (followerSpeed * followerSpeed / followerDecel);
733 : }
734 :
735 : /// @brief whether follower could stay behind leader (possibly by braking)
736 : static bool couldBrakeForLeader(double followDist, double leaderDist, const MSVehicle* follow, const MSVehicle* leader);
737 :
738 : MSLink* computeParallelLink(int direction);
739 :
740 : /// @brief check for persons on walkingarea in the path of ego vehicle
741 : void checkWalkingAreaFoe(const MSVehicle* ego, const MSLane* foeLane, std::vector<const MSPerson*>* collectBlockers, LinkLeaders& result) const;
742 :
743 : /// @brief whether the given person is in front of the car
744 : bool isInFront(const MSVehicle* ego, const PositionVector& egoPath, const Position& pPos) const;
745 :
746 : /// @brief whether the given person is walking towards the car returned as a factor in [0, 1]
747 : double isOnComingPed(const MSVehicle* ego, const MSPerson* p) const;
748 :
749 : /// @brief return extrapolated position of the given person after the given time
750 : Position getFuturePosition(const MSPerson* p, double timeHorizon = 1) const;
751 :
752 : bool blockedByFoe(const SUMOVehicle* veh, const ApproachingVehicleInformation& avi,
753 : SUMOTime arrivalTime, SUMOTime leaveTime, double arrivalSpeed, double leaveSpeed,
754 : bool sameTargetLane, double impatience, double decel, SUMOTime waitingTime,
755 : const SUMOTrafficObject* ego) const;
756 :
757 : /// @brief figure out whether the cont status remains in effect when switching off the tls
758 : bool checkContOff() const;
759 :
760 : /// @brief check if the lane intersects with a foe cont-lane
761 : bool contIntersect(const MSLane* lane, const MSLane* foe);
762 :
763 : /// @brief compute point of divergence for geomatries with a common start or end
764 : double computeDistToDivergence(const MSLane* lane, const MSLane* sibling, double minDist, bool sameSource, double siblingPredLength = 0) const;
765 :
766 : /// @brief compute arrival time if foe vehicle is braking for ego
767 : static SUMOTime computeFoeArrivalTimeBraking(SUMOTime arrivalTime, const SUMOVehicle* foe, SUMOTime foeArrivalTime, double impatience, double dist, double& fasb);
768 :
769 : /// @brief check whether the given vehicle positions overlap laterally
770 : static bool lateralOverlap(double posLat, double width, double posLat2, double width2);
771 :
772 : /// @brief return CustomConflict with foeLane if it is defined
773 : const CustomConflict* getCustomConflict(const MSLane* foeLane) const;
774 :
775 : /// @brief add information about another pedestrian crossing
776 : void updateDistToFoePedCrossing(double dist);
777 :
778 : private:
779 : /// @brief The lane behind the junction approached by this link
780 : MSLane* myLane;
781 :
782 : /// @brief The lane approaching this link
783 : MSLane* myLaneBefore;
784 :
785 : ApproachInfos myApproachingVehicles;
786 : PersonApproachInfos* myApproachingPersons;
787 :
788 : /// @brief The position within this respond
789 : int myIndex;
790 :
791 : /// @brief the traffic light index
792 : const int myTLIndex;
793 :
794 : /// @brief the controlling logic or 0
795 : const MSTrafficLightLogic* myLogic;
796 :
797 : /// @brief The state of the link
798 : LinkState myState;
799 : /// @brief The last green state of the link (minor or major)
800 : LinkState myLastGreenState;
801 : /// @brief The state of the link when switching of traffic light control
802 : const LinkState myOffState;
803 :
804 : /// @brief The time of the last state change
805 : SUMOTime myLastStateChange;
806 :
807 : /// @brief An abstract (hopefully human readable) definition of the link's direction
808 : LinkDirection myDirection;
809 :
810 : /// @brief The length of the link
811 : /// @note This is not equal to the result of getInternalLengthsAfter for links with more than one internal lane.
812 : double myLength;
813 :
814 : /// @brief distance from which an approaching vehicle is able to
815 : /// see all relevant foes and may accelerate if the link is minor
816 : /// and no foe is approaching. Defaults to 4.5m.
817 : /// For zipper links (major) this is the distance at which zipper merging starts (and foes become "visible")
818 : double myFoeVisibilityDistance;
819 :
820 : /// @brief distance from the stop line to the first pedestrian crossing or maxdouble
821 : double myDistToFoePedCrossing;
822 :
823 : /// @brief Whether any foe links exist
824 : bool myHasFoes;
825 :
826 : // @brief whether vehicles may continue past this link to wait within the intersection
827 : bool myAmCont;
828 : // @brief whether vehicles may continue past this link to wait within the intersection after switching of the traffic light at this intersection
829 : bool myAmContOff;
830 :
831 : // @brief whether vehicles must keep the intersection clear if there is a downstream jam
832 : bool myKeepClear;
833 :
834 : /// @brief The following junction-internal lane if used
835 : MSLane* const myInternalLane;
836 :
837 : /* @brief The preceding junction-internal lane, only used at
838 : * - exit links (from internal lane to normal lane)
839 : * - internal junction links (from internal lane to internal lane)
840 : */
841 : const MSLane* myInternalLaneBefore;
842 :
843 : /// @brief penalty time at tls for mesoscopic simulation
844 : SUMOTime myMesoTLSPenalty;
845 : /// @brief green fraction at tls for mesoscopic simulation
846 : double myGreenFraction;
847 :
848 : /// @brief lateral shift to be applied when passing this link
849 : double myLateralShift;
850 :
851 : /* @brief lengths after the crossing point with foeLane
852 : * (index corresponds to myFoeLanes)
853 : * empty vector for entry links
854 : * */
855 : std::vector<ConflictInfo> myConflicts;
856 :
857 : std::vector<CustomConflict> myCustomConflicts;
858 :
859 : // TODO: documentation
860 : std::vector<MSLink*> myFoeLinks;
861 : std::vector<const MSLane*> myFoeLanes;
862 :
863 : /* prioritized links when the traffic light is switched off (only needed for RightOfWay::ALLWAYSTOP)
864 : * @note stored as a pointer to save space since it won't be used in most cases
865 : */
866 : std::vector<MSLink*>* myOffFoeLinks;
867 :
868 : /// @brief walkingArea that must be checked when entering the intersection
869 : const MSLane* myWalkingAreaFoe;
870 : /// @brief walkingArea that must be checked when leaving the intersection
871 : const MSLane* myWalkingAreaFoeExit;
872 :
873 : /// @brief whether on of myFoeLanes is a crossing
874 : bool myHavePedestrianCrossingFoe;
875 :
876 : /* @brief Links with the same origin lane and the same destination edge that may
877 : be in conflict for sublane simulation */
878 : std::vector<MSLink*> mySublaneFoeLinks;
879 : /* @brief Links with the same origin lane and different destination edge that may
880 : be in conflict for sublane simulation */
881 : std::vector<MSLink*> mySublaneFoeLinks2;
882 :
883 : /* @brief Internal Lanes with the same origin lane and the same destination edge that may
884 : be in conflict for sublane simulation */
885 : std::vector<MSLane*> mySublaneFoeLanes;
886 :
887 : static const SUMOTime myLookaheadTime;
888 : static const SUMOTime myLookaheadTimeZipper;
889 :
890 : /// @brief links that need post processing after initialization (to deal with legacy networks)
891 : static std::set<std::pair<MSLink*, MSLink*> > myRecheck;
892 :
893 : MSLink* myParallelRight;
894 : MSLink* myParallelLeft;
895 :
896 : /// @brief whether this connection is an indirect turning movement
897 : const bool myAmIndirect;
898 :
899 : /// @brief the turning radius for this link or doublemax for straight links
900 : double myRadius;
901 :
902 : /// @brief who may drive on this link
903 : SVCPermissions myPermissions;
904 :
905 : /// @brief the junction to which this link belongs
906 : MSJunction* myJunction;
907 :
908 : /// invalidated copy constructor
909 : MSLink(const MSLink& s);
910 :
911 : /// invalidated assignment operator
912 : MSLink& operator=(const MSLink& s);
913 :
914 : };
|