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 706320 : struct WalkingAreaPath {
56 176580 : WalkingAreaPath(const MSLane* _from, const MSLane* _walkingArea, const MSLane* _to, const PositionVector& _shape, int _dir, double _angleOverride) :
57 176580 : from(_from),
58 176580 : to(_to),
59 176580 : lane(_walkingArea),
60 0 : shape(_shape),
61 176580 : dir(_dir),
62 176580 : angleOverride(_angleOverride),
63 176580 : length(_shape.length()) {
64 176580 : }
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 the time pedestrians take to reach maximum impatience
147 : static const double MAX_WAIT_TOLERANCE;
148 :
149 : /// @brief the fraction of forward speed to be used for lateral movemenk
150 : static const double LATERAL_SPEED_FACTOR;
151 :
152 : /// @brief the minimum distance to the next obstacle in order to start walking after stopped
153 : static const double MIN_STARTUP_DIST;
154 :
155 : ///@}
156 :
157 : /// @brief Convert the striping to the vehicle lateral position and vice versa.
158 : // The striping model uses as lateral position the distance of the center of the pedestrian
159 : // to the left boundary of the lane minus a half stripe width, where right is positive.
160 : // The vehicle uses the distance to the center of the lane (and left is positive).
161 : // The function happens to be self inverse so it can be used to convert in both directions.
162 : inline static double posLatConversion(const double posLat, const double laneWidth) {
163 140 : return .5 * (laneWidth - stripeWidth) - posLat;
164 : }
165 :
166 :
167 : protected:
168 : static const double DIST_FAR_AWAY;
169 : static const double DIST_BEHIND;
170 : static const double DIST_OVERLAP;
171 :
172 : struct Obstacle;
173 : class PState;
174 : typedef std::vector<Obstacle> Obstacles;
175 : typedef std::map<const MSLane*, Obstacles, ComparatorNumericalIdLess> NextLanesObstacles;
176 : typedef std::map<const MSLane*, double> MinNextLengths;
177 :
178 : struct NextLaneInfo {
179 1396452 : NextLaneInfo(const MSLane* _lane, const MSLink* _link, int _dir) :
180 1396452 : lane(_lane),
181 1396452 : link(_link),
182 1396452 : dir(_dir) {
183 : }
184 :
185 653168 : NextLaneInfo() :
186 653168 : lane(0),
187 653168 : link(0),
188 214226 : dir(UNDEFINED_DIRECTION) {
189 : }
190 :
191 : /// @brief the next lane to be used
192 : const MSLane* lane;
193 : /// @brief the link from the current lane to the next lane
194 : const MSLink* link;
195 : /// @brief the direction on the next lane
196 : int dir;
197 : };
198 :
199 : enum ObstacleType {
200 : OBSTACLE_NONE = 0,
201 : OBSTACLE_PED = 1,
202 : OBSTACLE_VEHICLE = 3,
203 : OBSTACLE_END = 4,
204 : OBSTACLE_NEXTEND = 5,
205 : OBSTACLE_LINKCLOSED = 6,
206 : OBSTACLE_ARRIVALPOS = 7
207 : };
208 :
209 : /// @brief information regarding surround Pedestrians (and potentially other things)
210 1391565215 : struct Obstacle {
211 : /// @brief create No-Obstacle
212 : Obstacle(int dir, double dist = DIST_FAR_AWAY);
213 : /// @brief create an obstacle from ped for ego moving in dir
214 : Obstacle(const PState& ped);
215 : /// @brief create an obstacle from explicit values
216 : Obstacle(double _x, double _speed, ObstacleType _type, const std::string& _description, const double width = 0., const SUMOVehicle* veh = nullptr)
217 6090003 : : xFwd(_x + width / 2.), xBack(_x - width / 2.), speed(_speed), type(_type), description(_description), vehicle(veh) {};
218 :
219 : /// @brief maximal position on the current lane in forward direction
220 : double xFwd;
221 : /// @brief maximal position on the current lane in backward direction
222 : double xBack;
223 : /// @brief speed relative to lane direction (positive means in the same direction)
224 : double speed;
225 : /// @brief whether this obstacle denotes a border, a vehicle or a pedestrian
226 : ObstacleType type;
227 : /// @brief the id / description of the obstacle
228 : std::string description;
229 : /// @brief a pointer to the vehicle if this obstacle is one
230 : const SUMOVehicle* vehicle = nullptr;
231 :
232 : bool closer(const Obstacle& o, int dir);
233 : };
234 :
235 : class walkingarea_path_sorter {
236 : public:
237 : /// comparing operation
238 : bool operator()(const WalkingAreaPath* p1, const WalkingAreaPath* p2) const {
239 9850766 : if (p1->from->getNumericalID() < p2->from->getNumericalID()) {
240 : return true;
241 : }
242 9706089 : if (p1->from->getNumericalID() == p2->from->getNumericalID()) {
243 9608627 : if (p1->to->getNumericalID() < p2->to->getNumericalID()) {
244 : return true;
245 : }
246 : }
247 : return false;
248 : }
249 : };
250 :
251 :
252 : /**
253 : * @class PState
254 : * @brief Container for pedestrian state and individual position update function
255 : */
256 : class PState : public MSPModel_InteractingState {
257 : public:
258 : PState(MSPerson* person, MSStageMoving* stage, const MSLane* lane);
259 :
260 : /// @brief constructor for loading state
261 : PState(MSPerson* person, MSStageMoving* stage, std::istringstream* in = nullptr);
262 :
263 477330 : ~PState() {};
264 : Position getPosition(const MSStageMoving& stage, SUMOTime now) const;
265 : double getAngle(const MSStageMoving& stage, SUMOTime now) const;
266 : const MSEdge* getNextEdge(const MSStageMoving& stage) const;
267 : void moveTo(MSPerson* p, MSLane* lane, double lanePos, double lanePosLat, SUMOTime t);
268 : void moveToXY(MSPerson* p, Position pos, MSLane* lane, double lanePos,
269 : double lanePosLat, double angle, int routeOffset,
270 : const ConstMSEdgeVector& edges, SUMOTime t);
271 :
272 : /// @brief information about the upcoming lane
273 : NextLaneInfo myNLI;
274 : /// @brief the current walkingAreaPath or 0
275 : const WalkingAreaPath* myWalkingAreaPath;
276 :
277 : /// @brief return the minimum position on the lane
278 : virtual double getMinX(const bool includeMinGap = true) const;
279 :
280 : /// @brief return the maximum position on the lane
281 : virtual double getMaxX(const bool includeMinGap = true) const;
282 :
283 : /// @brief return the length of the pedestrian
284 : double getLength() const;
285 :
286 : /// @brief return the minimum gap of the pedestrian
287 : double getMinGap() const;
288 :
289 : /// @brief the absolute distance to the end of the lane in walking direction (or to the arrivalPos)
290 : double distToLaneEnd() const;
291 :
292 : /// @brief return whether this pedestrian has passed the end of the current lane and update myRelX if so
293 : bool moveToNextLane(SUMOTime currentTime);
294 :
295 : /// @brief perform position update
296 : void walk(const Obstacles& obs, SUMOTime currentTime);
297 :
298 : /// @brief returns the impatience
299 : double getImpatience(SUMOTime now) const;
300 :
301 : int stripe() const;
302 : int otherStripe() const;
303 :
304 : static int stripe(const double relY);
305 : int otherStripe(const double relY) const;
306 :
307 : /* @brief calculate distance to the given obstacle,
308 : * - non-negative values signify an obstacle in front of ego
309 : * the special values DIST_OVERLAP and DIST_BEHIND are used to signify
310 : * obstacles that overlap and obstacles behind ego respectively
311 : * the result is the same regardless of walking direction
312 : */
313 : double distanceTo(const Obstacle& obs, const bool includeMinGap = true) const;
314 :
315 : /// @brief replace obstacles in the first vector with obstacles from the second if they are closer to me
316 : void mergeObstacles(Obstacles& into, const Obstacles& obs2);
317 :
318 : /// @brief replace obstacles in the first vector with obstacles from the second if they are closer in the given direction
319 : static void mergeObstacles(Obstacles& into, const Obstacles& obs2, int dir, int offset);
320 :
321 : /// @brief whether the pedestrian may ignore a red light
322 : bool ignoreRed(const MSLink* link) const;
323 :
324 : /// @brief return the person width
325 : virtual double getWidth() const;
326 :
327 471161654 : virtual ObstacleType getOType() const {
328 471161654 : return OBSTACLE_PED;
329 : }
330 :
331 : /// @brief whether the person is currently being controlled via TraCI
332 : bool isRemoteControlled() const;
333 :
334 : /** @brief Saves the current state into the given stream
335 : */
336 : void saveState(std::ostringstream& out);
337 :
338 : const MSLane* getNextCrossing() const;
339 :
340 : /// @brief return the lateral offset to the lane center
341 11472244 : double getLatOffset() const {
342 11472244 : return posLatConversion(myPosLat, myLane->getWidth());
343 : }
344 :
345 : inline double getPosLat() const {
346 10056707 : return myPosLat;
347 : }
348 :
349 : double getPathLength() const;
350 : void reverse(const double pathLength, const double usableWidth);
351 : void reset(const double edgePos, const double latPos);
352 :
353 : protected:
354 : /// @brief constructor for PStateVehicle
355 : PState();
356 : private:
357 : /// @brief Invalidated assignment operator.
358 : PState& operator=(const PState&) = delete;
359 : };
360 :
361 : class PStateVehicle : public PState {
362 : public:
363 : PStateVehicle(const MSVehicle* veh, const MSLane* walkingarea, double relX, double relY, double xWidth, double yWidth);
364 : const std::string& getID() const;
365 : double getMinX(const bool includeMinGap = true) const;
366 : double getMaxX(const bool includeMinGap = true) const;
367 : double getWidth() const;
368 :
369 464765 : ObstacleType getOType() const {
370 464765 : return OBSTACLE_VEHICLE;
371 : }
372 :
373 : const MSVehicle* getVehicle() const {
374 464765 : return myVehicle;
375 : }
376 : private:
377 : const MSVehicle* myVehicle;
378 : const double myXWidth;
379 : const double myYWidth;
380 : };
381 :
382 :
383 : class MovePedestrians : public Command {
384 : public:
385 3839 : MovePedestrians(MSPModel_Striping* model) : myModel(model) {};
386 3838 : ~MovePedestrians() {};
387 : SUMOTime execute(SUMOTime currentTime);
388 : private:
389 : MSPModel_Striping* const myModel;
390 : private:
391 : /// @brief Invalidated assignment operator.
392 : MovePedestrians& operator=(const MovePedestrians&) = delete;
393 : };
394 :
395 : /// @brief sorts the persons by position on the lane. If dir is forward, higher x positions come first.
396 : class by_xpos_sorter {
397 : public:
398 : /// constructor
399 : by_xpos_sorter(int dir): myDir(dir) {}
400 :
401 : public:
402 : /// comparing operation
403 1806953222 : bool operator()(const MSPModel_InteractingState* p1, const MSPModel_InteractingState* p2) const {
404 1806953222 : if (p1->getEdgePos(0) != p2->getEdgePos(0)) {
405 857878105 : return myDir * p1->getEdgePos(0) > myDir * p2->getEdgePos(0);
406 : }
407 949075117 : return p1->getID() < p2->getID();
408 : }
409 :
410 : private:
411 : const int myDir;
412 : };
413 :
414 :
415 : /// @brief move all pedestrians forward and advance to the next lane if applicable
416 : void moveInDirection(SUMOTime currentTime, std::set<MSPerson*>& changedLane, int dir);
417 :
418 : /// @brief move pedestrians forward on one lane
419 : void moveInDirectionOnLane(Pedestrians& pedestrians, const MSLane* lane, SUMOTime currentTime, std::set<MSPerson*>& changedLane, int dir, bool debug);
420 :
421 : /// @brief handle arrivals and lane advancement
422 : void arriveAndAdvance(Pedestrians& pedestrians, SUMOTime currentTime, std::set<MSPerson*>& changedLane, int dir);
423 :
424 : const ActiveLanes& getActiveLanes() {
425 : return myActiveLanes;
426 : }
427 :
428 : private:
429 : static void DEBUG_PRINT(const Obstacles& obs);
430 :
431 : /// @brief returns the direction in which these lanes are connectioned or 0 if they are not
432 : static int connectedDirection(const MSLane* from, const MSLane* to);
433 :
434 : /** @brief computes the successor lane for the given pedestrian and sets the
435 : * link as well as the direction to use on the succesor lane
436 : * @param[in] currentLane The lane the pedestrian is currently on
437 : * @param[in] ped The pedestrian for which to compute the next lane
438 : */
439 : static NextLaneInfo getNextLane(const PState& ped, const MSLane* currentLane, const MSLane* prevLane);
440 :
441 : /// @brief return the next walkingArea in the given direction
442 : static const MSLane* getNextWalkingArea(const MSLane* currentLane, const int dir, const MSLink*& link);
443 :
444 : static void initWalkingAreaPaths(const MSNet* net);
445 :
446 : /// @brief creates and inserts all paths into the given map
447 : static void insertWalkArePaths(const MSEdge* edge, WalkingAreaPaths& into);
448 :
449 : static const WalkingAreaPath* getWalkingAreaPath(const MSEdge* walkingArea, const MSLane* before, const MSLane* after);
450 :
451 : /// @brief return an arbitrary path across the given walkingArea
452 : static const WalkingAreaPath* getArbitraryPath(const MSEdge* walkingArea);
453 :
454 : static const WalkingAreaPath* guessPath(const MSEdge* walkingArea, const MSEdge* before, const MSEdge* after);
455 :
456 : /// @brief return the maximum number of pedestrians walking side by side
457 : static int numStripes(const MSLane* lane);
458 :
459 : static Obstacles getNeighboringObstacles(const Pedestrians& pedestrians, int egoIndex, int stripes);
460 :
461 : const Obstacles& getNextLaneObstacles(NextLanesObstacles& nextLanesObs, const MSLane* lane, const MSLane* nextLane, int stripes,
462 : int nextDir, double currentLength, int currentDir);
463 :
464 : static void transformToCurrentLanePositions(Obstacles& o, int currentDir, int nextDir, double currentLength, double nextLength);
465 :
466 : static void addCloserObstacle(Obstacles& obs, double x, int stripe, int numStripes, const std::string& id, double width, int dir, ObstacleType type);
467 :
468 : /* @brief compute stripe-offset to transform relY values from a lane with origStripes into a lane wit destStrips
469 : * @note this is called once for transforming nextLane peds to into the current system as obstacles and another time
470 : * (in reverse) to transform the pedestrian coordinates into the nextLane-coordinates when changing lanes
471 : */
472 : static int getStripeOffset(int origStripes, int destStripes, bool addRemainder);
473 :
474 : ///@brief add vehicles driving across
475 : static bool addCrossingVehs(const MSLane* crossing, int stripes, double lateral_offset, int dir, Obstacles& crossingVehs, bool prio);
476 :
477 : ///@brief retrieve vehicle obstacles on the given lane
478 : static Obstacles getVehicleObstacles(const MSLane* lane, int dir, PState* ped = 0);
479 :
480 : static bool addVehicleFoe(const MSVehicle* veh, const MSLane* walkingarea, const Position& relPos, double xWidth, double yWidth, double lateral_offset,
481 : double minY, double maxY, Pedestrians& toDelete, Pedestrians& transformedPeds);
482 :
483 : static int getReserved(int stripes, double factor);
484 :
485 : /// @brief register pedestrian approach with the junction model
486 : static void registerCrossingApproach(const PState& ped, const MSLane* crossing, const MSLane* beforeWA);
487 :
488 : private:
489 : /// @brief store for walkinArea elements
490 : static WalkingAreaPaths myWalkingAreaPaths;
491 : static std::map<const MSEdge*, std::vector<const MSLane*> > myWalkingAreaFoes;
492 : static MinNextLengths myMinNextLengths;
493 : };
|