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 following model (prototype)
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.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 following model
47 : *
48 : */
49 : class MSPModel_Striping : public MSPModel {
50 :
51 : friend class GUIPerson; // for debugging
52 :
53 : public:
54 :
55 535720 : struct WalkingAreaPath {
56 133930 : WalkingAreaPath(const MSLane* _from, const MSLane* _walkingArea, const MSLane* _to, const PositionVector& _shape, int _dir, double _angleOverride) :
57 133930 : from(_from),
58 133930 : to(_to),
59 133930 : lane(_walkingArea),
60 133930 : shape(_shape),
61 133930 : dir(_dir),
62 133930 : angleOverride(_angleOverride),
63 133930 : length(_shape.length()) {
64 133930 : }
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 Resets pedestrians when quick-loading state
84 : void clearState();
85 :
86 : /// @brief register the given person as a pedestrian
87 : MSTransportableStateAdapter* add(MSTransportable* transportable, MSStageMoving* stage, SUMOTime now);
88 :
89 : /// @brief load the state of the given transportable
90 : MSTransportableStateAdapter* loadState(MSTransportable* transportable, MSStageMoving* stage, std::istringstream& in);
91 :
92 : /// @brief remove the specified person from the pedestrian simulation
93 : void remove(MSTransportableStateAdapter* state);
94 :
95 : /** @brief whether a pedestrian is blocking the crossing of lane for the given vehicle bondaries
96 : * @param[in] ego The object that inquires about blockage (and may electively ignore foes)
97 : * @param[in] lane The crossing to check
98 : * @param[in] vehside The offset to the vehicle side near the start of the crossing
99 : * @param[in] vehWidth The width of the vehicle
100 : * @param[in] oncomingGap The distance which the vehicle wants to keep from oncoming pedestrians
101 : * @param[in] collectBlockers The list of persons blocking the crossing
102 : * @return Whether the vehicle must wait
103 : */
104 : bool blockedAtDist(const SUMOTrafficObject* ego, const MSLane* lane, double vehSide, double vehWidth,
105 : double oncomingGap, std::vector<const MSPerson*>* collectBlockers);
106 :
107 : /// @brief whether the given lane has pedestrians on it
108 : bool hasPedestrians(const MSLane* lane);
109 :
110 : /// @brief whether movements on intersections are modelled
111 : //// @note function declared as member for sake of inheritance (delegates to static function)
112 : bool usingInternalLanes();
113 :
114 : /// @brief returns the next pedestrian beyond minPos that is laterally between minRight and maxLeft or 0
115 : PersonDist nextBlocking(const MSLane* lane, double minPos, double minRight, double maxLeft, double stopTime = 0, bool bidi = false);
116 :
117 : /// @brief model parameters
118 : ///@{
119 :
120 : // @brief the width of a pedstrian stripe
121 : static double stripeWidth;
122 :
123 : // @brief the factor for random slow-down
124 : static double dawdling;
125 :
126 : // @brief the safety buffer to vehicles
127 : static double minGapToVehicle;
128 :
129 : // @brief intermediate points to smooth out lanes within the walkingarea
130 : static int myWalkingAreaDetail;
131 :
132 : // @brief the time threshold before becoming jammed
133 : static SUMOTime jamTime;
134 : static SUMOTime jamTimeCrossing;
135 : static SUMOTime jamTimeNarrow;
136 :
137 : // @brief use old style departPosLat interpretation
138 : static bool myLegacyPosLat;
139 :
140 : // @brief the distance (in seconds) to look ahead for changing stripes
141 : static const double LOOKAHEAD_SAMEDIR;
142 : // @brief the distance (in seconds) to look ahead for changing stripes (regarding oncoming pedestrians)
143 : static const double LOOKAHEAD_ONCOMING;
144 : // @brief the distance (in m) to look around for vehicles
145 : static const double LOOKAROUND_VEHICLES;
146 :
147 : // @brief the utility penalty for moving sideways (corresponds to meters)
148 : static const double LATERAL_PENALTY;
149 :
150 : // @brief the utility penalty for obstructed (physically blocking me) stripes (corresponds to meters)
151 : static const double OBSTRUCTED_PENALTY;
152 :
153 : // @brief the utility penalty for inappropriate (reserved for oncoming traffic or may violate my min gap) stripes (corresponds to meters)
154 : static const double INAPPROPRIATE_PENALTY;
155 :
156 : // @brief the utility penalty for oncoming conflicts on stripes (corresponds to meters)
157 : static const double ONCOMING_CONFLICT_PENALTY;
158 :
159 : // @brief the minimum utility that indicates obstruction
160 : static const double OBSTRUCTION_THRESHOLD;
161 :
162 : // @brief the factor by which pedestrian width is reduced when sqeezing past each other
163 : static const double SQUEEZE;
164 :
165 : // @brief fraction of the leftmost lanes to reserve for oncoming traffic
166 : static double RESERVE_FOR_ONCOMING_FACTOR;
167 : static double RESERVE_FOR_ONCOMING_FACTOR_JUNCTIONS;
168 : static double RESERVE_FOR_ONCOMING_MAX;
169 :
170 : // @brief the time pedestrians take to reach maximum impatience
171 : static const double MAX_WAIT_TOLERANCE;
172 :
173 : // @brief the fraction of forward speed to be used for lateral movemenk
174 : static const double LATERAL_SPEED_FACTOR;
175 :
176 : // @brief the minimum distance to the next obstacle in order to start walking after stopped
177 : static const double MIN_STARTUP_DIST;
178 :
179 : ///@}
180 :
181 :
182 : protected:
183 : static const double DIST_FAR_AWAY;
184 : static const double DIST_BEHIND;
185 : static const double DIST_OVERLAP;
186 :
187 : class lane_by_numid_sorter {
188 : public:
189 : /// comparing operation
190 : bool operator()(const MSLane* l1, const MSLane* l2) const {
191 0 : return l1->getNumericalID() < l2->getNumericalID();
192 : }
193 : };
194 :
195 : struct Obstacle;
196 : class PState;
197 : typedef std::vector<PState*> Pedestrians;
198 : typedef std::map<const MSLane*, Pedestrians, lane_by_numid_sorter> ActiveLanes;
199 : typedef std::vector<Obstacle> Obstacles;
200 : typedef std::map<const MSLane*, Obstacles, lane_by_numid_sorter> NextLanesObstacles;
201 : typedef std::map<const MSLane*, double> MinNextLengths;
202 :
203 : struct NextLaneInfo {
204 1253405 : NextLaneInfo(const MSLane* _lane, const MSLink* _link, int _dir) :
205 1253405 : lane(_lane),
206 1253405 : link(_link),
207 1253405 : dir(_dir) {
208 : }
209 :
210 819768 : NextLaneInfo() :
211 819768 : lane(0),
212 819768 : link(0),
213 269571 : dir(UNDEFINED_DIRECTION) {
214 : }
215 :
216 : // @brief the next lane to be used
217 : const MSLane* lane;
218 : // @brief the link from the current lane to the next lane
219 : const MSLink* link;
220 : // @brief the direction on the next lane
221 : int dir;
222 : };
223 :
224 : enum ObstacleType {
225 : OBSTACLE_NONE = 0,
226 : OBSTACLE_PED = 1,
227 : OBSTACLE_VEHICLE = 3,
228 : OBSTACLE_END = 4,
229 : OBSTACLE_NEXTEND = 5,
230 : OBSTACLE_LINKCLOSED = 6,
231 : OBSTACLE_ARRIVALPOS = 7
232 : };
233 :
234 : /// @brief information regarding surround Pedestrians (and potentially other things)
235 1257352445 : struct Obstacle {
236 : /// @brief create No-Obstacle
237 : Obstacle(int dir, double dist = DIST_FAR_AWAY);
238 : /// @brief create an obstacle from ped for ego moving in dir
239 : Obstacle(const PState& ped);
240 : /// @brief create an obstacle from explict values
241 : Obstacle(double _x, double _speed, ObstacleType _type, const std::string& _description, const double width = 0., const SUMOVehicle* veh = nullptr)
242 3843145 : : xFwd(_x + width / 2.), xBack(_x - width / 2.), speed(_speed), type(_type), description(_description), vehicle(veh) {};
243 :
244 : /// @brief maximal position on the current lane in forward direction
245 : double xFwd;
246 : /// @brief maximal position on the current lane in backward direction
247 : double xBack;
248 : /// @brief speed relative to lane direction (positive means in the same direction)
249 : double speed;
250 : /// @brief whether this obstacle denotes a border or a pedestrian
251 : ObstacleType type;
252 : /// @brief the id / description of the obstacle
253 : std::string description;
254 : /// @brief a pointer to the vehicle if this obstacle is one
255 : const SUMOVehicle* vehicle = nullptr;
256 :
257 : bool closer(const Obstacle& o, int dir);
258 : };
259 :
260 : class walkingarea_path_sorter {
261 : public:
262 : /// comparing operation
263 : bool operator()(const WalkingAreaPath* p1, const WalkingAreaPath* p2) const {
264 2456815 : if (p1->from->getNumericalID() < p2->from->getNumericalID()) {
265 : return true;
266 : }
267 2311380 : if (p1->from->getNumericalID() == p2->from->getNumericalID()) {
268 2216018 : if (p1->to->getNumericalID() < p2->to->getNumericalID()) {
269 : return true;
270 : }
271 : }
272 : return false;
273 : }
274 : };
275 :
276 :
277 : /**
278 : * @class PState
279 : * @brief Container for pedestrian state and individual position update function
280 : */
281 : class PState : public MSTransportableStateAdapter {
282 : public:
283 :
284 : /// @brief abstract methods inherited from PedestrianState
285 : /// @{
286 : double getEdgePos(const MSStageMoving& stage, SUMOTime now) const;
287 : int getDirection(const MSStageMoving& stage, SUMOTime now) const;
288 : Position getPosition(const MSStageMoving& stage, SUMOTime now) const;
289 : double getAngle(const MSStageMoving& stage, SUMOTime now) const;
290 : SUMOTime getWaitingTime(const MSStageMoving& stage, SUMOTime now) const;
291 : double getSpeed(const MSStageMoving& stage) const;
292 : const MSEdge* getNextEdge(const MSStageMoving& stage) const;
293 : void moveTo(MSPerson* p, MSLane* lane, double lanePos, double lanePosLat, SUMOTime t);
294 : void moveToXY(MSPerson* p, Position pos, MSLane* lane, double lanePos,
295 : double lanePosLat, double angle, int routeOffset,
296 : const ConstMSEdgeVector& edges, SUMOTime t);
297 : /// @brief whether the transportable is jammed
298 : bool isJammed() const;
299 : const MSLane* getLane() const;
300 : double getPathLength() const;
301 : /// @}
302 :
303 : PState(MSPerson* person, MSStageMoving* stage, const MSLane* lane);
304 :
305 : /// @brief constructor for loading state
306 : PState(MSPerson* person, MSStageMoving* stage, std::istringstream* in = nullptr);
307 :
308 525554 : ~PState() {};
309 : MSPerson* myPerson;
310 : MSStageMoving* myStage;
311 : /// @brief the current lane of this pedestrian
312 : const MSLane* myLane;
313 : /// @brief the advancement along the current lane
314 : double myRelX;
315 : /// @brief the orthogonal shift on the current lane
316 : double myRelY;
317 : /// @brief the walking direction on the current lane (1 forward, -1 backward)
318 : int myDir;
319 : /// @brief the current walking speed
320 : double mySpeed;
321 : /// @brief the current lateral walking speed
322 : double mySpeedLat;
323 : /// @brief whether the pedestrian is waiting to start its walk
324 : bool myWaitingToEnter;
325 : /// @brief the consecutive time spent at speed 0
326 : SUMOTime myWaitingTime;
327 : /// @brief information about the upcoming lane
328 : NextLaneInfo myNLI;
329 : /// @brief the current walkingAreaPath or 0
330 : const WalkingAreaPath* myWalkingAreaPath;
331 : /// @brief whether the person is jammed
332 : bool myAmJammed;
333 : /// @brief remote-controlled position
334 : Position myRemoteXYPos;
335 : /// @brief cached angle
336 : mutable double myAngle;
337 :
338 : /// @brief return the minimum position on the lane
339 : virtual double getMinX(const bool includeMinGap = true) const;
340 :
341 : /// @brief return the maximum position on the lane
342 : virtual double getMaxX(const bool includeMinGap = true) const;
343 :
344 : /// @brief return the length of the pedestrian
345 : double getLength() const;
346 :
347 : /// @brief return the minimum gap of the pedestrian
348 : double getMinGap() const;
349 :
350 : /// @brief the absolute distance to the end of the lane in walking direction (or to the arrivalPos)
351 : double distToLaneEnd() const;
352 :
353 : /// @brief return whether this pedestrian has passed the end of the current lane and update myRelX if so
354 : bool moveToNextLane(SUMOTime currentTime);
355 :
356 : /// @brief perform position update
357 : void walk(const Obstacles& obs, SUMOTime currentTime);
358 :
359 : /// @brief returns the impatience
360 : double getImpatience(SUMOTime now) const;
361 :
362 : int stripe() const;
363 : int otherStripe() const;
364 :
365 : static int stripe(const double relY);
366 : int otherStripe(const double relY) const;
367 :
368 : /* @brief calculate distance to the given obstacle,
369 : * - non-negative values signify an obstacle in front of ego
370 : * the special values DIST_OVERLAP and DIST_BEHIND are used to signify
371 : * obstacles that overlap and obstacles behind ego respectively
372 : * the result is the same regardless of walking direction
373 : */
374 : double distanceTo(const Obstacle& obs, const bool includeMinGap = true) const;
375 :
376 : /// @brief replace obstacles in the first vector with obstacles from the second if they are closer to me
377 : void mergeObstacles(Obstacles& into, const Obstacles& obs2);
378 :
379 : /// @brief replace obstacles in the first vector with obstacles from the second if they are closer in the given direction
380 : static void mergeObstacles(Obstacles& into, const Obstacles& obs2, int dir, int offset);
381 :
382 : /// @brief whether the pedestrian may ignore a red light
383 : bool ignoreRed(const MSLink* link) const;
384 :
385 : /// @brief return the person id
386 : virtual const std::string& getID() const;
387 :
388 : /// @brief return the person width
389 : virtual double getWidth() const;
390 :
391 384856437 : virtual ObstacleType getOType() const {
392 384856437 : return OBSTACLE_PED;
393 : }
394 :
395 : /// @brief whether the person is currently being controlled via TraCI
396 : bool isRemoteControlled() const;
397 :
398 : /** @brief Saves the current state into the given stream
399 : */
400 : void saveState(std::ostringstream& out);
401 :
402 : protected:
403 : /// @brief constructor for PStateVehicle
404 : PState();
405 : private:
406 : /// @brief Invalidated assignment operator.
407 : PState& operator=(const PState&) = delete;
408 : };
409 :
410 : class PStateVehicle : public PState {
411 : public:
412 : PStateVehicle(const MSVehicle* veh, const MSLane* walkingarea, double relX, double relY, double xWidth, double yWidth);
413 : const std::string& getID() const;
414 : double getMinX(const bool includeMinGap = true) const;
415 : double getMaxX(const bool includeMinGap = true) const;
416 : double getWidth() const;
417 :
418 585143 : ObstacleType getOType() const {
419 585143 : return OBSTACLE_VEHICLE;
420 : }
421 :
422 : const MSVehicle* getVehicle() const {
423 585143 : return myVehicle;
424 : }
425 : private:
426 : const MSVehicle* myVehicle;
427 : const double myXWidth;
428 : const double myYWidth;
429 : };
430 :
431 :
432 : class MovePedestrians : public Command {
433 : public:
434 2174 : MovePedestrians(MSPModel_Striping* model) : myModel(model) {};
435 2173 : ~MovePedestrians() {};
436 : SUMOTime execute(SUMOTime currentTime);
437 : private:
438 : MSPModel_Striping* const myModel;
439 : private:
440 : /// @brief Invalidated assignment operator.
441 : MovePedestrians& operator=(const MovePedestrians&) = delete;
442 : };
443 :
444 : /// @brief sorts the persons by position on the lane. If dir is forward, higher x positions come first.
445 : class by_xpos_sorter {
446 : public:
447 : /// constructor
448 : by_xpos_sorter(int dir): myDir(dir) {}
449 :
450 : public:
451 : /// comparing operation
452 1884551515 : bool operator()(const PState* p1, const PState* p2) const {
453 1884551515 : if (p1->myRelX != p2->myRelX) {
454 715313315 : return myDir * p1->myRelX > myDir * p2->myRelX;
455 : }
456 1169238200 : return p1->getID() < p2->getID();
457 : }
458 :
459 : private:
460 : const int myDir;
461 : };
462 :
463 :
464 : /// @brief move all pedestrians forward and advance to the next lane if applicable
465 : void moveInDirection(SUMOTime currentTime, std::set<MSPerson*>& changedLane, int dir);
466 :
467 : /// @brief move pedestrians forward on one lane
468 : void moveInDirectionOnLane(Pedestrians& pedestrians, const MSLane* lane, SUMOTime currentTime, std::set<MSPerson*>& changedLane, int dir, bool debug);
469 :
470 : /// @brief handle arrivals and lane advancement
471 : void arriveAndAdvance(Pedestrians& pedestrians, SUMOTime currentTime, std::set<MSPerson*>& changedLane, int dir);
472 :
473 : const ActiveLanes& getActiveLanes() {
474 : return myActiveLanes;
475 : }
476 :
477 : /// @brief return the number of active objects
478 564997 : int getActiveNumber() {
479 564997 : return myNumActivePedestrians;
480 : }
481 :
482 : void registerActive() {
483 1126 : myNumActivePedestrians++;
484 1126 : }
485 :
486 : private:
487 : static void DEBUG_PRINT(const Obstacles& obs);
488 :
489 : /// @brief returns the direction in which these lanes are connectioned or 0 if they are not
490 : static int connectedDirection(const MSLane* from, const MSLane* to);
491 :
492 : /** @brief computes the successor lane for the given pedestrian and sets the
493 : * link as well as the direction to use on the succesor lane
494 : * @param[in] currentLane The lane the pedestrian is currently on
495 : * @param[in] ped The pedestrian for which to compute the next lane
496 : */
497 : static NextLaneInfo getNextLane(const PState& ped, const MSLane* currentLane, const MSLane* prevLane);
498 :
499 : /// @brief return the next walkingArea in the given direction
500 : static const MSLane* getNextWalkingArea(const MSLane* currentLane, const int dir, const MSLink*& link);
501 :
502 : static void initWalkingAreaPaths(const MSNet* net);
503 :
504 : /// @brief creates and inserts all paths into the given map
505 : static void insertWalkArePaths(const MSEdge* edge, WalkingAreaPaths& into);
506 :
507 : static const WalkingAreaPath* getWalkingAreaPath(const MSEdge* walkingArea, const MSLane* before, const MSLane* after);
508 :
509 : /// @brief return an arbitrary path across the given walkingArea
510 : static const WalkingAreaPath* getArbitraryPath(const MSEdge* walkingArea);
511 :
512 : static const WalkingAreaPath* guessPath(const MSEdge* walkingArea, const MSEdge* before, const MSEdge* after);
513 :
514 : /// @brief return the maximum number of pedestrians walking side by side
515 : static int numStripes(const MSLane* lane);
516 :
517 : static Obstacles getNeighboringObstacles(const Pedestrians& pedestrians, int egoIndex, int stripes);
518 :
519 : const Obstacles& getNextLaneObstacles(NextLanesObstacles& nextLanesObs, const MSLane* lane, const MSLane* nextLane, int stripes,
520 : int nextDir, double currentLength, int currentDir);
521 :
522 : static void transformToCurrentLanePositions(Obstacles& o, int currentDir, int nextDir, double currentLength, double nextLength);
523 :
524 : static void addCloserObstacle(Obstacles& obs, double x, int stripe, int numStripes, const std::string& id, double width, int dir, ObstacleType type);
525 :
526 : /// @brief retrieves the pedestian vector for the given lane (may be empty)
527 : Pedestrians& getPedestrians(const MSLane* lane);
528 :
529 : /* @brief compute stripe-offset to transform relY values from a lane with origStripes into a lane wit destStrips
530 : * @note this is called once for transforming nextLane peds to into the current system as obstacles and another time
531 : * (in reverse) to transform the pedestrian coordinates into the nextLane-coordinates when changing lanes
532 : */
533 : static int getStripeOffset(int origStripes, int destStripes, bool addRemainder);
534 :
535 : ///@brief add vehicles driving across
536 : static bool addCrossingVehs(const MSLane* crossing, int stripes, double lateral_offset, int dir, Obstacles& crossingVehs, bool prio);
537 :
538 : ///@brief retrieve vehicle obstacles on the given lane
539 : static Obstacles getVehicleObstacles(const MSLane* lane, int dir, PState* ped = 0);
540 :
541 : static bool usingInternalLanesStatic();
542 :
543 : static bool addVehicleFoe(const MSVehicle* veh, const MSLane* walkingarea, const Position& relPos, double xWidth, double yWidth, double lateral_offset,
544 : double minY, double maxY, Pedestrians& toDelete, Pedestrians& transformedPeds);
545 :
546 : static int getReserved(int stripes, double factor);
547 :
548 :
549 : private:
550 : /// @brief the total number of active pedestrians
551 : int myNumActivePedestrians;
552 :
553 : /// @brief store of all lanes which have pedestrians on them
554 : ActiveLanes myActiveLanes;
555 :
556 : /// @brief whether an event for pedestrian processing was added
557 : bool myAmActive;
558 :
559 : /// @brief store for walkinArea elements
560 : static WalkingAreaPaths myWalkingAreaPaths;
561 : static std::map<const MSEdge*, std::vector<const MSLane*> > myWalkingAreaFoes;
562 : static MinNextLengths myMinNextLengths;
563 :
564 : /// @brief empty pedestrian vector
565 : static Pedestrians noPedestrians;
566 :
567 : };
|