7#define _USE_MATH_DEFINES
47 return static_cast<float>(rand()) /
static_cast<float>(RAND_MAX);
88 std::istream_iterator<uint8_t> start(f),
end;
92 f.open(filename, std::ios::binary);
97 std::vector<uint8_t> content(start,
end);
101 return Load(std::move(content));
107 const int NAVMESHSET_MAGIC =
'M' << 24 |
'S' << 16 |
'E' << 8 |
'T';
108 const int NAVMESHSET_VERSION = 1;
113 struct NavMeshSetHeader {
117 dtNavMeshParams params;
120 struct NavMeshTileHeader {
129 if (content.size() <
sizeof(header)) {
135 unsigned long pos = 0;
136 memcpy(&header, &content[pos],
sizeof(header));
137 pos +=
sizeof(header);
140 if (header.magic != NAVMESHSET_MAGIC || header.version != NAVMESHSET_VERSION) {
146 dtNavMesh *mesh = dtAllocNavMesh();
154 dtStatus status = mesh->init(&header.params);
155 if (dtStatusFailed(status)) {
160 for (
int i = 0; i < header.num_tiles; ++i) {
161 NavMeshTileHeader tile_header;
164 memcpy(&tile_header, &content[pos],
sizeof(tile_header));
165 pos +=
sizeof(tile_header);
166 if (pos >= content.size()) {
173 if (!tile_header.tile_ref || !tile_header.data_size) {
179 char *data =
static_cast<char *
>(dtAlloc(
static_cast<size_t>(tile_header.data_size), DT_ALLOC_PERM));
186 memcpy(data, &content[pos],
static_cast<size_t>(tile_header.data_size));
187 pos +=
static_cast<unsigned long>(tile_header.data_size);
188 if (pos > content.size()) {
196 mesh->addTile(
reinterpret_cast<unsigned char *
>(data), tile_header.data_size, DT_TILE_FREE_DATA,
197 tile_header.tile_ref, 0);
252 dtObstacleAvoidanceParams params;
254 memcpy(¶ms,
_crowd->getObstacleAvoidanceParams(0),
sizeof(dtObstacleAvoidanceParams));
257 params.velBias = 0.5f;
258 params.adaptiveDivs = 5;
259 params.adaptiveRings = 2;
260 params.adaptiveDepth = 1;
261 _crowd->setObstacleAvoidanceParams(0, ¶ms);
264 params.velBias = 0.5f;
265 params.adaptiveDivs = 5;
266 params.adaptiveRings = 2;
267 params.adaptiveDepth = 2;
268 _crowd->setObstacleAvoidanceParams(1, ¶ms);
271 params.velBias = 0.5f;
272 params.adaptiveDivs = 7;
273 params.adaptiveRings = 2;
274 params.adaptiveDepth = 3;
275 _crowd->setObstacleAvoidanceParams(2, ¶ms);
278 params.velBias = 0.5f;
279 params.adaptiveDivs = 7;
280 params.adaptiveRings = 3;
281 params.adaptiveDepth = 3;
283 _crowd->setObstacleAvoidanceParams(3, ¶ms);
289 dtQueryFilter * filter,
290 std::vector<carla::geom::Location> &path,
291 std::vector<unsigned char> &area) {
294 unsigned char straight_path_flags[
MAX_POLYS];
295 dtPolyRef straight_path_polys[
MAX_POLYS];
296 int num_straight_path;
297 int straight_path_options = DT_STRAIGHTPATH_AREA_CROSSINGS;
312 float poly_pick_ext[3];
313 poly_pick_ext[0] = 2;
314 poly_pick_ext[1] = 4;
315 poly_pick_ext[2] = 2;
318 dtQueryFilter filter2;
319 if (filter ==
nullptr) {
328 dtPolyRef start_ref = 0;
329 dtPolyRef end_ref = 0;
330 float start_pos[3] = { from.
x, from.
z, from.
y };
331 float end_pos[3] = { to.
x, to.
z, to.
y };
334 std::lock_guard<std::mutex> lock(
_mutex);
335 _nav_query->findNearestPoly(start_pos, poly_pick_ext, filter, &start_ref, 0);
336 _nav_query->findNearestPoly(end_pos, poly_pick_ext, filter, &end_ref, 0);
339 if (!start_ref || !end_ref) {
345 std::lock_guard<std::mutex> lock(
_mutex);
347 _nav_query->findPath(start_ref, end_ref, start_pos, end_pos, filter, polys, &num_polys,
MAX_POLYS);
351 num_straight_path = 0;
352 if (num_polys == 0) {
358 dtVcopy(end_pos2, end_pos);
359 if (polys[num_polys - 1] != end_ref) {
361 std::lock_guard<std::mutex> lock(
_mutex);
362 _nav_query->closestPointOnPoly(polys[num_polys - 1], end_pos, end_pos2, 0);
368 std::lock_guard<std::mutex> lock(
_mutex);
369 _nav_query->findStraightPath(start_pos, end_pos2, polys, num_polys,
370 straight_path, straight_path_flags,
371 straight_path_polys, &num_straight_path,
MAX_POLYS, straight_path_options);
376 path.reserve(
static_cast<unsigned long>(num_straight_path));
377 unsigned char area_type;
378 for (
int i = 0, j = 0; j < num_straight_path; i += 3, ++j) {
380 path.emplace_back(straight_path[i], straight_path[i + 2], straight_path[i + 1]);
384 std::lock_guard<std::mutex> lock(
_mutex);
385 _nav_mesh->getPolyArea(straight_path_polys[j], &area_type);
387 area.emplace_back(area_type);
394 std::vector<carla::geom::Location> &path, std::vector<unsigned char> &area) {
397 unsigned char straight_path_flags[
MAX_POLYS];
398 dtPolyRef straight_path_polys[
MAX_POLYS];
399 int num_straight_path = 0;
400 int straight_path_options = DT_STRAIGHTPATH_AREA_CROSSINGS;
414 float poly_pick_ext[3] = {2,4,2};
423 const dtQueryFilter *filter;
426 std::lock_guard<std::mutex> lock(
_mutex);
428 filter =
_crowd->getFilter(
_crowd->getAgent(it->second)->params.queryFilterType);
432 dtPolyRef start_ref = 0;
433 dtPolyRef end_ref = 0;
435 float start_pos[3] = { from.
x, from.
z, from.
y };
436 float end_pos[3] = { to.
x, to.
z, to.
y };
439 std::lock_guard<std::mutex> lock(
_mutex);
441 _nav_query->findNearestPoly(start_pos, poly_pick_ext, filter, &start_ref, 0);
443 _nav_query->findNearestPoly(end_pos, poly_pick_ext, filter, &end_ref, 0);
445 if (!start_ref || !end_ref) {
452 std::lock_guard<std::mutex> lock(
_mutex);
454 _nav_query->findPath(start_ref, end_ref, start_pos, end_pos, filter, polys, &num_polys,
MAX_POLYS);
458 if (num_polys == 0) {
464 dtVcopy(end_pos2, end_pos);
465 if (polys[num_polys - 1] != end_ref) {
467 std::lock_guard<std::mutex> lock(
_mutex);
469 _nav_query->closestPointOnPoly(polys[num_polys - 1], end_pos, end_pos2, 0);
476 std::lock_guard<std::mutex> lock(
_mutex);
478 _nav_query->findStraightPath(start_pos, end_pos2, polys, num_polys,
479 straight_path, straight_path_flags,
480 straight_path_polys, &num_straight_path,
MAX_POLYS, straight_path_options);
485 path.reserve(
static_cast<unsigned long>(num_straight_path));
486 unsigned char area_type;
487 for (
int i = 0, j = 0; j < num_straight_path; i += 3, ++j) {
489 path.emplace_back(straight_path[i], straight_path[i + 2], straight_path[i + 1]);
493 std::lock_guard<std::mutex> lock(
_mutex);
494 _nav_mesh->getPolyArea(straight_path_polys[j], &area_type);
496 area.emplace_back(area_type);
504 dtCrowdAgentParams params;
514 memset(¶ms, 0,
sizeof(params));
517 params.maxAcceleration = 160.0f;
518 params.maxSpeed = 1.47f;
519 params.collisionQueryRange = 10;
520 params.obstacleAvoidanceType = 3;
521 params.separationWeight = 0.5f;
525 params.queryFilterType = 1;
527 params.queryFilterType = 0;
531 params.updateFlags = 0;
537 float point_from[3] = { from.
x, from.
z - (
AGENT_HEIGHT / 2.0f), from.
y };
542 std::lock_guard<std::mutex> lock(
_mutex);
543 index =
_crowd->addAgent(point_from, ¶ms);
565 dtCrowdAgentParams params;
585 box_corner1 = cg::Math::RotatePointOnOrigin2D(box_corner1, angle);
586 box_corner2 = cg::Math::RotatePointOnOrigin2D(box_corner2, angle);
587 box_corner3 = cg::Math::RotatePointOnOrigin2D(box_corner3, angle);
588 box_corner4 = cg::Math::RotatePointOnOrigin2D(box_corner4, angle);
599 int index = it->second;
605 std::lock_guard<std::mutex> lock(
_mutex);
606 agent =
_crowd->getEditableAgent(index);
614 agent->params.obb[0] = box_corner1.x;
615 agent->params.obb[1] = box_corner1.z;
616 agent->params.obb[2] = box_corner1.y;
617 agent->params.obb[3] = box_corner2.x;
618 agent->params.obb[4] = box_corner2.z;
619 agent->params.obb[5] = box_corner2.y;
620 agent->params.obb[6] = box_corner3.x;
621 agent->params.obb[7] = box_corner3.z;
622 agent->params.obb[8] = box_corner3.y;
623 agent->params.obb[9] = box_corner4.x;
624 agent->params.obb[10] = box_corner4.z;
625 agent->params.obb[11] = box_corner4.y;
632 memset(¶ms, 0,
sizeof(params));
635 params.maxAcceleration = 0.0f;
636 params.maxSpeed = 1.47f;
637 params.collisionQueryRange = 0;
638 params.obstacleAvoidanceType = 0;
639 params.separationWeight = 100.0f;
642 params.updateFlags = 0;
647 params.useObb =
true;
648 params.obb[0] = box_corner1.x;
649 params.obb[1] = box_corner1.z;
650 params.obb[2] = box_corner1.y;
651 params.obb[3] = box_corner2.x;
652 params.obb[4] = box_corner2.z;
653 params.obb[5] = box_corner2.y;
654 params.obb[6] = box_corner3.x;
655 params.obb[7] = box_corner3.z;
656 params.obb[8] = box_corner3.y;
657 params.obb[9] = box_corner4.x;
658 params.obb[10] = box_corner4.z;
659 params.obb[11] = box_corner4.y;
670 std::lock_guard<std::mutex> lock(
_mutex);
671 index =
_crowd->addAgent(point_from, ¶ms);
673 logging::log(
"Vehicle agent not added to the crowd by some problem!");
678 dtCrowdAgent *agent =
_crowd->getEditableAgent(index);
680 agent->state = DT_CROWDAGENT_STATE_WALKING;
707 std::lock_guard<std::mutex> lock(
_mutex);
708 _crowd->removeAgent(it->second);
724 std::lock_guard<std::mutex> lock(
_mutex);
725 _crowd->removeAgent(it->second);
739 std::unordered_set<carla::rpc::ActorId> updated;
743 updated.insert(entry.first);
747 for (
auto &&entry : vehicles) {
751 updated.erase(entry.id);
755 for (
auto &&entry : updated) {
782 std::lock_guard<std::mutex> lock(
_mutex);
783 dtCrowdAgent *agent =
_crowd->getEditableAgent(it->second);
785 agent->params.maxSpeed = max_speed;
843 float point_to[3] = { to.
x, to.
z, to.
y };
848 std::lock_guard<std::mutex> lock(
_mutex);
849 const dtQueryFilter *filter =
_crowd->getFilter(0);
850 dtPolyRef target_ref;
851 _nav_query->findNearestPoly(point_to,
_crowd->getQueryHalfExtents(), filter, &target_ref, nearest);
856 res =
_crowd->requestMoveTarget(index, target_ref, point_to);
876 std::lock_guard<std::mutex> lock(
_mutex);
887 int total_unblocked = 0;
891 std::lock_guard<std::mutex> lock(
_mutex);
892 total_agents =
_crowd->getAgentCount();
894 const dtCrowdAgent *ag;
895 for (
int i = 0; i < total_agents; ++i) {
898 std::lock_guard<std::mutex> lock(
_mutex);
902 if (!ag->active || ag->paused || ag->dead) {
907 if (!ag->params.useObb && !ag->paused) {
908 bool reset_target_pos =
false;
909 bool use_same_filter =
false;
920 reset_target_pos =
true;
921 use_same_filter =
true;
927 if (reset_target_pos) {
929 if (!use_same_filter) {
968 int index = it->second;
974 const dtCrowdAgent *agent;
977 std::lock_guard<std::mutex> lock(
_mutex);
978 agent =
_crowd->getAgent(index);
981 if (!agent->active) {
994 if (agent->vel[0] < -
min || agent->vel[0] >
min ||
995 agent->vel[2] < -
min || agent->vel[2] >
min) {
996 yaw = atan2f(agent->vel[2], agent->vel[0]) * (180.0f /
static_cast<float>(M_PI));
997 speed = sqrtf(agent->vel[0] * agent->vel[0] + agent->vel[1] * agent->vel[1] + agent->vel[2] * agent->vel[2]);
999 yaw = atan2f(agent->dvel[2], agent->dvel[0]) * (180.0f /
static_cast<float>(M_PI));
1000 speed = sqrtf(agent->dvel[0] * agent->dvel[0] + agent->dvel[1] * agent->dvel[1] + agent->dvel[2] * agent->dvel[2]);
1004 float shortest_angle = fmod(yaw -
_yaw_walkers[
id] + 540.0f, 360.0f) - 180.0f;
1005 float per = (speed / 1.5f);
1006 if (per > 1.0f) per = 1.0f;
1007 float rotation_speed = per * 6.0f;
1009 (shortest_angle * rotation_speed *
static_cast<float>(
_delta_seconds));
1032 int index = it->second;
1038 const dtCrowdAgent *agent;
1041 std::lock_guard<std::mutex> lock(
_mutex);
1042 agent =
_crowd->getAgent(index);
1045 if (!agent->active) {
1050 location.
x = agent->npos[0];
1051 location.
y = agent->npos[2];
1052 location.
z = agent->npos[1];
1073 int index = it->second;
1079 const dtCrowdAgent *agent;
1082 std::lock_guard<std::mutex> lock(
_mutex);
1083 agent =
_crowd->getAgent(index);
1086 return sqrt(agent->vel[0] * agent->vel[0] + agent->vel[1] * agent->vel[1] + agent->vel[2] *
1101 dtQueryFilter filter2;
1102 if (filter ==
nullptr) {
1109 dtPolyRef random_ref { 0 };
1110 float point[3] { 0.0f, 0.0f, 0.0f };
1115 std::lock_guard<std::mutex> lock(
_mutex);
1117 status =
_nav_query->findRandomPoint(filter,
frand, &random_ref, point);
1119 if (status == DT_SUCCESS) {
1120 location.
x = point[0];
1121 location.
y = point[2];
1122 location.
z = point[1];
1125 }
while (status != DT_SUCCESS && rounds > 0);
1128 return (rounds > 0);
1135 dtCrowdAgent *agent;
1138 std::lock_guard<std::mutex> lock(
_mutex);
1139 agent =
_crowd->getEditableAgent(agent_index);
1141 agent->params.queryFilterType =
static_cast<unsigned char>(filter_index);
1168 int index = it->second;
1174 dtCrowdAgent *agent;
1177 std::lock_guard<std::mutex> lock(
_mutex);
1178 agent =
_crowd->getEditableAgent(index);
1182 agent->paused = pause;
1195 float dir[3] = { direction.
x, direction.
z, direction.
y };
1199 std::lock_guard<std::mutex> lock(
_mutex);
1200 result =
_crowd->hasVehicleNear(it->second, distance * distance, dir,
false);
1216 dtCrowdAgent *agent;
1219 std::lock_guard<std::mutex> lock(
_mutex);
1220 agent =
_crowd->getEditableAgent(it->second);
1224 float x = (location.
x - agent->npos[0]) * 0.0001f;
1225 float y = (location.
y - agent->npos[2]) * 0.0001f;
1226 float z = (location.
z - agent->npos[1]) * 0.0001f;
1257 int index = it->second;
1263 const dtCrowdAgent *agent;
1266 std::lock_guard<std::mutex> lock(
_mutex);
1267 agent =
_crowd->getAgent(index);
1271 alive = !agent->dead;
auto end() const noexcept
#define DEBUG_ASSERT(predicate)
double min(double v1, double v2)
返回两个数中的较小值
const auto & GetTimestamp() const
Vector3D extent
边界框的半尺寸(本地坐标系下,表示在每个轴方向上的半宽、半高和半深)
float SquaredLength() const
bool SetWalkerMaxSpeed(ActorId id, float max_speed)
设置新的最大速度
void UpdateCrowd(const client::detail::EpisodeState &state)
更新人群中的所有步行者
bool GetPath(carla::geom::Location from, carla::geom::Location to, dtQueryFilter *filter, std::vector< carla::geom::Location > &path, std::vector< unsigned char > &area)
返回从一个位置到另一个位置的路径点
void SetAgentFilter(int agent_index, int filter_index)
为代理分配过滤索引
std::unordered_map< ActorId, int > _mapped_vehicles_id
std::unordered_map< ActorId, int > _mapped_walkers_id
mapping Id
bool RemoveAgent(ActorId id)
移除代理
std::weak_ptr< carla::client::detail::Simulator > _simulator
bool GetWalkerPosition(ActorId id, carla::geom::Location &location)
获取行人的当前位置
float GetWalkerSpeed(ActorId id)
获取步行人速度
bool Load(const std::string &filename)
从磁盘中加载导航数据
bool SetWalkerTarget(ActorId id, carla::geom::Location to)
设置新的目标点以通过有事件的路线
void SetSeed(unsigned int seed)
设置随机数种子
bool UpdateVehicles(std::vector< VehicleCollisionInfo > vehicles)
在人群中添加/更新/删除车辆
std::unordered_map< int, ActorId > _mapped_by_index
bool SetWalkerDirectTarget(ActorId id, carla::geom::Location to)
bool SetWalkerLookAt(ActorId id, carla::geom::Location location)
让代理查看某个位置
void PauseAgent(ActorId id, bool pause)
将人群中的代理设置为暂停
bool HasVehicleNear(ActorId id, float distance, carla::geom::Location direction)
如果代理在附近有车辆(作为邻居),则返回
bool GetWalkerTransform(ActorId id, carla::geom::Transform &trans)
获取步行人当前变换
bool GetRandomLocation(carla::geom::Location &location, dtQueryFilter *filter=nullptr) const
获取导航的随机位置
bool IsWalkerAlive(ActorId id, bool &alive)
如果行人代理被车辆撞死,则返回
WalkerManager _walker_manager
行人管理器负责带事件的路线规划
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)
设置行人代理在路径跟随过程中穿过马路的概率
std::unordered_map< ActorId, float > _yaw_walkers
存储上一个节拍的行人偏航角
bool AddWalker(ActorId id, carla::geom::Location from)
创建新的行人
std::vector< uint8_t > _binary_mesh
bool SetWalkerDirectTargetIndex(int index, carla::geom::Location to)
void SetSimulator(std::weak_ptr< carla::client::detail::Simulator > simulator)
引用模拟器来访问API函数
dtNavMeshQuery * _nav_query
void CreateCrowd(void)
创建人群对象
bool AddOrUpdateVehicle(VehicleCollisionInfo &vehicle)
在人群中创造一辆新的车辆,让行人避开
float _probability_crossing
std::unordered_map< int, carla::geom::Vector3D > _walkers_blocked_position
每隔一段时间保存每个参与者的位置,并检查是否有参与者被阻挡
bool RemoveWalker(ActorId id)
bool AddWalker(ActorId id)
void SetSimulator(std::weak_ptr< carla::client::detail::Simulator > simulator)
bool Update(double delta)
void SetNav(Navigation *nav)
bool SetWalkerRoute(ActorId id)
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
carla::geom::BoundingBox bounding
carla::geom::Transform transform