7#define _USE_MATH_DEFINES
48 return static_cast<float>(rand()) /
static_cast<float>(RAND_MAX);
85 std::istream_iterator<uint8_t> start(f), end;
88 f.open(filename, std::ios::binary);
92 std::vector<uint8_t> content(start, end);
96 return Load(std::move(content));
101 const int NAVMESHSET_MAGIC =
'M' << 24 |
'S' << 16 |
'E' << 8 |
'T';
102 const int NAVMESHSET_VERSION = 1;
105 struct NavMeshSetHeader {
109 dtNavMeshParams params;
111 struct NavMeshTileHeader {
118 if (content.size() <
sizeof(header)) {
124 unsigned long pos = 0;
125 memcpy(&header, &content[pos],
sizeof(header));
126 pos +=
sizeof(header);
129 if (header.magic != NAVMESHSET_MAGIC || header.version != NAVMESHSET_VERSION) {
134 dtNavMesh *mesh = dtAllocNavMesh();
140 dtStatus status = mesh->init(&header.params);
141 if (dtStatusFailed(status)) {
146 for (
int i = 0; i < header.num_tiles; ++i) {
147 NavMeshTileHeader tile_header;
150 memcpy(&tile_header, &content[pos],
sizeof(tile_header));
151 pos +=
sizeof(tile_header);
152 if (pos >= content.size()) {
158 if (!tile_header.tile_ref || !tile_header.data_size) {
163 char *data =
static_cast<char *
>(dtAlloc(
static_cast<size_t>(tile_header.data_size), DT_ALLOC_PERM));
169 memcpy(data, &content[pos],
static_cast<size_t>(tile_header.data_size));
170 pos +=
static_cast<unsigned long>(tile_header.data_size);
171 if (pos > content.size()) {
178 mesh->addTile(
reinterpret_cast<unsigned char *
>(data), tile_header.data_size, DT_TILE_FREE_DATA,
179 tile_header.tile_ref, 0);
232 dtObstacleAvoidanceParams params;
234 memcpy(¶ms,
_crowd->getObstacleAvoidanceParams(0),
sizeof(dtObstacleAvoidanceParams));
237 params.velBias = 0.5f;
238 params.adaptiveDivs = 5;
239 params.adaptiveRings = 2;
240 params.adaptiveDepth = 1;
241 _crowd->setObstacleAvoidanceParams(0, ¶ms);
244 params.velBias = 0.5f;
245 params.adaptiveDivs = 5;
246 params.adaptiveRings = 2;
247 params.adaptiveDepth = 2;
248 _crowd->setObstacleAvoidanceParams(1, ¶ms);
251 params.velBias = 0.5f;
252 params.adaptiveDivs = 7;
253 params.adaptiveRings = 2;
254 params.adaptiveDepth = 3;
255 _crowd->setObstacleAvoidanceParams(2, ¶ms);
258 params.velBias = 0.5f;
259 params.adaptiveDivs = 7;
260 params.adaptiveRings = 3;
261 params.adaptiveDepth = 3;
263 _crowd->setObstacleAvoidanceParams(3, ¶ms);
269 dtQueryFilter * filter,
270 std::vector<carla::geom::Location> &path,
271 std::vector<unsigned char> &area) {
274 unsigned char straight_path_flags[
MAX_POLYS];
275 dtPolyRef straight_path_polys[
MAX_POLYS];
276 int num_straight_path;
277 int straight_path_options = DT_STRAIGHTPATH_AREA_CROSSINGS;
291 float poly_pick_ext[3];
292 poly_pick_ext[0] = 2;
293 poly_pick_ext[1] = 4;
294 poly_pick_ext[2] = 2;
297 dtQueryFilter filter2;
298 if (filter ==
nullptr) {
307 dtPolyRef start_ref = 0;
308 dtPolyRef end_ref = 0;
309 float start_pos[3] = { from.
x, from.
z, from.
y };
310 float end_pos[3] = { to.
x, to.
z, to.
y };
313 std::lock_guard<std::mutex> lock(
_mutex);
314 _nav_query->findNearestPoly(start_pos, poly_pick_ext, filter, &start_ref, 0);
315 _nav_query->findNearestPoly(end_pos, poly_pick_ext, filter, &end_ref, 0);
317 if (!start_ref || !end_ref) {
323 std::lock_guard<std::mutex> lock(
_mutex);
325 _nav_query->findPath(start_ref, end_ref, start_pos, end_pos, filter, polys, &num_polys,
MAX_POLYS);
329 num_straight_path = 0;
330 if (num_polys == 0) {
337 dtVcopy(end_pos2, end_pos);
338 if (polys[num_polys - 1] != end_ref) {
340 std::lock_guard<std::mutex> lock(
_mutex);
341 _nav_query->closestPointOnPoly(polys[num_polys - 1], end_pos, end_pos2, 0);
347 std::lock_guard<std::mutex> lock(
_mutex);
348 _nav_query->findStraightPath(start_pos, end_pos2, polys, num_polys,
349 straight_path, straight_path_flags,
350 straight_path_polys, &num_straight_path,
MAX_POLYS, straight_path_options);
355 path.reserve(
static_cast<unsigned long>(num_straight_path));
356 unsigned char area_type;
357 for (
int i = 0, j = 0; j < num_straight_path; i += 3, ++j) {
359 path.emplace_back(straight_path[i], straight_path[i + 2], straight_path[i + 1]);
363 std::lock_guard<std::mutex> lock(
_mutex);
364 _nav_mesh->getPolyArea(straight_path_polys[j], &area_type);
366 area.emplace_back(area_type);
373 std::vector<carla::geom::Location> &path, std::vector<unsigned char> &area) {
376 unsigned char straight_path_flags[
MAX_POLYS];
377 dtPolyRef straight_path_polys[
MAX_POLYS];
378 int num_straight_path = 0;
379 int straight_path_options = DT_STRAIGHTPATH_AREA_CROSSINGS;
393 float poly_pick_ext[3] = {2,4,2};
400 const dtQueryFilter *filter;
403 std::lock_guard<std::mutex> lock(
_mutex);
404 filter =
_crowd->getFilter(
_crowd->getAgent(it->second)->params.queryFilterType);
408 dtPolyRef start_ref = 0;
409 dtPolyRef end_ref = 0;
410 float start_pos[3] = { from.
x, from.
z, from.
y };
411 float end_pos[3] = { to.
x, to.
z, to.
y };
414 std::lock_guard<std::mutex> lock(
_mutex);
415 _nav_query->findNearestPoly(start_pos, poly_pick_ext, filter, &start_ref, 0);
416 _nav_query->findNearestPoly(end_pos, poly_pick_ext, filter, &end_ref, 0);
418 if (!start_ref || !end_ref) {
425 std::lock_guard<std::mutex> lock(
_mutex);
426 _nav_query->findPath(start_ref, end_ref, start_pos, end_pos, filter, polys, &num_polys,
MAX_POLYS);
430 if (num_polys == 0) {
437 dtVcopy(end_pos2, end_pos);
438 if (polys[num_polys - 1] != end_ref) {
440 std::lock_guard<std::mutex> lock(
_mutex);
441 _nav_query->closestPointOnPoly(polys[num_polys - 1], end_pos, end_pos2, 0);
447 std::lock_guard<std::mutex> lock(
_mutex);
448 _nav_query->findStraightPath(start_pos, end_pos2, polys, num_polys,
449 straight_path, straight_path_flags,
450 straight_path_polys, &num_straight_path,
MAX_POLYS, straight_path_options);
455 path.reserve(
static_cast<unsigned long>(num_straight_path));
456 unsigned char area_type;
457 for (
int i = 0, j = 0; j < num_straight_path; i += 3, ++j) {
459 path.emplace_back(straight_path[i], straight_path[i + 2], straight_path[i + 1]);
463 std::lock_guard<std::mutex> lock(
_mutex);
464 _nav_mesh->getPolyArea(straight_path_polys[j], &area_type);
466 area.emplace_back(area_type);
474 dtCrowdAgentParams params;
484 memset(¶ms, 0,
sizeof(params));
487 params.maxAcceleration = 160.0f;
488 params.maxSpeed = 1.47f;
489 params.collisionQueryRange = 10;
490 params.obstacleAvoidanceType = 3;
491 params.separationWeight = 0.5f;
495 params.queryFilterType = 1;
497 params.queryFilterType = 0;
501 params.updateFlags = 0;
508 float point_from[3] = { from.
x, from.
z - (
AGENT_HEIGHT / 2.0f), from.
y };
513 std::lock_guard<std::mutex> lock(
_mutex);
514 index =
_crowd->addAgent(point_from, ¶ms);
536 dtCrowdAgentParams params;
556 box_corner1 = cg::Math::RotatePointOnOrigin2D(box_corner1, angle);
557 box_corner2 = cg::Math::RotatePointOnOrigin2D(box_corner2, angle);
558 box_corner3 = cg::Math::RotatePointOnOrigin2D(box_corner3, angle);
559 box_corner4 = cg::Math::RotatePointOnOrigin2D(box_corner4, angle);
570 int index = it->second;
576 std::lock_guard<std::mutex> lock(
_mutex);
577 agent =
_crowd->getEditableAgent(index);
585 agent->params.obb[0] = box_corner1.x;
586 agent->params.obb[1] = box_corner1.z;
587 agent->params.obb[2] = box_corner1.y;
588 agent->params.obb[3] = box_corner2.x;
589 agent->params.obb[4] = box_corner2.z;
590 agent->params.obb[5] = box_corner2.y;
591 agent->params.obb[6] = box_corner3.x;
592 agent->params.obb[7] = box_corner3.z;
593 agent->params.obb[8] = box_corner3.y;
594 agent->params.obb[9] = box_corner4.x;
595 agent->params.obb[10] = box_corner4.z;
596 agent->params.obb[11] = box_corner4.y;
603 memset(¶ms, 0,
sizeof(params));
606 params.maxAcceleration = 0.0f;
607 params.maxSpeed = 1.47f;
608 params.collisionQueryRange = 0;
609 params.obstacleAvoidanceType = 0;
610 params.separationWeight = 100.0f;
613 params.updateFlags = 0;
618 params.useObb =
true;
619 params.obb[0] = box_corner1.x;
620 params.obb[1] = box_corner1.z;
621 params.obb[2] = box_corner1.y;
622 params.obb[3] = box_corner2.x;
623 params.obb[4] = box_corner2.z;
624 params.obb[5] = box_corner2.y;
625 params.obb[6] = box_corner3.x;
626 params.obb[7] = box_corner3.z;
627 params.obb[8] = box_corner3.y;
628 params.obb[9] = box_corner4.x;
629 params.obb[10] = box_corner4.z;
630 params.obb[11] = box_corner4.y;
641 std::lock_guard<std::mutex> lock(
_mutex);
642 index =
_crowd->addAgent(point_from, ¶ms);
644 logging::log(
"Vehicle agent not added to the crowd by some problem!");
649 dtCrowdAgent *agent =
_crowd->getEditableAgent(index);
651 agent->state = DT_CROWDAGENT_STATE_WALKING;
678 std::lock_guard<std::mutex> lock(
_mutex);
679 _crowd->removeAgent(it->second);
695 std::lock_guard<std::mutex> lock(
_mutex);
696 _crowd->removeAgent(it->second);
710 std::unordered_set<carla::rpc::ActorId> updated;
714 updated.insert(entry.first);
718 for (
auto &&entry : vehicles) {
722 updated.erase(entry.id);
726 for (
auto &&entry : updated) {
753 std::lock_guard<std::mutex> lock(
_mutex);
754 dtCrowdAgent *agent =
_crowd->getEditableAgent(it->second);
756 agent->params.maxSpeed = max_speed;
814 float point_to[3] = { to.
x, to.
z, to.
y };
819 std::lock_guard<std::mutex> lock(
_mutex);
820 const dtQueryFilter *filter =
_crowd->getFilter(0);
821 dtPolyRef target_ref;
822 _nav_query->findNearestPoly(point_to,
_crowd->getQueryHalfExtents(), filter, &target_ref, nearest);
827 res =
_crowd->requestMoveTarget(index, target_ref, point_to);
847 std::lock_guard<std::mutex> lock(
_mutex);
858 int total_unblocked = 0;
862 std::lock_guard<std::mutex> lock(
_mutex);
863 total_agents =
_crowd->getAgentCount();
865 const dtCrowdAgent *ag;
866 for (
int i = 0; i < total_agents; ++i) {
869 std::lock_guard<std::mutex> lock(
_mutex);
873 if (!ag->active || ag->paused || ag->dead) {
878 if (!ag->params.useObb && !ag->paused) {
879 bool reset_target_pos =
false;
880 bool use_same_filter =
false;
891 reset_target_pos =
true;
892 use_same_filter =
true;
898 if (reset_target_pos) {
900 if (!use_same_filter) {
939 int index = it->second;
945 const dtCrowdAgent *agent;
948 std::lock_guard<std::mutex> lock(
_mutex);
949 agent =
_crowd->getAgent(index);
952 if (!agent->active) {
965 if (agent->vel[0] < -
min || agent->vel[0] >
min ||
966 agent->vel[2] < -
min || agent->vel[2] >
min) {
967 yaw = atan2f(agent->vel[2], agent->vel[0]) * (180.0f /
static_cast<float>(M_PI));
968 speed = sqrtf(agent->vel[0] * agent->vel[0] + agent->vel[1] * agent->vel[1] + agent->vel[2] * agent->vel[2]);
970 yaw = atan2f(agent->dvel[2], agent->dvel[0]) * (180.0f /
static_cast<float>(M_PI));
971 speed = sqrtf(agent->dvel[0] * agent->dvel[0] + agent->dvel[1] * agent->dvel[1] + agent->dvel[2] * agent->dvel[2]);
975 float shortest_angle = fmod(yaw -
_yaw_walkers[
id] + 540.0f, 360.0f) - 180.0f;
976 float per = (speed / 1.5f);
977 if (per > 1.0f) per = 1.0f;
978 float rotation_speed = per * 6.0f;
980 (shortest_angle * rotation_speed *
static_cast<float>(
_delta_seconds));
1003 int index = it->second;
1009 const dtCrowdAgent *agent;
1012 std::lock_guard<std::mutex> lock(
_mutex);
1013 agent =
_crowd->getAgent(index);
1016 if (!agent->active) {
1021 location.
x = agent->npos[0];
1022 location.
y = agent->npos[2];
1023 location.
z = agent->npos[1];
1044 int index = it->second;
1050 const dtCrowdAgent *agent;
1053 std::lock_guard<std::mutex> lock(
_mutex);
1054 agent =
_crowd->getAgent(index);
1057 return sqrt(agent->vel[0] * agent->vel[0] + agent->vel[1] * agent->vel[1] + agent->vel[2] *
1072 dtQueryFilter filter2;
1073 if (filter ==
nullptr) {
1080 dtPolyRef random_ref { 0 };
1081 float point[3] { 0.0f, 0.0f, 0.0f };
1086 std::lock_guard<std::mutex> lock(
_mutex);
1088 status =
_nav_query->findRandomPoint(filter,
frand, &random_ref, point);
1090 if (status == DT_SUCCESS) {
1091 location.
x = point[0];
1092 location.
y = point[2];
1093 location.
z = point[1];
1096 }
while (status != DT_SUCCESS && rounds > 0);
1099 return (rounds > 0);
1106 dtCrowdAgent *agent;
1109 std::lock_guard<std::mutex> lock(
_mutex);
1110 agent =
_crowd->getEditableAgent(agent_index);
1112 agent->params.queryFilterType =
static_cast<unsigned char>(filter_index);
1140 int index = it->second;
1146 dtCrowdAgent *agent;
1149 std::lock_guard<std::mutex> lock(
_mutex);
1150 agent =
_crowd->getEditableAgent(index);
1154 agent->paused = pause;
1167 float dir[3] = { direction.
x, direction.
z, direction.
y };
1171 std::lock_guard<std::mutex> lock(
_mutex);
1172 result =
_crowd->hasVehicleNear(it->second, distance * distance, dir,
false);
1188 dtCrowdAgent *agent;
1191 std::lock_guard<std::mutex> lock(
_mutex);
1192 agent =
_crowd->getEditableAgent(it->second);
1196 float x = (location.
x - agent->npos[0]) * 0.0001f;
1197 float y = (location.
y - agent->npos[2]) * 0.0001f;
1198 float z = (location.
z - agent->npos[1]) * 0.0001f;
1229 int index = it->second;
1235 const dtCrowdAgent *agent;
1238 std::lock_guard<std::mutex> lock(
_mutex);
1239 agent =
_crowd->getAgent(index);
1243 alive = !agent->dead;
#define DEBUG_ASSERT(predicate)
double min(double v1, double v2)
Represents the state of all the actors of an episode at a given frame.
const auto & GetTimestamp() const
Vector3D extent
Half the size of the BoundingBox in local space
float SquaredLength() const
bool SetWalkerMaxSpeed(ActorId id, float max_speed)
set new max speed
void UpdateCrowd(const client::detail::EpisodeState &state)
update all walkers in crowd
bool GetPath(carla::geom::Location from, carla::geom::Location to, dtQueryFilter *filter, std::vector< carla::geom::Location > &path, std::vector< unsigned char > &area)
return the path points to go from one position to another
void SetAgentFilter(int agent_index, int filter_index)
assign a filter index to an agent
std::unordered_map< ActorId, int > _mapped_vehicles_id
std::unordered_map< ActorId, int > _mapped_walkers_id
mapping Id
bool RemoveAgent(ActorId id)
remove an agent
std::weak_ptr< carla::client::detail::Simulator > _simulator
bool GetWalkerPosition(ActorId id, carla::geom::Location &location)
get the walker current location
float GetWalkerSpeed(ActorId id)
get the walker current transform
bool Load(const std::string &filename)
load navigation data
bool SetWalkerTarget(ActorId id, carla::geom::Location to)
set a new target point to go through a route with events
void SetSeed(unsigned int seed)
set the seed to use with random numbers
dtNavMesh * _nav_mesh
meshes
bool UpdateVehicles(std::vector< VehicleCollisionInfo > vehicles)
add/update/delete vehicles in crowd
std::unordered_map< int, ActorId > _mapped_by_index
bool SetWalkerDirectTarget(ActorId id, carla::geom::Location to)
bool SetWalkerLookAt(ActorId id, carla::geom::Location location)
make agent look at some location
void PauseAgent(ActorId id, bool pause)
set an agent as paused for the crowd
bool HasVehicleNear(ActorId id, float distance, carla::geom::Location direction)
return if the agent has a vehicle near (as neighbour)
bool GetWalkerTransform(ActorId id, carla::geom::Transform &trans)
get the walker current transform
bool GetRandomLocation(carla::geom::Location &location, dtQueryFilter *filter=nullptr) const
get a random location for navigation
bool IsWalkerAlive(ActorId id, bool &alive)
return if the agent has been killed by a vehicle
WalkerManager _walker_manager
walker manager for the route planning with events
bool GetAgentRoute(ActorId id, carla::geom::Location from, carla::geom::Location to, std::vector< carla::geom::Location > &path, std::vector< unsigned char > &area)
void SetPedestriansCrossFactor(float percentage)
set the probability that an agent could cross the roads in its path following
std::unordered_map< ActorId, float > _yaw_walkers
store walkers yaw angle from previous tick
bool AddWalker(ActorId id, carla::geom::Location from)
create a new walker
std::vector< uint8_t > _binary_mesh
bool SetWalkerDirectTargetIndex(int index, carla::geom::Location to)
void SetSimulator(std::weak_ptr< carla::client::detail::Simulator > simulator)
reference to the simulator to access API functions
dtNavMeshQuery * _nav_query
void CreateCrowd(void)
create the crowd object
bool AddOrUpdateVehicle(VehicleCollisionInfo &vehicle)
create a new vehicle in crowd to be avoided by walkers
float _probability_crossing
std::unordered_map< int, carla::geom::Vector3D > _walkers_blocked_position
saves the position of each actor at intervals and check if any is blocked
bool RemoveWalker(ActorId id)
remove a walker route
bool AddWalker(ActorId id)
create a new walker route
void SetSimulator(std::weak_ptr< carla::client::detail::Simulator > simulator)
reference to the simulator to access API functions
bool Update(double delta)
update all routes
void SetNav(Navigation *nav)
assign the navigation module
bool SetWalkerRoute(ActorId id)
set a new route from its current position
static void log(Args &&... args)
@ DT_CROWD_OBSTACLE_AVOIDANCE
@ DT_CROWD_ANTICIPATE_TURNS
static const float AREA_ROAD_COST
static const float AGENT_UNBLOCK_TIME
static const float AGENT_RADIUS
static const float AGENT_HEIGHT
static const float AGENT_UNBLOCK_DISTANCE_SQUARED
static const int MAX_AGENTS
static const int MAX_POLYS
static const int MAX_QUERY_SEARCH_NODES
static const float AGENT_UNBLOCK_DISTANCE
static const float AREA_GRASS_COST
This file contains definitions of common data structures used in traffic manager.
struct to send info about vehicles to the crowd
carla::geom::BoundingBox bounding
carla::geom::Transform transform