Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2014-2024 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 MSPModel_Striping.h
15 : /// @author Jakob Erdmann
16 : /// @author Michael Behrisch
17 : /// @date Mon, 13 Jan 2014
18 : ///
19 : // The pedestrian movement model using stripes on sidewalks
20 : /****************************************************************************/
21 : #pragma once
22 : #include <config.h>
23 :
24 : #include <string>
25 : #include <limits>
26 : #include <utils/common/SUMOTime.h>
27 : #include <utils/common/Command.h>
28 : #include <utils/options/OptionsCont.h>
29 : #include <microsim/MSLane.h>
30 : #include "MSPerson.h"
31 : #include "MSPModel_Interacting.h"
32 :
33 : // ===========================================================================
34 : // class declarations
35 : // ===========================================================================
36 : class MSNet;
37 : class MSLink;
38 : class MSJunction;
39 :
40 :
41 : // ===========================================================================
42 : // class definitions
43 : // ===========================================================================
44 : /**
45 : * @class MSPModel_Striping
46 : * @brief The pedestrian movement model using stripes on sidewalks
47 : *
48 : */
49 : class MSPModel_Striping : public MSPModel_Interacting {
50 :
51 : friend class GUIPerson; // for debugging
52 :
53 : public:
54 :
55 712608 : struct WalkingAreaPath {
56 178152 : WalkingAreaPath(const MSLane* _from, const MSLane* _walkingArea, const MSLane* _to, const PositionVector& _shape, int _dir, double _angleOverride) :
57 178152 : from(_from),
58 178152 : to(_to),
59 178152 : lane(_walkingArea),
60 0 : shape(_shape),
61 178152 : dir(_dir),
62 178152 : angleOverride(_angleOverride),
63 178152 : length(_shape.length()) {
64 178152 : }
65 :
66 : const MSLane* const from;
67 : const MSLane* const to;
68 : const MSLane* const lane; // the walkingArea;
69 : const PositionVector shape;
70 : const int dir; // the direction when entering this path
71 : const double angleOverride;
72 : const double length;
73 :
74 : };
75 :
76 : typedef std::map<std::pair<const MSLane*, const MSLane*>, const WalkingAreaPath> WalkingAreaPaths;
77 :
78 : /// @brief Constructor (it should not be necessary to construct more than one instance)
79 : MSPModel_Striping(const OptionsCont& oc, MSNet* net);
80 :
81 : ~MSPModel_Striping();
82 :
83 : /// @brief register the given person as a pedestrian
84 : MSTransportableStateAdapter* add(MSTransportable* transportable, MSStageMoving* stage, SUMOTime now);
85 :
86 : /// @brief load the state of the given transportable
87 : MSTransportableStateAdapter* loadState(MSTransportable* transportable, MSStageMoving* stage, std::istringstream& in);
88 :
89 : /// @brief model parameters
90 : ///@{
91 :
92 : /// @brief the width of a pedstrian stripe
93 : static double stripeWidth;
94 :
95 : /// @brief the factor for random slow-down
96 : static double dawdling;
97 :
98 : /// @brief the safety buffer to vehicles
99 : static double minGapToVehicle;
100 :
101 : /// @brief intermediate points to smooth out lanes within the walkingarea
102 : static int myWalkingAreaDetail;
103 :
104 : /// @brief the time threshold before becoming jammed
105 : static SUMOTime jamTime;
106 : static SUMOTime jamTimeCrossing;
107 : static SUMOTime jamTimeNarrow;
108 : /// @brief the factor on speed when jammed
109 : static double jamFactor;
110 :
111 : /// @brief use old style departPosLat interpretation
112 : static bool myLegacyPosLat;
113 :
114 : /// @brief the distance (in seconds) to look ahead for changing stripes
115 : static const double LOOKAHEAD_SAMEDIR;
116 : /// @brief the distance (in seconds) to look ahead for changing stripes (regarding oncoming pedestrians)
117 : static const double LOOKAHEAD_ONCOMING;
118 : /// @brief the distance (in m) to look around for vehicles
119 : static const double LOOKAROUND_VEHICLES;
120 : /// @brief the distance (in m) to look ahead for obstacles on a subsequent edge
121 : static const double LOOKAHEAD_ONCOMING_DIST;
122 :
123 : /// @brief the utility penalty for moving sideways (corresponds to meters)
124 : static const double LATERAL_PENALTY;
125 :
126 : /// @brief the utility penalty for obstructed (physically blocking me) stripes (corresponds to meters)
127 : static const double OBSTRUCTED_PENALTY;
128 :
129 : /// @brief the utility penalty for inappropriate (reserved for oncoming traffic or may violate my min gap) stripes (corresponds to meters)
130 : static const double INAPPROPRIATE_PENALTY;
131 :
132 : /// @brief the utility penalty for oncoming conflicts on stripes (corresponds to meters)
133 : static const double ONCOMING_CONFLICT_PENALTY;
134 :
135 : /// @brief the minimum utility that indicates obstruction
136 : static const double OBSTRUCTION_THRESHOLD;
137 :
138 : /// @brief the factor by which pedestrian width is reduced when sqeezing past each other
139 : static const double SQUEEZE;
140 :
141 : /// @brief fraction of the leftmost lanes to reserve for oncoming traffic
142 : static double RESERVE_FOR_ONCOMING_FACTOR;
143 : static double RESERVE_FOR_ONCOMING_FACTOR_JUNCTIONS;
144 : static double RESERVE_FOR_ONCOMING_MAX;
145 :
146 : /// @brief whether to use speed limits embedded in the network
147 : static bool USE_NET_SPEEDS;
148 :
149 : /// @brief the time pedestrians take to reach maximum impatience
150 : static const double MAX_WAIT_TOLERANCE;
151 :
152 : /// @brief the fraction of forward speed to be used for lateral movemenk
153 : static const double LATERAL_SPEED_FACTOR;
154 :
155 : /// @brief the minimum distance to the next obstacle in order to start walking after stopped
156 : static const double MIN_STARTUP_DIST;
157 :
158 : ///@}
159 :
160 : /// @brief Convert the striping to the vehicle lateral position and vice versa.
161 : // The striping model uses as lateral position the distance of the center of the pedestrian
162 : // to the left boundary of the lane minus a half stripe width, where right is positive.
163 : // The vehicle uses the distance to the center of the lane (and left is positive).
164 : // The function happens to be self inverse so it can be used to convert in both directions.
165 : inline static double posLatConversion(const double posLat, const double laneWidth) {
166 140 : return .5 * (laneWidth - stripeWidth) - posLat;
167 : }
168 :
169 :
170 : protected:
171 : static const double DIST_FAR_AWAY;
172 : static const double DIST_BEHIND;
173 : static const double DIST_OVERLAP;
174 :
175 : struct Obstacle;
176 : class PState;
177 : typedef std::vector<Obstacle> Obstacles;
178 : typedef std::map<const MSLane*, Obstacles, ComparatorNumericalIdLess> NextLanesObstacles;
179 : typedef std::map<const MSLane*, double> MinNextLengths;
180 :
181 : struct NextLaneInfo {
182 1528102 : NextLaneInfo(const MSLane* _lane, const MSLink* _link, int _dir) :
183 1528102 : lane(_lane),
184 1528102 : link(_link),
185 1528102 : dir(_dir) {
186 : }
187 :
188 681623 : NextLaneInfo() :
189 681623 : lane(0),
190 681623 : link(0),
191 243773 : dir(UNDEFINED_DIRECTION) {
192 : }
193 :
194 : /// @brief the next lane to be used
195 : const MSLane* lane;
196 : /// @brief the link from the current lane to the next lane
197 : const MSLink* link;
198 : /// @brief the direction on the next lane
199 : int dir;
200 : };
201 :
202 : enum ObstacleType {
203 : OBSTACLE_NONE = 0,
204 : OBSTACLE_PED = 1,
205 : OBSTACLE_VEHICLE = 3,
206 : OBSTACLE_END = 4,
207 : OBSTACLE_NEXTEND = 5,
208 : OBSTACLE_LINKCLOSED = 6,
209 : OBSTACLE_ARRIVALPOS = 7
210 : };
211 :
212 : /// @brief information regarding surround Pedestrians (and potentially other things)
213 1853847174 : struct Obstacle {
214 : /// @brief create No-Obstacle
215 : Obstacle(int dir, double dist = DIST_FAR_AWAY);
216 : /// @brief create an obstacle from ped for ego moving in dir
217 : Obstacle(const PState& ped);
218 : /// @brief create an obstacle from explicit values
219 : Obstacle(double _x, double _speed, ObstacleType _type, const std::string& _description, const double width = 0., const SUMOVehicle* veh = nullptr)
220 6474125 : : xFwd(_x + width / 2.), xBack(_x - width / 2.), speed(_speed), type(_type), description(_description), vehicle(veh) {};
221 :
222 : /// @brief maximal position on the current lane in forward direction
223 : double xFwd;
224 : /// @brief maximal position on the current lane in backward direction
225 : double xBack;
226 : /// @brief speed relative to lane direction (positive means in the same direction)
227 : double speed;
228 : /// @brief whether this obstacle denotes a border, a vehicle or a pedestrian
229 : ObstacleType type;
230 : /// @brief the id / description of the obstacle
231 : std::string description;
232 : /// @brief a pointer to the vehicle if this obstacle is one
233 : const SUMOVehicle* vehicle = nullptr;
234 :
235 : bool closer(const Obstacle& o, int dir);
236 : };
237 :
238 : class walkingarea_path_sorter {
239 : public:
240 : /// comparing operation
241 : bool operator()(const WalkingAreaPath* p1, const WalkingAreaPath* p2) const {
242 14022788 : if (p1->from->getNumericalID() < p2->from->getNumericalID()) {
243 : return true;
244 : }
245 13877909 : if (p1->from->getNumericalID() == p2->from->getNumericalID()) {
246 13780625 : if (p1->to->getNumericalID() < p2->to->getNumericalID()) {
247 : return true;
248 : }
249 : }
250 : return false;
251 : }
252 : };
253 :
254 :
255 : /**
256 : * @class PState
257 : * @brief Container for pedestrian state and individual position update function
258 : */
259 : class PState : public MSPModel_InteractingState {
260 : public:
261 : PState(MSPerson* person, MSStageMoving* stage, const MSLane* lane);
262 :
263 : /// @brief constructor for loading state
264 : PState(MSPerson* person, MSStageMoving* stage, std::istringstream* in = nullptr);
265 :
266 507030 : ~PState() {};
267 : Position getPosition(const MSStageMoving& stage, SUMOTime now) const;
268 : double getAngle(const MSStageMoving& stage, SUMOTime now) const;
269 : const MSEdge* getNextEdge(const MSStageMoving& stage) const;
270 : void moveTo(MSPerson* p, MSLane* lane, double lanePos, double lanePosLat, SUMOTime t);
271 : void moveToXY(MSPerson* p, Position pos, MSLane* lane, double lanePos,
272 : double lanePosLat, double angle, int routeOffset,
273 : const ConstMSEdgeVector& edges, SUMOTime t);
274 :
275 : /// @brief information about the upcoming lane
276 : NextLaneInfo myNLI;
277 : /// @brief the current walkingAreaPath or 0
278 : const WalkingAreaPath* myWalkingAreaPath;
279 :
280 : /// @brief return the minimum position on the lane
281 : virtual double getMinX(const bool includeMinGap = true) const;
282 :
283 : /// @brief return the maximum position on the lane
284 : virtual double getMaxX(const bool includeMinGap = true) const;
285 :
286 : /// @brief return the length of the pedestrian
287 : double getLength() const;
288 :
289 : /// @brief return the minimum gap of the pedestrian
290 : double getMinGap() const;
291 :
292 : /// @brief the absolute distance to the end of the lane in walking direction (or to the arrivalPos)
293 : double distToLaneEnd() const;
294 :
295 : /// @brief return whether this pedestrian has passed the end of the current lane and update myRelX if so
296 : bool moveToNextLane(SUMOTime currentTime);
297 :
298 : /// @brief perform position update
299 : void walk(const Obstacles& obs, SUMOTime currentTime);
300 :
301 : /// @brief returns the impatience
302 : double getImpatience(SUMOTime now) const;
303 :
304 : int stripe() const;
305 : int otherStripe() const;
306 :
307 : static int stripe(const double relY);
308 : int otherStripe(const double relY) const;
309 :
310 : /* @brief calculate distance to the given obstacle,
311 : * - non-negative values signify an obstacle in front of ego
312 : * the special values DIST_OVERLAP and DIST_BEHIND are used to signify
313 : * obstacles that overlap and obstacles behind ego respectively
314 : * the result is the same regardless of walking direction
315 : */
316 : double distanceTo(const Obstacle& obs, const bool includeMinGap = true) const;
317 :
318 : /// @brief replace obstacles in the first vector with obstacles from the second if they are closer to me
319 : void mergeObstacles(Obstacles& into, const Obstacles& obs2);
320 :
321 : /// @brief replace obstacles in the first vector with obstacles from the second if they are closer in the given direction
322 : static void mergeObstacles(Obstacles& into, const Obstacles& obs2, int dir, int offset);
323 :
324 : /// @brief whether the pedestrian may ignore a red light
325 : bool ignoreRed(const MSLink* link) const;
326 :
327 : /// @brief whether the pedestrian should stop at a yellow light
328 : bool stopForYellow(const MSLink* link) const;
329 :
330 : /// @brief return the person width
331 : virtual double getWidth() const;
332 :
333 672154397 : virtual ObstacleType getOType() const {
334 672154397 : return OBSTACLE_PED;
335 : }
336 :
337 : /// @brief whether the person is currently being controlled via TraCI
338 : bool isRemoteControlled() const;
339 :
340 : /** @brief Saves the current state into the given stream
341 : */
342 : void saveState(std::ostringstream& out);
343 :
344 : const MSLane* getNextCrossing() const;
345 :
346 : /// @brief return the lateral offset to the lane center
347 11733401 : double getLatOffset() const {
348 11733401 : return posLatConversion(myPosLat, myLane->getWidth());
349 : }
350 :
351 : inline double getPosLat() const {
352 11485528 : return myPosLat;
353 : }
354 :
355 : double getPathLength() const;
356 : void reverse(const double pathLength, const double usableWidth);
357 : void reset(const double edgePos, const double latPos);
358 :
359 : protected:
360 : /// @brief constructor for PStateVehicle
361 : PState();
362 : private:
363 : /// @brief Invalidated assignment operator.
364 : PState& operator=(const PState&) = delete;
365 : };
366 :
367 : class PStateVehicle : public PState {
368 : public:
369 : PStateVehicle(const MSVehicle* veh, const MSLane* walkingarea, double relX, double relY, double xWidth, double yWidth);
370 : const std::string& getID() const;
371 : double getMinX(const bool includeMinGap = true) const;
372 : double getMaxX(const bool includeMinGap = true) const;
373 : double getWidth() const;
374 :
375 463388 : ObstacleType getOType() const {
376 463388 : return OBSTACLE_VEHICLE;
377 : }
378 :
379 : const MSVehicle* getVehicle() const {
380 463388 : return myVehicle;
381 : }
382 : private:
383 : const MSVehicle* myVehicle;
384 : const double myXWidth;
385 : const double myYWidth;
386 : };
387 :
388 :
389 : class MovePedestrians : public Command {
390 : public:
391 3885 : MovePedestrians(MSPModel_Striping* model) : myModel(model) {};
392 3884 : ~MovePedestrians() {};
393 : SUMOTime execute(SUMOTime currentTime);
394 : private:
395 : MSPModel_Striping* const myModel;
396 : private:
397 : /// @brief Invalidated assignment operator.
398 : MovePedestrians& operator=(const MovePedestrians&) = delete;
399 : };
400 :
401 : /// @brief sorts the persons by position on the lane. If dir is forward, higher x positions come first.
402 : class by_xpos_sorter {
403 : public:
404 : /// constructor
405 : by_xpos_sorter(int dir): myDir(dir) {}
406 :
407 : public:
408 : /// comparing operation
409 2940167416 : bool operator()(const MSPModel_InteractingState* p1, const MSPModel_InteractingState* p2) const {
410 2940167416 : if (p1->getEdgePos(0) != p2->getEdgePos(0)) {
411 1410742033 : return myDir * p1->getEdgePos(0) > myDir * p2->getEdgePos(0);
412 : }
413 1529425383 : return p1->getID() < p2->getID();
414 : }
415 :
416 : private:
417 : const int myDir;
418 : };
419 :
420 :
421 : /// @brief move all pedestrians forward and advance to the next lane if applicable
422 : void moveInDirection(SUMOTime currentTime, std::set<MSPerson*>& changedLane, int dir);
423 :
424 : /// @brief move pedestrians forward on one lane
425 : void moveInDirectionOnLane(Pedestrians& pedestrians, const MSLane* lane, SUMOTime currentTime, std::set<MSPerson*>& changedLane, int dir, bool debug);
426 :
427 : /// @brief handle arrivals and lane advancement
428 : void arriveAndAdvance(Pedestrians& pedestrians, SUMOTime currentTime, std::set<MSPerson*>& changedLane, int dir);
429 :
430 : const ActiveLanes& getActiveLanes() {
431 : return myActiveLanes;
432 : }
433 :
434 : private:
435 : static void DEBUG_PRINT(const Obstacles& obs);
436 :
437 : /// @brief returns the direction in which these lanes are connectioned or 0 if they are not
438 : static int connectedDirection(const MSLane* from, const MSLane* to);
439 :
440 : /** @brief computes the successor lane for the given pedestrian and sets the
441 : * link as well as the direction to use on the succesor lane
442 : * @param[in] currentLane The lane the pedestrian is currently on
443 : * @param[in] ped The pedestrian for which to compute the next lane
444 : */
445 : static NextLaneInfo getNextLane(const PState& ped, const MSLane* currentLane, const MSLane* prevLane);
446 :
447 : /// @brief return the next walkingArea in the given direction
448 : static const MSLane* getNextWalkingArea(const MSLane* currentLane, const int dir, const MSLink*& link);
449 :
450 : static void initWalkingAreaPaths(const MSNet* net);
451 :
452 : /// @brief creates and inserts all paths into the given map
453 : static void insertWalkArePaths(const MSEdge* edge, WalkingAreaPaths& into);
454 :
455 : static const WalkingAreaPath* getWalkingAreaPath(const MSEdge* walkingArea, const MSLane* before, const MSLane* after);
456 :
457 : /// @brief return an arbitrary path across the given walkingArea
458 : static const WalkingAreaPath* getArbitraryPath(const MSEdge* walkingArea);
459 :
460 : static const WalkingAreaPath* guessPath(const MSEdge* walkingArea, const MSEdge* before, const MSEdge* after);
461 :
462 : /// @brief return the maximum number of pedestrians walking side by side
463 : static int numStripes(const MSLane* lane);
464 :
465 : static Obstacles getNeighboringObstacles(const Pedestrians& pedestrians, int egoIndex, int stripes);
466 :
467 : const Obstacles& getNextLaneObstacles(NextLanesObstacles& nextLanesObs, const MSLane* lane, const MSLane* nextLane, int stripes,
468 : int nextDir, double currentLength, int currentDir);
469 :
470 : static void transformToCurrentLanePositions(Obstacles& o, int currentDir, int nextDir, double currentLength, double nextLength);
471 :
472 : static void addCloserObstacle(Obstacles& obs, double x, int stripe, int numStripes, const std::string& id, double width, int dir, ObstacleType type);
473 :
474 : /* @brief compute stripe-offset to transform relY values from a lane with origStripes into a lane wit destStrips
475 : * @note this is called once for transforming nextLane peds to into the current system as obstacles and another time
476 : * (in reverse) to transform the pedestrian coordinates into the nextLane-coordinates when changing lanes
477 : */
478 : static int getStripeOffset(int origStripes, int destStripes, bool addRemainder);
479 :
480 : ///@brief add vehicles driving across
481 : static bool addCrossingVehs(const MSLane* crossing, int stripes, double lateral_offset, int dir, Obstacles& crossingVehs, bool prio);
482 :
483 : ///@brief retrieve vehicle obstacles on the given lane
484 : static Obstacles getVehicleObstacles(const MSLane* lane, int dir, PState* ped = 0);
485 :
486 : static bool addVehicleFoe(const MSVehicle* veh, const MSLane* walkingarea, const Position& relPos, double xWidth, double yWidth, double lateral_offset,
487 : double minY, double maxY, Pedestrians& toDelete, Pedestrians& transformedPeds);
488 :
489 : static int getReserved(int stripes, double factor);
490 :
491 : /// @brief register pedestrian approach with the junction model
492 : static void registerCrossingApproach(const PState& ped, const MSLane* crossing, const MSLane* beforeWA);
493 :
494 : private:
495 : /// @brief store for walkinArea elements
496 : static WalkingAreaPaths myWalkingAreaPaths;
497 : static std::map<const MSEdge*, std::vector<const MSLane*> > myWalkingAreaFoes;
498 : static MinNextLengths myMinNextLengths;
499 : };
|