VIPRA Documentation
Loading...
Searching...
No Matches
pedestrians.hpp
1#pragma once
2
3#include <functional>
4#include <random>
5#include <vector>
6
7#include "vipra/geometry/circle.hpp"
8#include "vipra/logging/logging.hpp"
9
10#include "vipra/macros/errors.hpp"
11#include "vipra/macros/module.hpp"
12#include "vipra/modules/map.hpp"
13
14#include "vipra/geometry/f3d.hpp"
15
16#include "vipra/modules/module.hpp"
17#include "vipra/modules/pedestrian_input.hpp"
18
19#include "vipra/random/random.hpp"
20
21#include "vipra/types/float.hpp"
22#include "vipra/types/idx.hpp"
23#include "vipra/types/size.hpp"
24#include "vipra/types/state.hpp"
25
26#include "vipra/macros/parameters.hpp"
27#include "vipra/macros/pedestrians.hpp"
28
29namespace VIPRA::Modules {
30
35class Pedestrians : public BaseModule<Pedestrians> {
36 public:
37 virtual VIPRA_PEDS_INIT_STEP = 0;
38 virtual VIPRA_PEDS_UPDATE_STEP = 0;
39 virtual VIPRA_PEDS_RESET = 0;
40
41 [[nodiscard]] virtual auto all_neighbors_within(
42 VIPRA::idx pedIdx, VIPRA::f_pnt radius) const -> std::vector<VIPRA::idx> = 0;
43
44 [[nodiscard]] virtual auto closest_ped(VIPRA::idx pedIdx) const -> VIPRA::idx = 0;
45
46 [[nodiscard]] virtual auto conditional_closest_ped(
47 VIPRA::idx pedIdx,
48 std::function<bool(VIPRA::idx)> const& condition) const -> VIPRA::idx = 0;
49
50 VIPRA_MODULE_TYPE(Pedestrians);
51
52 VIPRA_REGISTER_BASE_PARAMS(VIPRA_PARAM("random_count", _randomPedCnt),
53 VIPRA_PARAM("spawn_random", _randomSpawn),
54 VIPRA_PARAM("use_file", _useFile))
55
56 void initialize(VIPRA::Modules::PedestrianInput& input, VIPRA::Modules::Map const& map,
58 {
59 VIPRA::Log::debug("Initializing Pedestrians");
60 if ( ! (_randomSpawn || _useFile) )
61 VIPRA_BASE_MODULE_ERROR(
62 "Pedestrians",
63 "Random spawning AND Using the pedestrian file input is turned off "
64 "in parameters (Cannot Add any "
65 "Pedestrians, "
66 "one needs to be true)");
67
68 init_specific_peds(input);
69
70 if ( _randomSpawn && _randomPedCnt > 0 ) {
71 init_random_peds(map, engine);
72 }
73
74 if ( _coords.size() == 0 )
75 VIPRA_BASE_MODULE_ERROR("Pedestrians", "No Pedestrians added to simulation");
76
77 assert(_coords.size() > 0);
78 assert(_coords.size() == _velocities.size());
79
80 init_step(map, engine);
81 VIPRA::Log::debug("Pedestrians Initialized");
82 }
83
84 void reset_module()
85 {
86 _coords.clear();
87 _velocities.clear();
88 }
89
90 void update(VIPRA::State const& state)
91 {
92 update_step(state);
93
94 for ( VIPRA::idx pedIdx = 0; pedIdx < state.size(); ++pedIdx ) {
95 _coords[pedIdx] = state.positions[pedIdx];
96 _velocities[pedIdx] = state.velocities[pedIdx];
97 }
98 }
99
100 [[nodiscard]] auto distance(VIPRA::idx firstPed,
101 VIPRA::idx secondPed) const -> VIPRA::f_pnt
102 {
103 return _coords[firstPed].distance_to(_coords[secondPed]);
104 }
105
106 [[nodiscard]] auto num_pedestrians() const -> VIPRA::size { return _coords.size(); }
107
108 [[nodiscard]] auto ped_coords(VIPRA::idx pedIdx) const -> VIPRA::f3d const&
109 {
110 assert(pedIdx < _coords.size());
111
112 return _coords[pedIdx];
113 }
114
115 [[nodiscard]] auto all_coords() const -> std::vector<VIPRA::f3d> const&
116 {
117 return _coords;
118 }
119
120 [[nodiscard]] auto ped_velocity(VIPRA::idx pedIdx) const -> VIPRA::f3d const&
121 {
122 assert(pedIdx < _velocities.size());
123 return _velocities[pedIdx];
124 }
125
126 [[nodiscard]] auto all_velocities() const -> std::vector<VIPRA::f3d> const&
127 {
128 return _velocities;
129 }
130
131 private:
132 VIPRA::f3dVec _coords;
133 VIPRA::f3dVec _velocities;
134
135 size_t _randomPedCnt{0};
136 bool _randomSpawn{false};
137 bool _useFile{true};
138
139 protected:
140 void set_velocities(VIPRA::f3dVec const& velocities) { _velocities = velocities; }
141 void set_velocities(VIPRA::f3dVec&& velocities) noexcept { _velocities = velocities; }
142
143 void set_coordinates(VIPRA::f3dVec const& coordinates) { _coords = coordinates; }
144 void set_coordinates(VIPRA::f3dVec&& coordinates) noexcept { _coords = coordinates; }
145
146 [[nodiscard]] auto get_velocities() const -> VIPRA::f3dVec const&
147 {
148 return _velocities;
149 }
150 [[nodiscard]] auto get_coordinates() const -> VIPRA::f3dVec const& { return _coords; }
151
152 void init_random_peds(VIPRA::Modules::Map const& map, VIPRA::Random::Engine& engine)
153 {
154 // TODO(rolland): issue #45 handle spawn points
155 assert(_coords.size() == _velocities.size());
156
157 auto const& spawnAreas = map.get_spawns();
158 if ( spawnAreas.size() == 0 ) {
160 "{} Pedestrians were set to spawn randomly, but no spawn areas were "
161 "provided in the map",
162 _randomPedCnt);
163 return;
164 }
165
166 size_t startSize = _coords.size();
167 _coords.resize(_coords.size() + _randomPedCnt);
168 _velocities.resize(_velocities.size() + _randomPedCnt);
169
170 std::uniform_int_distribution<size_t> polyDist{0, spawnAreas.size() - 1};
171
172 // go through each pedestrian and give them a random point inside one of the spawn points
173 for ( size_t i = startSize; i < _coords.size(); ++i ) {
174 VIPRA::idx spawnIdx = polyDist(engine);
175
176 _coords[i] = find_random_point(spawnAreas[spawnIdx], map, engine);
177 }
178
179 VIPRA::Log::debug("{} pedestrians added randomly to {} spawn areas", _randomPedCnt,
180 spawnAreas.size());
181 }
182
183 void init_specific_peds(VIPRA::Modules::PedestrianInput& input)
184 {
185 if ( ! _useFile ) return;
186
187 auto coords = input.get_pedestrians();
188 if ( ! (coords || _randomSpawn) )
189 VIPRA_BASE_MODULE_ERROR(
190 "Pedestrians",
191 "Could not find pedestrian coordinates in input file and random "
192 "spawning is turned off (No "
193 "Pedestrians Added)");
194
195 if ( ! coords )
197 "Pedestrians were set to be loaded from a file, but no coordinates "
198 "could be loaded");
199
200 VIPRA::Log::debug("{} pedestrians added at {} specific spots", (*coords).size(),
201 (*coords).size());
202 set_coordinates(std::move(*coords));
203 set_velocities(std::vector<VIPRA::f3d>(_coords.size()));
204 }
205
206 static auto find_random_point(VIPRA::Geometry::Polygon const& polygon,
207 VIPRA::Modules::Map const& map,
208 VIPRA::Random::Engine& engine) -> f3d
209 {
210 constexpr size_t MAX_RETRIES = 100;
211 constexpr VIPRA::f_pnt CLOSEST_DIST = 0.3;
212 size_t retries = 0;
213
214 f3d point = polygon.random_point(engine);
215 while ( map.collision(Geometry::Circle{point, CLOSEST_DIST}) ) {
216 point = polygon.random_point(engine);
217 ++retries;
218 if ( retries > MAX_RETRIES ) {
219 VIPRA_BASE_MODULE_ERROR(
220 "Pedestrians",
221 "Unable to obtain a point in the spawn area centered at ({}, {}). "
222 "Make sure all spawn areas are outside of obstacles.",
223 polygon.center().x, polygon.center().y);
224 }
225 }
226
227 return point;
228 }
229
230 public:
231 virtual ~Pedestrians() = default;
232 Pedestrians() = default;
233 Pedestrians(Pedestrians const&) = default;
234 Pedestrians(Pedestrians&&) noexcept = default;
235 auto operator=(Pedestrians const&) -> Pedestrians& = default;
236 auto operator=(Pedestrians&&) noexcept -> Pedestrians& = default;
237};
238} // namespace VIPRA::Modules
Definition circle.hpp:9
Definition polygon.hpp:18
static VIPRA_INLINE void warn(fmt::format_string< param_ts... > message, param_ts &&... params)
Calls the provided Logger with Level WARN.
Definition logging.hpp:51
static VIPRA_INLINE void debug(fmt::format_string< param_ts... > message, param_ts &&... params)
Calls the provided Logger with Level DEBUG.
Definition logging.hpp:85
VIPRA Module Base CRTP Class.
Definition module.hpp:21
Base Map Module Class.
Definition map.hpp:23
Base PedestrianInput Module.
Definition pedestrian_input.hpp:13
Psuedo Random number engine.
Definition random.hpp:22
Struct that holds the updated positions and velocities of all pedestrians.
Definition state.hpp:12
Definition f3d.hpp:27