Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-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 MSEdge.h
15 : /// @author Christian Roessel
16 : /// @author Daniel Krajzewicz
17 : /// @author Jakob Erdmann
18 : /// @author Sascha Krieg
19 : /// @author Michael Behrisch
20 : /// @date Mon, 12 Mar 2001
21 : ///
22 : // A road/street connecting two junctions
23 : /****************************************************************************/
24 : #pragma once
25 : #include <config.h>
26 :
27 : #include <vector>
28 : #include <map>
29 : #include <string>
30 : #include <iostream>
31 : #ifdef HAVE_FOX
32 : #include <utils/foxtools/fxheader.h>
33 : #endif
34 : #include <utils/common/Named.h>
35 : #include <utils/common/Parameterised.h>
36 : #include <utils/common/SUMOTime.h>
37 : #include <utils/common/SUMOVehicleClass.h>
38 : #include <utils/geom/Boundary.h>
39 : #include <utils/router/ReversedEdge.h>
40 : #include <utils/router/RailEdge.h>
41 : #include <utils/vehicle/SUMOVehicle.h>
42 : #include <utils/vehicle/SUMOTrafficObject.h>
43 : #include "MSNet.h"
44 :
45 :
46 : // ===========================================================================
47 : // class declarations
48 : // ===========================================================================
49 : class Boundary;
50 : class OutputDevice;
51 : class SUMOVehicle;
52 : class SUMOVehicleParameter;
53 : class MSVehicle;
54 : class MSLane;
55 : class MSLaneChanger;
56 : class MSPerson;
57 : class MSJunction;
58 : class MSEdge;
59 : class MSTransportable;
60 :
61 :
62 : // ===========================================================================
63 : // class definitions
64 : // ===========================================================================
65 : /**
66 : * @class MSEdge
67 : * @brief A road/street connecting two junctions
68 : *
69 : * A single connection between two junctions.
70 : * Holds lanes which are reponsible for vehicle movements.
71 : */
72 :
73 : typedef std::vector<MSEdge*> MSEdgeVector;
74 : typedef std::vector<const MSEdge*> ConstMSEdgeVector;
75 : typedef std::vector<std::pair<const MSEdge*, const MSEdge*> > MSConstEdgePairVector;
76 :
77 : class MSEdge : public Named, public Parameterised {
78 : private:
79 : /** @brief "Map" from vehicle class to allowed lanes */
80 : typedef std::vector<std::pair<SVCPermissions, std::shared_ptr<const std::vector<MSLane*> > > > AllowedLanesCont;
81 :
82 : /** @brief Succeeding edges (keys) and allowed lanes to reach these edges (values). */
83 : typedef std::map<const MSEdge*, AllowedLanesCont> AllowedLanesByTarget;
84 :
85 :
86 : public:
87 : friend class MSLaneChangerSublane; // needs access to myLaneChanger
88 :
89 : /** @brief Constructor.
90 : *
91 : * After calling this constructor, the edge is not yet initialised
92 : * completely. A call to "initialize" with proper values is needed
93 : * for this.
94 : *
95 : * @param[in] id The id of the edge
96 : * @param[in] numericalID The numerical id (index) of the edge
97 : * @param[in] function A basic type of the edge
98 : * @param[in] streetName The street name for that edge
99 : */
100 : MSEdge(const std::string& id, int numericalID, const SumoXMLEdgeFunc function,
101 : const std::string& streetName, const std::string& edgeType,
102 : const std::string& routingType, int priority, double distance);
103 :
104 :
105 : /// @brief Destructor.
106 : virtual ~MSEdge();
107 :
108 :
109 : /** @brief Initialize the edge.
110 : *
111 : * @param[in] allowed Information which edges may be reached from which lanes
112 : * @param[in] lanes List of this edge's lanes
113 : */
114 : void initialize(const std::vector<MSLane*>* lanes);
115 :
116 :
117 : /** @brief Recalculates the cached values
118 : */
119 : void recalcCache();
120 :
121 :
122 : /// @todo Has to be called after all edges were built and all connections were set...; Still, is not very nice
123 : virtual void closeBuilding();
124 :
125 : /// Has to be called after all sucessors and predecessors have been set (after closeBuilding())
126 : void buildLaneChanger();
127 :
128 : /* @brief returns whether initizliaing a lane change is permitted on this edge
129 : * @note Has to be called after all sucessors and predecessors have been set (after closeBuilding())
130 : */
131 : bool allowsLaneChanging() const;
132 :
133 : /// @name Access to the edge's lanes
134 : /// @{
135 :
136 : /** @brief Returns the lane left to the one given, 0 if the given lane is leftmost
137 : *
138 : * @param[in] lane The lane right to the one to be returned
139 : * @return The lane left to the given, 0 if no such lane exists
140 : * @todo This method searches for the given in the container; probably, this could be done faster
141 : */
142 : MSLane* leftLane(const MSLane* const lane) const;
143 :
144 :
145 : /** @brief Returns the lane right to the one given, 0 if the given lane is rightmost
146 : *
147 : * @param[in] lane The lane left to the one to be returned
148 : * @return The lane right to the given, 0 if no such lane exists
149 : * @todo This method searches for the given in the container; probably, this could be done faster
150 : */
151 : MSLane* rightLane(const MSLane* const lane) const;
152 :
153 :
154 : /** @brief Returns the lane with the given offset parallel to the given lane one or 0 if it does not exist
155 : *
156 : * @param[in] lane The base lane
157 : * @param[in] offset The offset of the result lane
158 : * @param[in] includeOpposte Whether an opposite direction lane may be returned
159 : * @todo This method searches for the given in the container; probably, this could be done faster
160 : */
161 : MSLane* parallelLane(const MSLane* const lane, int offset, bool includeOpposite = true) const;
162 :
163 :
164 : /** @brief Returns this edge's lanes
165 : *
166 : * @return This edge's lanes
167 : */
168 : inline const std::vector<MSLane*>& getLanes() const {
169 : return *myLanes;
170 : }
171 :
172 : inline int getNumLanes() const {
173 792753458 : return (int)myLanes->size();
174 : }
175 :
176 : /// @brief return the number of lanes that permit non-weak modes if the edge allows non weak modes and the number of lanes otherwise
177 : int getNumDrivingLanes() const;
178 :
179 : /// @brief return total number of vehicles on this edges lanes or segments
180 : int getVehicleNumber() const;
181 :
182 : /// @brief whether this edge has no vehicles
183 : bool isEmpty() const;
184 :
185 : /// @brief return vehicles on this edges lanes or segments
186 : std::vector<const SUMOVehicle*> getVehicles() const;
187 :
188 : double getBruttoOccupancy() const;
189 :
190 : /// @brief return flow based on meanSpead @note: may produced incorrect results when jammed
191 : double getFlow() const;
192 :
193 : /// @brief return accumated waiting time for all vehicles on this edges lanes or segments
194 : double getWaitingSeconds() const;
195 :
196 : /// @brief return mean occupancy on this edges lanes or segments
197 : double getOccupancy() const;
198 :
199 : /** @brief Returns this edge's persons set.
200 : * @brief Avoids the creation of new vector as in getSortedPersons
201 : *
202 : * @return This edge's persons.
203 : */
204 : inline const std::set<MSTransportable*, ComparatorNumericalIdLess>& getPersons() const {
205 : return myPersons;
206 : }
207 :
208 : /** @brief Returns this edge's persons sorted by pos
209 : *
210 : * @return This edge's persons sorted by pos
211 : */
212 : std::vector<MSTransportable*> getSortedPersons(SUMOTime timestep, bool includeRiding = false) const;
213 :
214 :
215 : /** @brief Returns this edge's containers sorted by pos
216 : *
217 : * @return This edge's containers sorted by pos
218 : */
219 : std::vector<MSTransportable*> getSortedContainers(SUMOTime timestep, bool includeRiding = false) const;
220 :
221 : /** @brief Get the allowed lanes to reach the destination-edge.
222 : *
223 : * If there is no such edge, return nullptr. Then you are on the wrong edge.
224 : *
225 : * @param[in] destination The edge to reach
226 : * @param[in] vclass The vehicle class for which this information shall be returned
227 : * @return The lanes that may be used to reach the given edge, nullptr if no such lanes exist
228 : */
229 : const std::vector<MSLane*>* allowedLanes(const MSEdge& destination,
230 : SUMOVehicleClass vclass = SVC_IGNORING, bool ignoreTransientPermissions = false) const;
231 :
232 :
233 :
234 : /** @brief Get the allowed lanes for the given vehicle class.
235 : *
236 : * If there is no such edge, return nullptr. Then you are on the wrong edge.
237 : *
238 : * @param[in] vclass The vehicle class for which this information shall be returned
239 : * @return The lanes that may be used by the given vclass
240 : */
241 : const std::vector<MSLane*>* allowedLanes(SUMOVehicleClass vclass = SVC_IGNORING) const;
242 : const std::vector<MSLane*>* allowedLanes(SUMOVehicleClass vclass, bool ignoreTransientPermissions) const;
243 :
244 : inline bool isConnectedTo(const MSEdge& destination, SUMOVehicleClass vclass, bool ignoreTransientPermissions = false) const {
245 447518 : const std::vector<MSLane*>* const lanes = allowedLanes(destination, vclass, ignoreTransientPermissions);
246 558579 : return lanes != nullptr && !lanes->empty();
247 : }
248 : /// @}
249 :
250 :
251 :
252 : /// @name Access to other edge attributes
253 : /// @{
254 :
255 : /** @brief Returns the edge type (SumoXMLEdgeFunc)
256 : * @return This edge's SumoXMLEdgeFunc
257 : * @see SumoXMLEdgeFunc
258 : */
259 : inline SumoXMLEdgeFunc getFunction() const {
260 3877965 : return myFunction;
261 : }
262 :
263 : /// @brief return whether this edge is an internal edge
264 : inline bool isNormal() const {
265 66775630 : return myFunction == SumoXMLEdgeFunc::NORMAL;
266 : }
267 :
268 : /// @brief return whether this edge is an internal edge
269 : inline bool isInternal() const {
270 4449835899 : return myFunction == SumoXMLEdgeFunc::INTERNAL;
271 : }
272 :
273 : /// @brief return whether this edge is a pedestrian crossing
274 : inline bool isCrossing() const {
275 169137572 : return myFunction == SumoXMLEdgeFunc::CROSSING;
276 : }
277 :
278 :
279 : /// @brief check and register the opposite superposable edge if any
280 : void checkAndRegisterBiDirEdge(const std::string& bidiID = "");
281 :
282 : /// @brief return opposite superposable/congruent edge, if it exist and 0 else
283 : inline const MSEdge* getBidiEdge() const {
284 161091166 : return myBidiEdge;
285 : }
286 :
287 : /// @brief return whether this edge is walking area
288 : inline bool isWalkingArea() const {
289 497852718 : return myFunction == SumoXMLEdgeFunc::WALKINGAREA;
290 : }
291 :
292 : inline bool isTazConnector() const {
293 5600155139 : return myFunction == SumoXMLEdgeFunc::CONNECTOR;
294 : }
295 :
296 : void setOtherTazConnector(const MSEdge* edge) {
297 35024 : myOtherTazConnector = edge;
298 : }
299 :
300 : const MSEdge* getOtherTazConnector() const {
301 37624 : return myOtherTazConnector;
302 : }
303 :
304 : /** @brief Returns the numerical id of the edge
305 : * @return This edge's numerical id
306 : */
307 : inline int getNumericalID() const {
308 814541011 : return myNumericalID;
309 : }
310 :
311 :
312 : /** @brief Returns the street name of the edge
313 : */
314 : const std::string& getStreetName() const {
315 0 : return myStreetName;
316 : }
317 :
318 : /** @brief Returns the type of the edge
319 : */
320 : const std::string& getEdgeType() const {
321 3004243 : return myEdgeType;
322 : }
323 :
324 : /** @brief Returns the type of the edge
325 : */
326 : const std::string& getRoutingType() const {
327 5337 : return myRoutingType.empty() ? myEdgeType : myRoutingType;
328 : }
329 :
330 : double getPreference(const SUMOVTypeParameter& pars) const;
331 :
332 : // @brief try to infer edge type for internal edges
333 : void inferEdgeType();
334 :
335 : /** @brief Returns the priority of the edge
336 : */
337 : int getPriority() const {
338 155054 : return myPriority;
339 : }
340 :
341 : /** @brief Returns the kilometrage/mileage encoding at the start of the edge
342 : * (negative values encode descending direction)
343 : */
344 : double getDistance() const {
345 0 : return myDistance;
346 : }
347 :
348 : /** @brief Returns the kilometrage/mileage at the given offset along the edge
349 : */
350 : double getDistanceAt(double pos) const;
351 :
352 : bool hasDistance() const {
353 0 : return myDistance != 0;
354 : }
355 : /// @}
356 :
357 : /**@brief Sets the crossed edge ids for a crossing edge
358 : *
359 : */
360 19360 : void setCrossingEdges(const std::vector<std::string>& crossingEdges) {
361 : myCrossingEdges.clear();
362 19360 : myCrossingEdges.insert(myCrossingEdges.begin(), crossingEdges.begin(), crossingEdges.end());
363 19360 : }
364 :
365 : /**@brief Gets the crossed edge ids
366 : *@return The list of crossed edge ids in a crossing edge or an empty vector
367 : */
368 : const std::vector<std::string>& getCrossingEdges() const {
369 : return myCrossingEdges;
370 : }
371 :
372 :
373 : /// @name Access to succeeding/predecessing edges
374 : /// @{
375 :
376 : /** @brief Adds an edge to the list of edges which may be reached from this edge and to the incoming of the other edge
377 : *
378 : * This is mainly used by the taz (district) parsing
379 : * @param[in] edge The edge to add
380 : */
381 : void addSuccessor(MSEdge* edge, const MSEdge* via = nullptr);
382 :
383 : void resetTAZ(MSJunction* junction);
384 :
385 : /** @brief Returns the number of edges that may be reached from this edge
386 : * @return The number of following edges
387 : */
388 : int getNumSuccessors() const {
389 1529563 : return (int) mySuccessors.size();
390 : }
391 :
392 :
393 : /** @brief Returns the following edges, restricted by vClass
394 : * @param[in] vClass The vClass for which to restrict the successors
395 : * @return The eligible following edges
396 : */
397 : const MSEdgeVector& getSuccessors(SUMOVehicleClass vClass = SVC_IGNORING) const;
398 :
399 : /** @brief Returns the following edges with internal vias, restricted by vClass
400 : * @param[in] vClass The vClass for which to restrict the successors
401 : * @return The eligible following edges
402 : */
403 : const MSConstEdgePairVector& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING, bool ignoreTransientPermissions = false) const;
404 :
405 :
406 : /** @brief Returns the number of edges this edge is connected to
407 : *
408 : * @return The number of edges following this edge
409 : */
410 : int getNumPredecessors() const {
411 942878 : return (int) myPredecessors.size();
412 : }
413 :
414 :
415 : /** @brief
416 : * @return
417 : */
418 : const MSEdgeVector& getPredecessors() const {
419 5460150 : return myPredecessors;
420 : }
421 :
422 :
423 : const MSJunction* getFromJunction() const {
424 45702485 : return myFromJunction;
425 : }
426 :
427 : const MSJunction* getToJunction() const {
428 721929763 : return myToJunction;
429 : }
430 :
431 :
432 : void setJunctions(MSJunction* from, MSJunction* to);
433 : /// @}
434 :
435 :
436 :
437 : /// @name Access to vaporizing interface
438 : /// @{
439 :
440 : /** @brief Returns whether vehicles on this edge shall be vaporized
441 : * @return Whether no vehicle shall be on this edge
442 : */
443 : bool isVaporizing() const {
444 5562382841 : return myVaporizationRequests > 0;
445 : }
446 :
447 :
448 : /** @brief Enables vaporization
449 : *
450 : * The internal vaporization counter is increased enabling the
451 : * vaporization.
452 : * Called from the event handler.
453 : * @param[in] t The current time (unused)
454 : * @return Time to next call (always 0)
455 : * @exception ProcessError not thrown by this method, just derived
456 : */
457 : SUMOTime incVaporization(SUMOTime t);
458 :
459 :
460 : /** @brief Disables vaporization
461 : *
462 : * The internal vaporization counter is decreased what disables
463 : * the vaporization if it was only once enabled.
464 : * Called from the event handler.
465 : * @param[in] t The current time (unused)
466 : * @return Time to next call (always 0)
467 : * @exception ProcessError not thrown by this method, just derived
468 : */
469 : SUMOTime decVaporization(SUMOTime t);
470 : /// @}
471 :
472 :
473 : /** @brief Computes and returns the current travel time for this edge
474 : *
475 : * The mean speed of all lanes is used to compute the travel time.
476 : * To avoid infinite travel times, the given minimum speed is used.
477 : *
478 : * @param[in] minSpeed The minimumSpeed to assume if traffic on this edge is stopped
479 : * @return The current effort (travel time) to pass the edge
480 : */
481 : double getCurrentTravelTime(const double minSpeed = NUMERICAL_EPS) const;
482 :
483 :
484 : /// @brief returns the minimum travel time for the given vehicle
485 217917150 : inline double getMinimumTravelTime(const SUMOVehicle* const veh) const {
486 217923457 : if (myFunction == SumoXMLEdgeFunc::CONNECTOR) {
487 : return 0;
488 209992915 : } else if (veh != 0) {
489 209859820 : return getLength() / getVehicleMaxSpeed(veh) + myTimePenalty;
490 : } else {
491 139346 : return myEmptyTraveltime;
492 : }
493 : }
494 :
495 0 : double getTimePenalty() const {
496 3702514 : return myTimePenalty;
497 : }
498 :
499 : /** @brief Returns the travel time for the given edge
500 : *
501 : * @param[in] edge The edge for which the travel time shall be retrieved
502 : * @param[in] veh The vehicle for which the travel time on this edge shall be retrieved
503 : * @param[in] time The time for which the travel time shall be returned [s]
504 : * @return The traveltime needed by the given vehicle to pass the edge at the given time
505 : */
506 : static inline double getTravelTimeStatic(const MSEdge* const edge, const SUMOVehicle* const veh, double time) {
507 92570 : return MSNet::getInstance()->getTravelTime(edge, veh, time);
508 : }
509 :
510 : static double getTravelTimeAggregated(const MSEdge* const edge, const SUMOVehicle* const veh, double time);
511 :
512 : /** @brief Returns the averaged speed used by the routing device
513 : */
514 : double getRoutingSpeed() const;
515 :
516 :
517 : /// @name Methods releated to vehicle insertion
518 : /// @{
519 :
520 : /** @brief Tries to insert the given vehicle into the network
521 : *
522 : * The procedure for choosing the proper lane is determined, first.
523 : * In dependence to this, the proper lane is chosen.
524 : *
525 : * Insertion itself is done by calling the chose lane's "insertVehicle"
526 : * method but only if the checkOnly argument is false. The check needs
527 : * to be certain only in the negative case (if false is returned, there
528 : * is no way this vehicle would be inserted).
529 : *
530 : * @param[in] v The vehicle to insert
531 : * @param[in] time The current simulation time
532 : * @param[in] checkOnly Whether we perform only the check without actually inserting
533 : * @param[in] forceCheck Whether the full insertion check should be run for each pending vehicle
534 : * or whether insertion on lanes for which an insertion has already a failed should be ignored
535 : * in the current time step.
536 : * @return Whether the vehicle could be inserted
537 : * @see MSLane::insertVehicle
538 : */
539 : bool insertVehicle(SUMOVehicle& v, SUMOTime time, const bool checkOnly = false, const bool forceCheck = false) const;
540 :
541 : /// @brief check whether the given departSpeed is valid for this edge
542 : bool validateDepartSpeed(SUMOVehicle& v) const;
543 :
544 : /** @brief Finds the emptiest lane allowing the vehicle class
545 : *
546 : * The emptiest lane is the one which vehicle insertion is most likely to succeed.
547 : *
548 : * If there are no vehicles before departPos, then the lane with the largest
549 : * gap between departPos and the last vehicle is
550 : * Otheriwise the lane with lowes occupancy is selected
551 : * If there is more than one, the first according to its
552 : * index in the lane container is chosen.
553 : *
554 : * If allowed==0, the lanes allowed for the given vehicle class
555 : * will be used.
556 : *
557 : * @param[in] allowed The lanes to choose from
558 : * @param[in] vclass The vehicle class to look for
559 : * @param[in] departPos An upper bound on vehicle depart position
560 : * @return the least occupied lane
561 : * @see allowedLanes
562 : */
563 : MSLane* getFreeLane(const std::vector<MSLane*>* allowed, const SUMOVehicleClass vclass, double departPos) const;
564 :
565 : /** @brief Finds the most probable lane allowing the vehicle class
566 : *
567 : * The most probable lane is the one which best corresponds to the desired speed of the vehicle
568 : * Vehicles with lower speeds will use lanes to the right while
569 : * vehicles with higher speeds will use lanes to the left
570 : *
571 : * @param[in] allowed The lanes to choose from
572 : * @param[in] vclass The vehicle class to look for
573 : * @param[in] departPos An upper bound on vehicle depart position
574 : * @param[in] maxSpeed The vehicles maxSpeed (including speedFactor)
575 : * @return the least occupied lane
576 : * @see allowedLanes
577 : */
578 : MSLane* getProbableLane(const std::vector<MSLane*>* allowed, const SUMOVehicleClass vclass, double departPos, double maxSpeed) const;
579 :
580 :
581 : /** @brief Finds a depart lane for the given vehicle parameters
582 : *
583 : * Depending on the depart lane procedure a depart lane is chosen.
584 : * Repeated calls with the same vehicle may return different results
585 : * if the procedure is "random" or "free". In case no appropriate
586 : * lane was found, 0 is returned.
587 : *
588 : * @param[in] veh The vehicle to get the depart lane for
589 : * @return a possible/chosen depart lane, 0 if no lane can be used
590 : */
591 : MSLane* getDepartLane(MSVehicle& veh) const;
592 :
593 : /* @brief get the rightmost lane that allows the given vClass or nullptr
594 : * @param[in] defaultFirst Whether the first lane should be returned if all lanes are forbidden
595 : */
596 : MSLane* getFirstAllowed(SUMOVehicleClass vClass, bool defaultFirst = false, int routingMode = 0) const;
597 :
598 : /// @brief consider given departLane parameter (only for validating speeds)
599 : MSLane* getDepartLaneMeso(SUMOVehicle& veh) const;
600 :
601 : /** @brief Returns the last time a vehicle could not be inserted
602 : * @return The current value
603 : */
604 : inline SUMOTime getLastFailedInsertionTime() const {
605 : return myLastFailedInsertionTime;
606 : }
607 :
608 :
609 : /** @brief Sets the last time a vehicle could not be inserted
610 : * @param[in] time the new value
611 : */
612 : inline void setLastFailedInsertionTime(SUMOTime time) const {
613 2069707943 : myLastFailedInsertionTime = time;
614 : }
615 : /// @}
616 :
617 :
618 : /** @brief Performs lane changing on this edge */
619 : void changeLanes(SUMOTime t) const;
620 :
621 :
622 : /// @todo extension: inner junctions are not filled
623 : const MSEdge* getInternalFollowingEdge(const MSEdge* followerAfterInternal, SUMOVehicleClass vClass) const;
624 :
625 :
626 : /// @brief returns the length of all internal edges on the junction until reaching the non-internal edge followerAfterInternal.
627 : double getInternalFollowingLengthTo(const MSEdge* followerAfterInternal, SUMOVehicleClass vClass) const;
628 :
629 : /// @brief if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
630 : const MSEdge* getNormalBefore() const;
631 :
632 : /// @brief if this edge is an internal edge, return its first normal successor, otherwise the edge itself
633 : const MSEdge* getNormalSuccessor() const;
634 :
635 : /// @brief Returns whether the vehicle (class) is not allowed on the edge
636 672941090 : inline bool prohibits(const SUMOVehicle* const vehicle) const {
637 672941090 : if (vehicle == nullptr) {
638 : return false;
639 : }
640 672940323 : const SUMOVehicleClass svc = vehicle->getVClass();
641 672940323 : return (vehicle->ignoreTransientPermissions()
642 672940323 : ? (myOriginalCombinedPermissions & svc) != svc
643 672869480 : : (myCombinedPermissions & svc) != svc);
644 : }
645 :
646 : bool hasTransientPermissions() const;
647 :
648 : /** @brief Returns whether this edge has restriction parameters forbidding the given vehicle to pass it
649 : * The restriction mechanism is not implemented yet for the microsim, so it always returns false.
650 : * @param[in] vehicle The vehicle for which the information has to be returned
651 : * @return Whether the vehicle must not enter this edge
652 : */
653 : inline bool restricts(const SUMOVehicle* const /* vehicle */) const {
654 : return false;
655 : }
656 :
657 : /// @brief Returns the combined permissions of all lanes of this edge
658 : inline SVCPermissions getPermissions() const {
659 2956326288 : return myCombinedPermissions;
660 : }
661 :
662 : /** @brief Returns the edges's width (sum over all lanes)
663 : * @return This edges's width
664 : */
665 : double getWidth() const {
666 690935278 : return myWidth;
667 : }
668 :
669 : /// @brief Returns the right side offsets of this edge's sublanes
670 : const std::vector<double> getSubLaneSides() const {
671 277734219 : return mySublaneSides;
672 : }
673 :
674 : void rebuildAllowedLanes(const bool onInit = false, bool updateVehicles = false);
675 :
676 : void rebuildAllowedTargets(const bool updateVehicles = true);
677 :
678 :
679 : /** @brief optimistic air distance heuristic for use in routing
680 : * @param[in] other The edge to which the distance shall be returned
681 : * @param[in] doBoundaryEstimate whether the distance should be estimated by looking at the distance of the bounding boxes
682 : * @return The distance to the other edge
683 : */
684 : double getDistanceTo(const MSEdge* other, const bool doBoundaryEstimate = false) const;
685 :
686 :
687 : /// @brief return the coordinates of the center of the given stop
688 : static const Position getStopPosition(const SUMOVehicleParameter::Stop& stop);
689 :
690 :
691 : /** @brief return the length of the edge
692 : * @return The edge's length
693 : */
694 : inline double getLength() const {
695 1842424185 : return myLength;
696 : }
697 :
698 :
699 : /** @brief Returns the speed limit of the edge
700 : * @caution The speed limit of the first lane is retured; should probably be the fastest edge
701 : * @return The maximum speed allowed on this edge
702 : */
703 : double getSpeedLimit() const;
704 :
705 : /// @brief return shape.length() / myLength
706 : double getLengthGeometryFactor() const;
707 :
708 : /** @brief Sets a new maximum speed for all lanes (used by TraCI and MSCalibrator)
709 : * @param[in] val the new speed in m/s
710 : * @param[in] modified whether this modifies the original speed
711 : * @param[in] jamThreshold also set a new jamThreshold
712 : */
713 : void setMaxSpeed(const double val, const bool modified = true, const double jamThreshold = -1);
714 :
715 : /** @brief Sets a new friction coefficient COF for all lanes [*later to be (used by TraCI and MSCalibrator)*]
716 : * @param[in] val the new coefficient in [0..1]
717 : */
718 : void setFrictionCoefficient(double val) const;
719 :
720 : /** @brief Returns the maximum speed the vehicle may use on this edge
721 : *
722 : * @caution Only the first lane is considered
723 : * @return The maximum velocity on this edge for the given vehicle
724 : */
725 : double getVehicleMaxSpeed(const SUMOTrafficObject* const veh) const;
726 :
727 :
728 : virtual void addTransportable(MSTransportable* t) const;
729 :
730 : virtual void removeTransportable(MSTransportable* t) const;
731 :
732 : inline bool isRoundabout() const {
733 2044561554 : return myAmRoundabout;
734 : }
735 :
736 : void markAsRoundabout() {
737 6849 : myAmRoundabout = true;
738 6849 : }
739 :
740 : void markDelayed() const {
741 74656817 : myAmDelayed = true;
742 54333193 : }
743 :
744 : // return whether there have been vehicles on this or the bidi edge (if there is any) at least once
745 : inline bool isDelayed() const {
746 755959970 : return myAmDelayed || (myBidiEdge != nullptr && myBidiEdge->myAmDelayed);
747 : }
748 :
749 : bool hasLaneChanger() const {
750 1753443186 : return myLaneChanger != nullptr;
751 : }
752 :
753 : /// @brief retrieve properties of a blocked vehicle that wants to chane to the lane with the given index
754 : std::pair<double, SUMOTime> getLastBlocked(int index) const;
755 :
756 : /// @brief whether this edge allows changing to the opposite direction edge
757 : bool canChangeToOpposite() const;
758 :
759 : /// @brief Returns the opposite direction edge if on exists else a nullptr
760 : const MSEdge* getOppositeEdge() const;
761 :
762 : /// @brief get the mean speed
763 : double getMeanSpeed() const;
764 :
765 : /// @brief get the mean friction over the lanes
766 : double getMeanFriction() const;
767 :
768 : /// @brief get the mean speed of all bicycles on this edge
769 : double getMeanSpeedBike() const;
770 :
771 : /// @brief whether any lane has a minor link
772 : bool hasMinorLink() const;
773 :
774 : /// @brief return whether this edge is at the fringe of the network
775 : bool isFringe() const {
776 : return myAmFringe;
777 : }
778 :
779 : /// @brief return whether this edge prohibits changing for the given vClass when starting on the given lane index
780 : bool hasChangeProhibitions(SUMOVehicleClass svc, int index) const;
781 :
782 : /// @brief whether this lane is selected in the GUI
783 0 : virtual bool isSelected() const {
784 0 : return false;
785 : }
786 :
787 : /// @brief grant exclusive access to the mesoscopic state
788 36905185 : virtual void lock() const {}
789 :
790 : /// @brief release exclusive access to the mesoscopic state
791 36905185 : virtual void unlock() const {};
792 :
793 : /// @brief Adds a vehicle to the list of waiting vehicles
794 : void addWaiting(SUMOVehicle* vehicle) const;
795 :
796 : /// @brief Removes a vehicle from the list of waiting vehicles
797 : void removeWaiting(const SUMOVehicle* vehicle) const;
798 :
799 : /* @brief returns a vehicle that is waiting for a for a person or a container at this edge at the given position
800 : * @param[in] transportable The person or container that wants to ride
801 : * @param[in] position The vehicle shall be positioned in the interval [position - t, position + t], where t is some tolerance
802 : */
803 : SUMOVehicle* getWaitingVehicle(MSTransportable* transportable, const double position) const;
804 :
805 : /** @brief Remove all transportables before quick-loading state */
806 : void clearState();
807 :
808 : void postLoadInitLaneChanger();
809 :
810 : static DepartLaneDefinition& getDefaultDepartLaneDefinition() {
811 : return myDefaultDepartLaneDefinition;
812 : }
813 :
814 : static int& getDefaultDepartLane() {
815 : return myDefaultDepartLane;
816 : }
817 :
818 : /** @brief Inserts edge into the static dictionary
819 : Returns true if the key id isn't already in the dictionary. Otherwise
820 : returns false. */
821 : static bool dictionary(const std::string& id, MSEdge* edge);
822 :
823 : /** @brief Returns the MSEdge associated to the key id if it exists, otherwise returns nullptr. */
824 : static MSEdge* dictionary(const std::string& id);
825 :
826 : /** @brief Returns the MSEdge associated to the key id giving a hint with a numerical id. */
827 : static MSEdge* dictionaryHint(const std::string& id, const int startIdx);
828 :
829 : /// @brief Returns all edges with a numerical id
830 : static const MSEdgeVector& getAllEdges();
831 :
832 : /** @brief Clears the dictionary */
833 : static void clear();
834 :
835 : /** @brief Inserts IDs of all known edges into the given vector */
836 : static void insertIDs(std::vector<std::string>& into);
837 :
838 : static SVCPermissions getMesoPermissions(SVCPermissions p, SVCPermissions ignoreIgnored = 0);
839 :
840 : static void setMesoIgnoredVClasses(SVCPermissions ignored) {
841 6737 : myMesoIgnoredVClasses = ignored;
842 : }
843 :
844 : public:
845 : /// @name Static parser helper
846 : /// @{
847 :
848 : /** @brief Parses the given string assuming it contains a list of edge ids divided by spaces
849 : *
850 : * Splits the string at spaces, uses polymorph method to generate edge vector.
851 : * @param[in] desc The string containing space-separated edge ids
852 : * @param[out] into The vector to fill
853 : * @param[in] rid The id of the route these description belongs to; used for error message generation
854 : * @exception ProcessError If one of the strings contained is not a known edge id
855 : */
856 : static void parseEdgesList(const std::string& desc, ConstMSEdgeVector& into,
857 : const std::string& rid);
858 :
859 :
860 : /** @brief Parses the given string vector assuming it edge ids
861 : * @param[in] desc The string vector containing edge ids
862 : * @param[out] into The vector to fill
863 : * @param[in] rid The id of the route these description belongs to; used for error message generation
864 : * @exception ProcessError If one of the strings contained is not a known edge id
865 : */
866 : static void parseEdgesList(const std::vector<std::string>& desc, ConstMSEdgeVector& into,
867 : const std::string& rid);
868 : /// @}
869 :
870 :
871 0 : ReversedEdge<MSEdge, SUMOVehicle>* getReversedRoutingEdge() const {
872 0 : if (myReversedRoutingEdge == nullptr) {
873 0 : myReversedRoutingEdge = new ReversedEdge<MSEdge, SUMOVehicle>(this);
874 : }
875 0 : return myReversedRoutingEdge;
876 : }
877 :
878 391424 : RailEdge<MSEdge, SUMOVehicle>* getRailwayRoutingEdge() const {
879 391424 : if (myRailwayRoutingEdge == nullptr) {
880 51117 : myRailwayRoutingEdge = new RailEdge<MSEdge, SUMOVehicle>(this);
881 : }
882 391424 : return myRailwayRoutingEdge;
883 : }
884 :
885 : const std::map<const MEVehicle*, std::pair<double, int> >& getMesoPositions() const;
886 :
887 : protected:
888 : /** @class by_id_sorter
889 : * @brief Sorts edges by their ids
890 : */
891 : class by_id_sorter {
892 : public:
893 : /// @brief constructor
894 : explicit by_id_sorter() { }
895 :
896 : /// @brief comparing operator
897 : int operator()(const MSEdge* const e1, const MSEdge* const e2) const {
898 : return e1->getNumericalID() < e2->getNumericalID();
899 : }
900 :
901 : };
902 :
903 : /** @class transportable_by_position_sorter
904 : * @brief Sorts transportables by their positions
905 : */
906 : class transportable_by_position_sorter {
907 : public:
908 : /// @brief constructor
909 : explicit transportable_by_position_sorter(SUMOTime timestep): myTime(timestep) { }
910 :
911 : /// @brief comparing operator
912 : int operator()(const MSTransportable* const c1, const MSTransportable* const c2) const;
913 : private:
914 : SUMOTime myTime;
915 : };
916 :
917 :
918 : /// @brief return upper bound for the depart position on this edge
919 : double getDepartPosBound(const MSVehicle& veh, bool upper = true) const;
920 :
921 : protected:
922 : /// @brief This edge's numerical id
923 : const int myNumericalID;
924 :
925 : /// @brief Container for the edge's lane; should be sorted: (right-hand-traffic) the more left the lane, the higher the container-index
926 : std::shared_ptr<const std::vector<MSLane*> > myLanes;
927 :
928 : /// @brief This member will do the lane-change
929 : MSLaneChanger* myLaneChanger;
930 :
931 : /// @brief the purpose of the edge
932 : const SumoXMLEdgeFunc myFunction;
933 :
934 : /// @brief Vaporizer counter
935 : int myVaporizationRequests;
936 :
937 : /// @brief The time of last insertion failure
938 : mutable SUMOTime myLastFailedInsertionTime;
939 :
940 : /// @brief A cache for the rejected insertion attempts. Used to assure that no
941 : /// further insertion attempts are made on a lane where an attempt has
942 : /// already failed in the current time step if MSInsertionControl::myEagerInsertionCheck is off.
943 : mutable std::set<int> myFailedInsertionMemory;
944 :
945 : /// @brief The crossed edges id for a crossing edge. On not crossing edges it is empty
946 : std::vector<std::string> myCrossingEdges;
947 :
948 : /// @brief The succeeding edges
949 : MSEdgeVector mySuccessors;
950 :
951 : MSConstEdgePairVector myViaSuccessors;
952 :
953 : /// @brief The preceeding edges
954 : MSEdgeVector myPredecessors;
955 :
956 : /// @brief the junctions for this edge
957 : MSJunction* myFromJunction;
958 : MSJunction* myToJunction;
959 :
960 : /// @brief Persons on the edge for drawing and pushbutton
961 : mutable std::set<MSTransportable*, ComparatorNumericalIdLess> myPersons;
962 :
963 : /// @brief Containers on the edge
964 : mutable std::set<MSTransportable*, ComparatorNumericalIdLess> myContainers;
965 :
966 : /// @name Storages for allowed lanes (depending on vehicle classes)
967 : /// @{
968 :
969 : /// @brief Associative container from vehicle class to allowed-lanes.
970 : AllowedLanesCont myAllowed;
971 : AllowedLanesCont myOrigAllowed;
972 :
973 : /// @brief From target edge to lanes allowed to be used to reach it
974 : AllowedLanesByTarget myAllowedTargets;
975 : AllowedLanesByTarget myOrigAllowedTargets;
976 :
977 : /// @brief The intersection of lane permissions for this edge
978 : SVCPermissions myMinimumPermissions = SVCAll;
979 : /// @brief The union of lane permissions for this edge
980 : SVCPermissions myCombinedPermissions = 0;
981 :
982 : /// @brief The original intersection of lane permissions for this edge (before temporary modifications)
983 : SVCPermissions myOriginalMinimumPermissions = SVCAll;
984 : /// @brief The original union of lane permissions for this edge (before temporary modifications)
985 : SVCPermissions myOriginalCombinedPermissions = SVCAll;
986 :
987 : /// @brief whether transient permission changes were applied to this edge or a predecessor
988 : bool myHaveTransientPermissions;
989 : /// @}
990 :
991 : /// @brief the other taz-connector if this edge isTazConnector, otherwise nullptr
992 : const MSEdge* myOtherTazConnector;
993 :
994 : /// @brief the real-world name of this edge (need not be unique)
995 : std::string myStreetName;
996 :
997 : /// @brief the type of the edge (optionally used during network creation)
998 : std::string myEdgeType;
999 :
1000 : /// @brief the routing type of the edge (used to look up vType and vClass specific routing preferences)
1001 : std::string myRoutingType;
1002 :
1003 : /// @brief the priority of the edge (used during network creation)
1004 : const int myPriority;
1005 :
1006 : /// @brief the kilometrage/mileage at the start of the edge
1007 : const double myDistance;
1008 :
1009 : /// Edge width [m]
1010 : double myWidth;
1011 :
1012 : /// @brief the length of the edge (cached value for speedup)
1013 : double myLength;
1014 :
1015 : /// @brief the traveltime on the empty edge (cached value for speedup)
1016 : double myEmptyTraveltime;
1017 :
1018 : /// @brief flat penalty when computing traveltime
1019 : double myTimePenalty;
1020 :
1021 : /// @brief whether this edge had a vehicle with less than max speed on it
1022 : mutable bool myAmDelayed;
1023 :
1024 : /// @brief whether this edge belongs to a roundabout
1025 : bool myAmRoundabout;
1026 :
1027 : /// @brief whether this edge is at the network fringe
1028 : bool myAmFringe;
1029 :
1030 : /// @brief the right side for each sublane on this edge
1031 : std::vector<double> mySublaneSides;
1032 :
1033 : /// @name Static edge container
1034 : /// @{
1035 :
1036 : /// @brief definition of the static dictionary type
1037 : typedef std::map< std::string, MSEdge* > DictType;
1038 :
1039 : /** @brief Static dictionary to associate string-ids with objects.
1040 : * @deprecated Move to MSEdgeControl, make non-static
1041 : */
1042 : static DictType myDict;
1043 :
1044 : /** @brief Static list of edges
1045 : * @deprecated Move to MSEdgeControl, make non-static
1046 : */
1047 : static MSEdgeVector myEdges;
1048 :
1049 : static SVCPermissions myMesoIgnoredVClasses;
1050 :
1051 : static DepartLaneDefinition myDefaultDepartLaneDefinition;
1052 : static int myDefaultDepartLane;
1053 : /// @}
1054 :
1055 :
1056 : /// @brief The successors available for a given vClass
1057 : mutable std::map<SUMOVehicleClass, MSEdgeVector> myClassesSuccessorMap;
1058 :
1059 : /// @brief The successors available for a given vClass
1060 : mutable std::map<SUMOVehicleClass, MSConstEdgePairVector> myClassesViaSuccessorMap;
1061 : mutable std::map<SUMOVehicleClass, MSConstEdgePairVector> myOrigClassesViaSuccessorMap;
1062 :
1063 : /// @brief The bounding rectangle of end nodes incoming or outgoing edges for taz connectors or of my own start and end node for normal edges
1064 : Boundary myBoundary;
1065 :
1066 : /// @brief List of waiting vehicles
1067 : mutable std::vector<SUMOVehicle*> myWaiting;
1068 :
1069 : /// @brief Mesoscopic vehicle positions
1070 : mutable std::map<const MEVehicle*, std::pair<double, int> > myCachedMesoPos;
1071 :
1072 : /// @brief time stamp of mesoscopic vehicle positions
1073 : mutable SUMOTime myLastCacheUpdate = -1;
1074 :
1075 : #ifdef HAVE_FOX
1076 : /// @brief Mutex for accessing waiting vehicles
1077 : mutable FXMutex myWaitingMutex;
1078 :
1079 : /// @brief Mutex for accessing successor edges
1080 : mutable FXMutex mySuccessorMutex;
1081 : #endif
1082 :
1083 : private:
1084 :
1085 : /// @brief the oppositing superposable edge
1086 : const MSEdge* myBidiEdge;
1087 :
1088 : /// @brief a reversed version for backward routing
1089 : mutable ReversedEdge<MSEdge, SUMOVehicle>* myReversedRoutingEdge = nullptr;
1090 : mutable RailEdge<MSEdge, SUMOVehicle>* myRailwayRoutingEdge = nullptr;
1091 :
1092 : /// @brief Invalidated copy constructor.
1093 : MSEdge(const MSEdge&);
1094 :
1095 : /// @brief assignment operator.
1096 : MSEdge& operator=(const MSEdge&) = delete;
1097 :
1098 : void setBidiLanes();
1099 :
1100 : bool isSuperposable(const MSEdge* other);
1101 :
1102 : void addToAllowed(const SVCPermissions permissions, std::shared_ptr<const std::vector<MSLane*> > allowedLanes, AllowedLanesCont& laneCont) const;
1103 : };
|