CARLA
Loading...
Searching...
No Matches
WalkerManager.cpp
Go to the documentation of this file.
1// Copyright (c) 2026 Computer Vision Center (CVC) at the Universitat Autonoma
2// de Barcelona (UAB).
3//
4// This work is licensed under the terms of the MIT license.
5// For a copy, see <https://opensource.org/licenses/MIT>.
6
8
9#include "carla/Logging.h"
12#include "carla/client/World.h"
15
16namespace carla {
17namespace nav {
18
21
24
25 // assign the navigation module
27 _nav = nav;
28 }
29
30 // reference to the simulator to access API functions
31 void WalkerManager::SetSimulator(std::weak_ptr<carla::client::detail::Simulator> simulator) {
32 _simulator = simulator;
33 }
34
35 // create a new walker route
38
39 WalkerInfo info;
40 info.state = WALKER_IDLE;
41
42 // save it
43 _walkers[id] = std::move(info);
44
45 return true;
46 }
47
48 // remove a walker route
50 // search
51 auto it = _walkers.find(id);
52 if (it == _walkers.end())
53 return false;
54 _walkers.erase(it);
55
56 return true;
57 }
58
59 // update all routes
60 bool WalkerManager::Update(double delta) {
61
62 // check all walkers
63 for (auto &it : _walkers) {
64
65 // get the elements
66 WalkerInfo &info = it.second;
67
68 // in function of the state
69 switch (info.state) {
70 case WALKER_IDLE:
71 break;
72
73 case WALKER_WALKING:
74 {
75 // get the target point
76 carla::geom::Location &target = info.route[info.currentIndex].location;
77 // get current position
79 _nav->GetWalkerPosition(it.first, current);
80 // check distance to the target point
81 carla::geom::Vector3D dist(target.x - current.x, target.z - current.z, target.y - current.y);
82 if (dist.SquaredLength() <= 1) {
84 }
85 }
86 break;
87
88 case WALKER_IN_EVENT:
89 switch (ExecuteEvent(it.first, it.second, delta)) {
91 break;
93 // next point in route
94 SetWalkerNextPoint(it.first);
95 break;
97 // unblock changing the route
98 SetWalkerRoute(it.first);
99 break;
100 }
101 break;
102
103 case WALKER_STOP:
104 info.state = WALKER_IDLE;
105 break;
106 }
107 }
108
109 return true;
110 }
111
112 // set a new route from its current position
114 // check
115 if (_nav == nullptr)
116 return false;
117
118 // set a new random target
119 carla::geom::Location location;
120 _nav->GetRandomLocation(location, nullptr);
121
122 // set the route
123 return SetWalkerRoute(id, location);
124 }
125
126 // set a new route from its current position
128 // check
129 if (_nav == nullptr)
130 return false;
131
132 // search
133 auto it = _walkers.find(id);
134 if (it == _walkers.end())
135 return false;
136
137 // get it
138 WalkerInfo &info = it->second;
139 std::vector<carla::geom::Location> path;
140 std::vector<unsigned char> area;
141
142 // save both points for the route
143 _nav->GetWalkerPosition(id, info.from);
144 info.to = to;
145 info.currentIndex = 0;
146 info.state = WALKER_IDLE;
147
148 // get a route from navigation
149 // if pathfinding fails (e.g. no polygon found near 'from'/'to' within
150 // tolerance) 'path'/'area' are left empty; previously this return
151 // value was ignored, so the route below silently ended up empty too.
152 // SetWalkerNextPoint() then found current index >= route size and
153 // paused the agent instead of ever requesting a crowd move target,
154 // with no error surfaced anywhere (info.state stays WALKER_IDLE here
155 // on failure, so callers see a stopped walker rather than a wrong one).
156 if (!_nav->GetAgentRoute(id, info.from, to, path, area)) {
157 return false;
158 }
159
160 // create each point of the route
161 info.route.clear();
162 info.route.reserve(path.size());
163 unsigned char previous_area = CARLA_AREA_SIDEWALK;
164 for (unsigned int i=0; i<path.size(); ++i) {
165 // get the type
166 switch (area[i]) {
167 // do nothing
169 info.route.emplace_back(WalkerEventIgnore(), std::move(path[i]), area[i]);
170 break;
171
172 // stop and check
173 case CARLA_AREA_ROAD:
175 // only if we come from a safe area (sidewalks, grass or crosswalk)
176 if (previous_area != CARLA_AREA_CROSSWALK && previous_area != CARLA_AREA_ROAD)
177 info.route.emplace_back(WalkerEventStopAndCheck(60), std::move(path[i]), area[i]);
178 break;
179
180 default:
181 info.route.emplace_back(WalkerEventIgnore(), std::move(path[i]), area[i]);
182 }
183 previous_area = area[i];
184 }
185
186 // assign the first point to go (second in the list)
188 return true;
189 }
190
191 // set the next point in the route
193 // check
194 if (_nav == nullptr)
195 return false;
196
197 // search
198 auto it = _walkers.find(id);
199 if (it == _walkers.end())
200 return false;
201
202 // get it
203 WalkerInfo &info = it->second;
204
205 // advance next point
206 ++info.currentIndex;
207
208 // check the end
209 if (info.currentIndex < info.route.size()) {
210 // change the state
211 info.state = WALKER_WALKING;
212 // assign the point to go
213 _nav->PauseAgent(id, false);
214 _nav->SetWalkerDirectTarget(id, info.route[info.currentIndex].location);
215 } else {
216 // change the state
217 info.state = WALKER_STOP;
218 _nav->PauseAgent(id, true);
219 // we need a new route from here
220 SetWalkerRoute(id);
221 }
222
223 return true;
224 }
225
226 // get the next point in the route
228 // check
229 if (_nav == nullptr)
230 return false;
231
232 // search
233 auto it = _walkers.find(id);
234 if (it == _walkers.end())
235 return false;
236
237 // get it
238 WalkerInfo &info = it->second;
239
240 // check the end
241 if (info.currentIndex < info.route.size()) {
242 location = info.route[info.currentIndex].location;
243 return true;
244 } else {
245 return false;
246 }
247 }
248
250 // check
251 if (_nav == nullptr)
252 return false;
253
254 // search
255 auto it = _walkers.find(id);
256 if (it == _walkers.end())
257 return false;
258
259 // get it
260 WalkerInfo &info = it->second;
261
262 // check the end of current crosswalk
263 unsigned int pos = info.currentIndex;
264 while (pos < info.route.size()) {
265 if (info.route[pos].areaType != CARLA_AREA_CROSSWALK) {
266 location = info.route[pos].location;
267 return true;
268 }
269 ++pos;
270 }
271
272 return false;
273 }
274
276 // go to the event
277 WalkerRoutePoint &rp = info.route[info.currentIndex];
278
279 // build the visitor structure
280 WalkerEventVisitor visitor(this, id, delta);
281 // run the event
282 return std::visit(visitor, rp.event);
283 }
284
286 static bool AlreadyCalculated = false;
287 if (AlreadyCalculated) return;
288
289 // the world
290 carla::client::World world = _simulator.lock()->GetWorld();
291
292 _traffic_lights.clear();
293 auto actors = world.GetActors();
294 for (auto const &actor : *actors) {
295 // check traffic lights only
296 if (actor->GetTypeId() == "traffic.traffic_light") {
297 // skip anything that reports the traffic-light type but does not
298 // resolve to a TrafficLight actor, otherwise the dereference below
299 // would crash on a null pointer
300 auto tl = std::dynamic_pointer_cast<carla::client::TrafficLight>(actor);
301 if (tl != nullptr) {
302 // get the waypoints where the TL affects
303 std::vector<SharedPtr<carla::client::Waypoint>> list = tl->GetStopWaypoints();
304 for (auto const &way : list) {
305 _traffic_lights.emplace_back(tl, way->GetTransform().location);
306 }
307 }
308 }
309 }
310
311 AlreadyCalculated = true;
312 }
313
314
315 // return the trafficlight affecting that position
317 carla::geom::Location UnrealPos,
318 float max_distance) {
319 float min_dist = std::numeric_limits<float>::infinity();
321 for (auto &&item : _traffic_lights) {
322 float dist = UnrealPos.DistanceSquared(item.second);
323 if (dist < min_dist) {
324 min_dist = dist;
325 actor = item.first;
326 }
327 }
328 // if distance is not in the limit, then reject the trafficlight
329 if (max_distance < 0.0f || min_dist <= max_distance * max_distance) {
330 return actor;
331 } else {
333 }
334 }
335
336
337} // namespace nav
338} // namespace carla
SharedPtr< ActorList > GetActors() const
Return a list with all the actors currently present in the world.
Definition World.cpp:126
Manage the pedestrians navigation, using the Recast & Detour library for low level calculations.
Definition Navigation.h:57
bool GetWalkerPosition(ActorId id, carla::geom::Location &location)
get the walker current location
bool SetWalkerDirectTarget(ActorId id, carla::geom::Location to)
void PauseAgent(ActorId id, bool pause)
set an agent as paused for the crowd
bool GetRandomLocation(carla::geom::Location &location, dtQueryFilter *filter=nullptr) const
get a random location for navigation
bool GetAgentRoute(ActorId id, carla::geom::Location from, carla::geom::Location to, std::vector< carla::geom::Location > &path, std::vector< unsigned char > &area)
bool RemoveWalker(ActorId id)
remove a walker route
std::vector< std::pair< SharedPtr< carla::client::TrafficLight >, carla::geom::Location > > _traffic_lights
bool AddWalker(ActorId id)
create a new walker route
bool GetWalkerCrosswalkEnd(ActorId id, carla::geom::Location &location)
get the point in the route that end current crosswalk
void SetSimulator(std::weak_ptr< carla::client::detail::Simulator > simulator)
reference to the simulator to access API functions
EventResult ExecuteEvent(ActorId id, WalkerInfo &info, double delta)
bool Update(double delta)
update all routes
bool GetWalkerNextPoint(ActorId id, carla::geom::Location &location)
get the next point in the route
bool SetWalkerNextPoint(ActorId id)
set the next point in the route
std::weak_ptr< carla::client::detail::Simulator > _simulator
std::unordered_map< ActorId, WalkerInfo > _walkers
SharedPtr< carla::client::TrafficLight > GetTrafficLightAffecting(carla::geom::Location UnrealPos, float max_distance=-1.0f)
return the trafficlight affecting that position
void SetNav(Navigation *nav)
assign the navigation module
bool SetWalkerRoute(ActorId id)
set a new route from its current position
@ CARLA_AREA_CROSSWALK
Definition Navigation.h:29
@ CARLA_AREA_SIDEWALK
Definition Navigation.h:28
@ CARLA_AREA_ROAD
Definition Navigation.h:30
EventResult
result of an event
Definition WalkerEvent.h:28
This file contains definitions of common data structures used in traffic manager.
std::shared_ptr< T > SharedPtr
Definition Memory.h:15
rpc::ActorId ActorId
Definition ActorId.h:18
constexpr auto DistanceSquared(Location loc) const
constexpr float SquaredLength() const
empty event that just ignores
Definition WalkerEvent.h:35
event to pause and check for near vehicles
Definition WalkerEvent.h:45
unsigned int currentIndex
std::vector< WalkerRoutePoint > route
carla::geom::Location from
carla::geom::Location to