Working on pedestrian movement
This commit is contained in:
parent
42a4ea0eb7
commit
007f9c7122
|
@ -100,12 +100,6 @@ namespace client {
|
|||
return _simulator->ApplyBatchSync(std::move(commands), do_tick_cue);
|
||||
}
|
||||
|
||||
std::vector<carla::geom::Location> CreateWalker(
|
||||
carla::geom::Location From,
|
||||
carla::geom::Location To) const {
|
||||
return _simulator->CreateWalker(From, To);
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
std::shared_ptr<detail::Simulator> _simulator;
|
||||
|
|
|
@ -19,7 +19,8 @@ namespace client {
|
|||
}
|
||||
|
||||
void WalkerAIController::GoToLocation(const carla::geom::Location &destination) {
|
||||
|
||||
auto nav = GetEpisode().Lock()->GetNavigation();
|
||||
nav->SetWalkerTarget(GetParent()->GetId(), destination);
|
||||
logging::log("GO TO LOCATION:", destination.x, destination.y, destination.z);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "carla/client/Actor.h"
|
||||
#include "carla/client/detail/WalkerNavigation.h"
|
||||
#include "carla/geom/Vector3D.h"
|
||||
|
||||
namespace carla {
|
||||
|
@ -22,7 +23,6 @@ namespace client {
|
|||
void GoToLocation(const carla::geom::Location &destination);
|
||||
|
||||
void SetMaxSpeed(const float max_speed);
|
||||
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
|
|
@ -52,6 +52,12 @@ namespace detail {
|
|||
|
||||
std::shared_ptr<WalkerNavigation> CreateNavigationIfMissing();
|
||||
|
||||
std::shared_ptr<WalkerNavigation> GetNavigation() const {
|
||||
auto nav = _navigation.load();
|
||||
DEBUG_ASSERT(nav != nullptr);
|
||||
return nav;
|
||||
}
|
||||
|
||||
void RegisterActor(rpc::Actor actor) {
|
||||
_actors.Insert(std::move(actor));
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "carla/client/detail/Client.h"
|
||||
#include "carla/client/detail/Episode.h"
|
||||
#include "carla/client/detail/EpisodeProxy.h"
|
||||
#include "carla/client/detail/WalkerNavigation.h"
|
||||
#include "carla/profiler/LifetimeProfiled.h"
|
||||
#include "carla/rpc/TrafficLightState.h"
|
||||
|
||||
|
@ -181,6 +182,10 @@ namespace detail {
|
|||
|
||||
void RegisterAIController(const WalkerAIController &controller);
|
||||
|
||||
std::shared_ptr<WalkerNavigation> GetNavigation() {
|
||||
return _episode->GetNavigation();
|
||||
}
|
||||
|
||||
/// @}
|
||||
// =========================================================================
|
||||
/// @name General operations with actors
|
||||
|
@ -342,12 +347,6 @@ namespace detail {
|
|||
_client.SetReplayerTimeFactor(time_factor);
|
||||
}
|
||||
|
||||
std::vector<carla::geom::Location> CreateWalker(
|
||||
carla::geom::Location From,
|
||||
carla::geom::Location To) const {
|
||||
return _client.CreateWalker(From, To);
|
||||
};
|
||||
|
||||
/// @}
|
||||
// =========================================================================
|
||||
/// @name Operations with walkers
|
||||
|
|
|
@ -14,34 +14,38 @@ namespace carla {
|
|||
namespace client {
|
||||
namespace detail {
|
||||
|
||||
static geom::Transform TickWalker(
|
||||
const float delta_seconds,
|
||||
geom::Transform transform) {
|
||||
transform.location += delta_seconds * 2.778f * transform.GetForwardVector();
|
||||
return transform;
|
||||
}
|
||||
|
||||
WalkerNavigation::WalkerNavigation(Client &client) : _client(client) {
|
||||
// Here call the server to retrieve the navmesh data.
|
||||
_nav.Load(_client.GetNavigationMesh());
|
||||
|
||||
// query the navigation to find a path of points
|
||||
// std::vector<carla::geom::Location> Path;
|
||||
// if (!_nav.GetPath(From, To, nullptr, Path)) {
|
||||
// logging::log("NAV: Path not found");
|
||||
// }
|
||||
// return Path;
|
||||
|
||||
}
|
||||
|
||||
void WalkerNavigation::Tick(const EpisodeState &state) const {
|
||||
void WalkerNavigation::Tick(const EpisodeState &state) {
|
||||
auto walkers = _walkers.Load();
|
||||
if (walkers->empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// update crowd in navigation module
|
||||
_nav.UpdateCrowd(state);
|
||||
|
||||
carla::geom::Transform trans;
|
||||
using Cmd = rpc::Command;
|
||||
std::vector<Cmd> commands;
|
||||
commands.reserve(walkers->size());
|
||||
|
||||
for (auto handle : *walkers) {
|
||||
commands.emplace_back(
|
||||
Cmd::ApplyTransform{
|
||||
handle.walker,
|
||||
TickWalker(
|
||||
static_cast<float>(state.GetTimestamp().delta_seconds),
|
||||
state.GetActorState(handle.walker).transform)});
|
||||
// get the transform of the walker
|
||||
if (_nav.GetWalkerTransform(handle.walker, trans)) {
|
||||
// logging::log("Nav: walker at ", trans.location.x, trans.location.y, trans.location.z);
|
||||
commands.emplace_back(Cmd::ApplyTransform{ handle.walker, trans });
|
||||
}
|
||||
}
|
||||
|
||||
_client.ApplyBatch(std::move(commands), false);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "carla/AtomicList.h"
|
||||
#include "carla/nav/Navigation.h"
|
||||
#include "carla/NonCopyable.h"
|
||||
#include "carla/client/Timestamp.h"
|
||||
#include "carla/client/detail/EpisodeProxy.h"
|
||||
|
@ -29,15 +30,26 @@ namespace detail {
|
|||
explicit WalkerNavigation(Client &client);
|
||||
|
||||
void RegisterWalker(ActorId walker_id, ActorId controller_id) {
|
||||
_walkers.Push(WalkerHandle{walker_id, controller_id});
|
||||
// add to list
|
||||
_walkers.Push(WalkerHandle { walker_id, controller_id });
|
||||
|
||||
// create the walker in the crowd (to manage its movement in Detour)
|
||||
_nav.AddWalker(walker_id);
|
||||
}
|
||||
|
||||
void Tick(const EpisodeState &episode_state) const;
|
||||
void Tick(const EpisodeState &episode_state);
|
||||
|
||||
// set a new target point to go
|
||||
bool SetWalkerTarget(ActorId id, carla::geom::Location to) {
|
||||
return _nav.SetWalkerTarget(id, to);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Client &_client;
|
||||
|
||||
carla::nav::Navigation _nav;
|
||||
|
||||
struct WalkerHandle {
|
||||
ActorId walker;
|
||||
ActorId controller;
|
||||
|
|
|
@ -23,9 +23,9 @@ namespace nav {
|
|||
}
|
||||
|
||||
Navigation::~Navigation() {
|
||||
dtFreeCrowd(Crowd);
|
||||
dtFreeNavMeshQuery(NavQuery);
|
||||
dtFreeNavMesh(NavMesh);
|
||||
dtFreeCrowd(_crowd);
|
||||
dtFreeNavMeshQuery(_navQuery);
|
||||
dtFreeNavMesh(_navMesh);
|
||||
}
|
||||
|
||||
// load navigation data
|
||||
|
@ -37,15 +37,15 @@ namespace nav {
|
|||
f.open(filename, std::ios::binary);
|
||||
if (!f.is_open())
|
||||
return false;
|
||||
std::vector<uint8_t> Content(start, end);
|
||||
std::vector<uint8_t> content(start, end);
|
||||
f.close();
|
||||
|
||||
// parse the content
|
||||
return Load(Content);
|
||||
return Load(content);
|
||||
}
|
||||
|
||||
// load navigation data from memory
|
||||
bool Navigation::Load(const std::vector<uint8_t> Content) {
|
||||
bool Navigation::Load(const std::vector<uint8_t> content) {
|
||||
const int NAVMESHSET_MAGIC = 'M'<<24 | 'S'<<16 | 'E'<<8 | 'T'; //'MSET';
|
||||
const int NAVMESHSET_VERSION = 1;
|
||||
#pragma pack(push, 1)
|
||||
|
@ -62,9 +62,9 @@ namespace nav {
|
|||
#pragma pack(pop)
|
||||
|
||||
// read the file header
|
||||
unsigned long Pos = 0;
|
||||
memcpy(&header, &Content[Pos], sizeof(header));
|
||||
Pos += sizeof(header);
|
||||
unsigned long pos = 0;
|
||||
memcpy(&header, &content[pos], sizeof(header));
|
||||
pos += sizeof(header);
|
||||
|
||||
// check file magic and version
|
||||
if (header.magic != NAVMESHSET_MAGIC || header.version != NAVMESHSET_VERSION) {
|
||||
|
@ -84,9 +84,9 @@ namespace nav {
|
|||
NavMeshTileHeader tileHeader;
|
||||
|
||||
// read the tile header
|
||||
memcpy(&tileHeader, &Content[Pos], sizeof(tileHeader));
|
||||
Pos += sizeof(tileHeader);
|
||||
if (Pos >= Content.size()) {
|
||||
memcpy(&tileHeader, &content[pos], sizeof(tileHeader));
|
||||
pos += sizeof(tileHeader);
|
||||
if (pos >= content.size()) {
|
||||
dtFreeNavMesh(mesh);
|
||||
return false;
|
||||
}
|
||||
|
@ -101,9 +101,9 @@ namespace nav {
|
|||
|
||||
// read the tile
|
||||
memset(data, 0, static_cast<size_t>(tileHeader.dataSize));
|
||||
memcpy(data, &Content[Pos], static_cast<size_t>(tileHeader.dataSize));
|
||||
Pos += static_cast<unsigned long>(tileHeader.dataSize);
|
||||
if (Pos > Content.size()) {
|
||||
memcpy(data, &content[pos], static_cast<size_t>(tileHeader.dataSize));
|
||||
pos += static_cast<unsigned long>(tileHeader.dataSize);
|
||||
if (pos > content.size()) {
|
||||
dtFree(data);
|
||||
dtFreeNavMesh(mesh);
|
||||
return false;
|
||||
|
@ -114,72 +114,72 @@ namespace nav {
|
|||
}
|
||||
|
||||
// exchange
|
||||
dtFreeNavMesh(NavMesh);
|
||||
NavMesh = mesh;
|
||||
dtFreeNavMesh(_navMesh);
|
||||
_navMesh = mesh;
|
||||
|
||||
// prepare the query object
|
||||
dtFreeNavMeshQuery(NavQuery);
|
||||
NavQuery = dtAllocNavMeshQuery();
|
||||
NavQuery->init(NavMesh, 2048);
|
||||
dtFreeNavMeshQuery(_navQuery);
|
||||
_navQuery = dtAllocNavMeshQuery();
|
||||
_navQuery->init(_navMesh, 2048);
|
||||
|
||||
// create and init the crowd manager
|
||||
CreateCrowd();
|
||||
|
||||
// copy
|
||||
BinaryMesh = Content;
|
||||
_binaryMesh = content;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Navigation::CreateCrowd(void) {
|
||||
|
||||
if (Crowd != nullptr)
|
||||
if (_crowd != nullptr)
|
||||
return;
|
||||
|
||||
// create and init
|
||||
Crowd = dtAllocCrowd();
|
||||
Crowd->init(MAX_AGENTS, AGENT_RADIUS, NavMesh);
|
||||
_crowd = dtAllocCrowd();
|
||||
_crowd->init(MAX_AGENTS, AGENT_RADIUS, _navMesh);
|
||||
|
||||
// make polygons with 'disabled' flag invalid
|
||||
Crowd->getEditableFilter(0)->setExcludeFlags(SAMPLE_POLYFLAGS_DISABLED);
|
||||
_crowd->getEditableFilter(0)->setExcludeFlags(SAMPLE_POLYFLAGS_DISABLED);
|
||||
|
||||
// Setup local avoidance params to different qualities.
|
||||
dtObstacleAvoidanceParams Params;
|
||||
dtObstacleAvoidanceParams params;
|
||||
// Use mostly default settings, copy from dtCrowd.
|
||||
memcpy(&Params, Crowd->getObstacleAvoidanceParams(0), sizeof(dtObstacleAvoidanceParams));
|
||||
memcpy(¶ms, _crowd->getObstacleAvoidanceParams(0), sizeof(dtObstacleAvoidanceParams));
|
||||
|
||||
// Low (11)
|
||||
Params.velBias = 0.5f;
|
||||
Params.adaptiveDivs = 5;
|
||||
Params.adaptiveRings = 2;
|
||||
Params.adaptiveDepth = 1;
|
||||
Crowd->setObstacleAvoidanceParams(0, &Params);
|
||||
params.velBias = 0.5f;
|
||||
params.adaptiveDivs = 5;
|
||||
params.adaptiveRings = 2;
|
||||
params.adaptiveDepth = 1;
|
||||
_crowd->setObstacleAvoidanceParams(0, ¶ms);
|
||||
|
||||
// Medium (22)
|
||||
Params.velBias = 0.5f;
|
||||
Params.adaptiveDivs = 5;
|
||||
Params.adaptiveRings = 2;
|
||||
Params.adaptiveDepth = 2;
|
||||
Crowd->setObstacleAvoidanceParams(1, &Params);
|
||||
params.velBias = 0.5f;
|
||||
params.adaptiveDivs = 5;
|
||||
params.adaptiveRings = 2;
|
||||
params.adaptiveDepth = 2;
|
||||
_crowd->setObstacleAvoidanceParams(1, ¶ms);
|
||||
|
||||
// Good (45)
|
||||
Params.velBias = 0.5f;
|
||||
Params.adaptiveDivs = 7;
|
||||
Params.adaptiveRings = 2;
|
||||
Params.adaptiveDepth = 3;
|
||||
Crowd->setObstacleAvoidanceParams(2, &Params);
|
||||
params.velBias = 0.5f;
|
||||
params.adaptiveDivs = 7;
|
||||
params.adaptiveRings = 2;
|
||||
params.adaptiveDepth = 3;
|
||||
_crowd->setObstacleAvoidanceParams(2, ¶ms);
|
||||
|
||||
// High (66)
|
||||
Params.velBias = 0.5f;
|
||||
Params.adaptiveDivs = 7;
|
||||
Params.adaptiveRings = 3;
|
||||
Params.adaptiveDepth = 3;
|
||||
params.velBias = 0.5f;
|
||||
params.adaptiveDivs = 7;
|
||||
params.adaptiveRings = 3;
|
||||
params.adaptiveDepth = 3;
|
||||
|
||||
Crowd->setObstacleAvoidanceParams(3, &Params);
|
||||
_crowd->setObstacleAvoidanceParams(3, ¶ms);
|
||||
}
|
||||
|
||||
// return the path points to go from one position to another
|
||||
bool Navigation::GetPath(const carla::geom::Location From, const carla::geom::Location To, dtQueryFilter* Filter, std::vector<carla::geom::Location> &Path) {
|
||||
bool Navigation::GetPath(const carla::geom::Location from, const carla::geom::Location to, dtQueryFilter* filter, std::vector<carla::geom::Location> &path) {
|
||||
// path found
|
||||
float m_straightPath[MAX_POLYS*3];
|
||||
unsigned char m_straightPathFlags[MAX_POLYS];
|
||||
|
@ -190,9 +190,9 @@ namespace nav {
|
|||
dtPolyRef m_polys[MAX_POLYS];
|
||||
int m_npolys;
|
||||
|
||||
// check to load the binary navmesh from server
|
||||
logging::log("Nav: ", BinaryMesh.size());
|
||||
if (BinaryMesh.size() == 0) {
|
||||
// check to load the binary _navMesh from server
|
||||
logging::log("Nav: ", _binaryMesh.size());
|
||||
if (_binaryMesh.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -203,26 +203,26 @@ namespace nav {
|
|||
m_polyPickExt[2] = 2;
|
||||
|
||||
// filter
|
||||
dtQueryFilter m_filter;
|
||||
if (Filter == nullptr) {
|
||||
m_filter.setIncludeFlags(SAMPLE_POLYFLAGS_ALL ^ SAMPLE_POLYFLAGS_DISABLED);
|
||||
m_filter.setExcludeFlags(0);
|
||||
Filter = &m_filter;
|
||||
dtQueryFilter filter2;
|
||||
if (filter == nullptr) {
|
||||
filter2.setIncludeFlags(SAMPLE_POLYFLAGS_ALL ^ SAMPLE_POLYFLAGS_DISABLED);
|
||||
filter2.setExcludeFlags(0);
|
||||
filter = &filter2;
|
||||
}
|
||||
|
||||
// set the points
|
||||
dtPolyRef m_startRef = 0;
|
||||
dtPolyRef m_endRef = 0;
|
||||
float m_spos[3] = { From.x, From.z, From.y };
|
||||
float m_epos[3] = { To.x, To.z, To.y };
|
||||
NavQuery->findNearestPoly(m_spos, m_polyPickExt, Filter, &m_startRef, 0);
|
||||
NavQuery->findNearestPoly(m_epos, m_polyPickExt, Filter, &m_endRef, 0);
|
||||
float m_spos[3] = { from.x, from.z, from.y };
|
||||
float m_epos[3] = { to.x, to.z, to.y };
|
||||
_navQuery->findNearestPoly(m_spos, m_polyPickExt, filter, &m_startRef, 0);
|
||||
_navQuery->findNearestPoly(m_epos, m_polyPickExt, filter, &m_endRef, 0);
|
||||
if (!m_startRef || !m_endRef) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// get the path of nodes
|
||||
NavQuery->findPath(m_startRef, m_endRef, m_spos, m_epos, Filter, m_polys, &m_npolys, MAX_POLYS);
|
||||
_navQuery->findPath(m_startRef, m_endRef, m_spos, m_epos, filter, m_polys, &m_npolys, MAX_POLYS);
|
||||
|
||||
// get the path of points
|
||||
m_nstraightPath = 0;
|
||||
|
@ -234,100 +234,122 @@ namespace nav {
|
|||
float epos[3];
|
||||
dtVcopy(epos, m_epos);
|
||||
if (m_polys[m_npolys-1] != m_endRef)
|
||||
NavQuery->closestPointOnPoly(m_polys[m_npolys-1], m_epos, epos, 0);
|
||||
_navQuery->closestPointOnPoly(m_polys[m_npolys-1], m_epos, epos, 0);
|
||||
|
||||
// get the points
|
||||
NavQuery->findStraightPath(m_spos, epos, m_polys, m_npolys,
|
||||
_navQuery->findStraightPath(m_spos, epos, m_polys, m_npolys,
|
||||
m_straightPath, m_straightPathFlags,
|
||||
m_straightPathPolys, &m_nstraightPath, MAX_POLYS, m_straightPathOptions);
|
||||
|
||||
// copy the path to the output buffer
|
||||
Path.clear();
|
||||
Path.reserve(static_cast<unsigned long>(m_nstraightPath));
|
||||
path.clear();
|
||||
path.reserve(static_cast<unsigned long>(m_nstraightPath));
|
||||
for (int i=0; i<m_nstraightPath*3; i+=3) {
|
||||
// export for Unreal axis (x, z, y)
|
||||
Path.emplace_back(m_straightPath[i], m_straightPath[i+2], m_straightPath[i+1]);
|
||||
path.emplace_back(m_straightPath[i], m_straightPath[i+2], m_straightPath[i+1]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// create a new walker
|
||||
bool Navigation::AddWalker(ActorId Id, carla::geom::Location From) {
|
||||
dtCrowdAgentParams Params;
|
||||
// create a new walker but not yet add in crowd
|
||||
void Navigation::AddWalker(ActorId id) {
|
||||
// add to the queue to be added later and next tick where we can access the transform
|
||||
_walkersQueueToAdd.push_back(id);
|
||||
}
|
||||
|
||||
if (Crowd == nullptr) {
|
||||
// create a new walker in crowd
|
||||
bool Navigation::AddWalkerInCrowd(ActorId id, carla::geom::Location from) {
|
||||
dtCrowdAgentParams params;
|
||||
|
||||
if (_crowd == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// set parameters
|
||||
memset(&Params, 0, sizeof(Params));
|
||||
Params.radius = AGENT_RADIUS;
|
||||
Params.height = AGENT_HEIGHT;
|
||||
Params.maxAcceleration = 8.0f;
|
||||
Params.maxSpeed = 3.5f;
|
||||
Params.collisionQueryRange = Params.radius * 12.0f;
|
||||
Params.pathOptimizationRange = Params.radius * 30.0f;
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.radius = AGENT_RADIUS;
|
||||
params.height = AGENT_HEIGHT;
|
||||
params.maxAcceleration = 8.0f;
|
||||
params.maxSpeed = 3.5f;
|
||||
params.collisionQueryRange = params.radius * 12.0f;
|
||||
params.pathOptimizationRange = params.radius * 30.0f;
|
||||
|
||||
// flags
|
||||
Params.updateFlags = 0;
|
||||
Params.updateFlags |= DT_CROWD_ANTICIPATE_TURNS;
|
||||
Params.updateFlags |= DT_CROWD_OPTIMIZE_VIS;
|
||||
Params.updateFlags |= DT_CROWD_OPTIMIZE_TOPO;
|
||||
Params.updateFlags |= DT_CROWD_OBSTACLE_AVOIDANCE;
|
||||
Params.updateFlags |= DT_CROWD_SEPARATION;
|
||||
Params.obstacleAvoidanceType = 3;
|
||||
Params.separationWeight = 2.0;
|
||||
params.updateFlags = 0;
|
||||
params.updateFlags |= DT_CROWD_ANTICIPATE_TURNS;
|
||||
params.updateFlags |= DT_CROWD_OPTIMIZE_VIS;
|
||||
params.updateFlags |= DT_CROWD_OPTIMIZE_TOPO;
|
||||
params.updateFlags |= DT_CROWD_OBSTACLE_AVOIDANCE;
|
||||
params.updateFlags |= DT_CROWD_SEPARATION;
|
||||
params.obstacleAvoidanceType = 3;
|
||||
params.separationWeight = 2.0;
|
||||
|
||||
// add walker
|
||||
float PointFrom[3] = { From.x, From.y, From.z };
|
||||
int Index = Crowd->addAgent(PointFrom, &Params);
|
||||
if (Index != -1) {
|
||||
float PointFrom[3] = { from.x, from.y, from.z };
|
||||
int index = _crowd->addAgent(PointFrom, ¶ms);
|
||||
if (index != -1) {
|
||||
// save the id
|
||||
MappedId[Id] = Index;
|
||||
_mappedId[id] = index;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// set a new target point to go
|
||||
bool Navigation::SetWalkerTarget(ActorId Id, carla::geom::Location To) {
|
||||
bool Navigation::SetWalkerTarget(ActorId id, carla::geom::Location to) {
|
||||
// get the internal index
|
||||
auto It = MappedId.find(Id);
|
||||
if (It == MappedId.end())
|
||||
auto it = _mappedId.find(id);
|
||||
if (it == _mappedId.end())
|
||||
return false;
|
||||
|
||||
// get the index found
|
||||
int Index = It->second;
|
||||
if (Index != -1) {
|
||||
int index = it->second;
|
||||
if (index == -1)
|
||||
return false;
|
||||
|
||||
// set target position
|
||||
float PointTo[3] = { To.x, To.y, To.z };
|
||||
float Nearest[3];
|
||||
const dtQueryFilter *Filter = Crowd->getFilter(0);
|
||||
dtPolyRef TargetRef;
|
||||
NavQuery->findNearestPoly(PointTo, Crowd->getQueryHalfExtents(), Filter, &TargetRef, Nearest);
|
||||
if (TargetRef)
|
||||
Crowd->requestMoveTarget(Index, TargetRef, PointTo);
|
||||
}
|
||||
logging::log("Nav: ", index, it->first);
|
||||
|
||||
// set target position
|
||||
float pointTo[3] = { to.x, to.y, to.z };
|
||||
float nearest[3];
|
||||
const dtQueryFilter *filter = _crowd->getFilter(0);
|
||||
dtPolyRef targetRef;
|
||||
_navQuery->findNearestPoly(pointTo, _crowd->getQueryHalfExtents(), filter, &targetRef, nearest);
|
||||
if (targetRef)
|
||||
_crowd->requestMoveTarget(index, targetRef, pointTo);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// update all walkers in crowd
|
||||
void Navigation::UpdateCrowd(float DeltaTime) {
|
||||
void Navigation::UpdateCrowd(const client::detail::EpisodeState &state) {
|
||||
|
||||
if (!NavMesh || !Crowd) {
|
||||
if (!_navMesh || !_crowd) {
|
||||
return;
|
||||
}
|
||||
|
||||
// update all
|
||||
Crowd->update(DeltaTime, nullptr);
|
||||
// check if we have more walkers in the queue to add
|
||||
while (_walkersQueueToAdd.size() > 0) {
|
||||
// add it
|
||||
ActorId id = _walkersQueueToAdd.back();
|
||||
carla::geom::Transform trans = state.GetActorState(id).transform;
|
||||
trans.location.z -= (AGENT_HEIGHT / 2.0f);
|
||||
if (!AddWalkerInCrowd(id, trans.location)) {
|
||||
break;
|
||||
}
|
||||
// remove it
|
||||
_walkersQueueToAdd.pop_back();
|
||||
}
|
||||
|
||||
// update all
|
||||
double deltaTime = state.GetTimestamp().delta_seconds;
|
||||
_crowd->update(static_cast<float>(deltaTime), nullptr);
|
||||
/*
|
||||
// get all walker positions
|
||||
for (int i = 0; i < Crowd->getAgentCount(); ++i)
|
||||
for (int i = 0; i < _crowd->getAgentCount(); ++i)
|
||||
{
|
||||
const dtCrowdAgent* ag = Crowd->getAgent(i);
|
||||
const dtCrowdAgent* ag = _crowd->getAgent(i);
|
||||
if (!ag->active)
|
||||
continue;
|
||||
|
||||
|
@ -336,6 +358,33 @@ namespace nav {
|
|||
// trail->htrail = (trail->htrail + 1) % AGENT_MAX_TRAIL;
|
||||
// dtVcopy(&trail->trail[trail->htrail*3], ag->npos);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// get the walker current transform
|
||||
bool Navigation::GetWalkerTransform(ActorId id, carla::geom::Transform &trans) {
|
||||
// get the internal index
|
||||
auto it = _mappedId.find(id);
|
||||
if (it == _mappedId.end())
|
||||
return false;
|
||||
|
||||
// get the index found
|
||||
int index = it->second;
|
||||
if (index == -1)
|
||||
return false;
|
||||
|
||||
// get the walker
|
||||
const dtCrowdAgent *agent = _crowd->getAgent(index);
|
||||
// set its position
|
||||
trans.location.x = agent->npos[0];
|
||||
trans.location.y = agent->npos[2];
|
||||
trans.location.z = agent->npos[1] + (AGENT_HEIGHT / 2.0f);
|
||||
// set its rotation
|
||||
trans.rotation.pitch = asin(agent->nvel[2]);
|
||||
trans.rotation.yaw = asin(agent->nvel[0]);
|
||||
trans.rotation.roll = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace nav
|
||||
|
|
|
@ -6,8 +6,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "carla/rpc/ActorId.h"
|
||||
#include "carla/client/detail/EpisodeState.h"
|
||||
#include "carla/geom/Location.h"
|
||||
#include "carla/geom/Transform.h"
|
||||
#include "carla/rpc/ActorId.h"
|
||||
#include "recast/Recast.h"
|
||||
#include "recast/DetourCrowd.h"
|
||||
#include "recast/DetourNavMesh.h"
|
||||
|
@ -51,30 +53,35 @@ namespace nav {
|
|||
Navigation();
|
||||
~Navigation();
|
||||
// load navigation data
|
||||
bool Load(const std::string Filename);
|
||||
bool Load(const std::string filename);
|
||||
// load navigation data from memory
|
||||
bool Load(const std::vector<uint8_t> Content);
|
||||
bool Load(const std::vector<uint8_t> content);
|
||||
// return the path points to go from one position to another
|
||||
bool GetPath(const carla::geom::Location From, const carla::geom::Location To, dtQueryFilter* Filter, std::vector<carla::geom::Location> &Path);
|
||||
bool GetPath(const carla::geom::Location from, const carla::geom::Location to, dtQueryFilter* filter, std::vector<carla::geom::Location> &path);
|
||||
|
||||
// create the crowd object
|
||||
void CreateCrowd(void);
|
||||
// add a walker
|
||||
bool AddWalker(ActorId Id, carla::geom::Location From);
|
||||
// create a new walker but not yet add in crowd
|
||||
void AddWalker(ActorId id);
|
||||
// create a new walker in crowd
|
||||
bool AddWalkerInCrowd(ActorId id, carla::geom::Location from);
|
||||
// set a new target point to go
|
||||
bool SetWalkerTarget(ActorId Id, carla::geom::Location To);
|
||||
bool SetWalkerTarget(ActorId id, carla::geom::Location to);
|
||||
// get the walker current transform
|
||||
bool GetWalkerTransform(ActorId id, carla::geom::Transform &trans);
|
||||
// update all walkers in crowd
|
||||
void UpdateCrowd(float DeltaTime);
|
||||
void UpdateCrowd(const client::detail::EpisodeState &state);
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> BinaryMesh;
|
||||
std::vector<uint8_t> _binaryMesh;
|
||||
std::vector<ActorId> _walkersQueueToAdd;
|
||||
// meshes
|
||||
dtNavMesh *NavMesh { nullptr };
|
||||
dtNavMeshQuery *NavQuery { nullptr };
|
||||
dtNavMesh *_navMesh { nullptr };
|
||||
dtNavMeshQuery *_navQuery { nullptr };
|
||||
// crowd
|
||||
dtCrowd *Crowd { nullptr };
|
||||
dtCrowd *_crowd { nullptr };
|
||||
// mapping Id
|
||||
std::unordered_map<ActorId, int> MappedId;
|
||||
std::unordered_map<ActorId, int> _mappedId;
|
||||
};
|
||||
|
||||
} // namespace nav
|
||||
|
|
|
@ -39,6 +39,7 @@ def get_libcarla_extensions():
|
|||
os.path.join(pwd, 'dependencies/lib/libboost_filesystem.a'),
|
||||
os.path.join(pwd, 'dependencies/lib/libRecast.a'),
|
||||
os.path.join(pwd, 'dependencies/lib/libDetour.a'),
|
||||
os.path.join(pwd, 'dependencies/lib/libDetourCrowd.a'),
|
||||
os.path.join(pwd, 'dependencies/lib', pylib)]
|
||||
extra_compile_args = [
|
||||
'-isystem', 'dependencies/include/system', '-fPIC', '-std=c++14',
|
||||
|
|
|
@ -71,6 +71,5 @@ void export_client() {
|
|||
.def("set_replayer_time_factor", &cc::Client::SetReplayerTimeFactor, (arg("time_factor")))
|
||||
.def("apply_batch", &ApplyBatchCommands, (arg("commands"), arg("do_tick")=false))
|
||||
.def("apply_batch_sync", &ApplyBatchCommandsSync, (arg("commands"), arg("do_tick")=false))
|
||||
.def("create_walker", CALL_RETURNING_LIST_2(cc::Client, CreateWalker, carla::geom::Location, carla::geom::Location), (arg("location"), arg("location")))
|
||||
;
|
||||
}
|
||||
|
|
|
@ -55,17 +55,42 @@ def main():
|
|||
world = client.get_world()
|
||||
m = world.get_map()
|
||||
debug = world.debug
|
||||
a = carla.Location(-141.789, -143.839, 0.139954)
|
||||
b = carla.Location(-29.7504, -26.8764, 0.270432)
|
||||
points = []
|
||||
points = client.create_walker(a, b)
|
||||
for i in range(len(points)-1):
|
||||
a1 = carla.Location(points[i].x, points[i].y, points[i].z)
|
||||
b1 = carla.Location(points[i+1].x, points[i+1].y, points[i+1].z)
|
||||
# print(a.x, a.y, a.z)
|
||||
debug.draw_line(a1, b1, color=orange, thickness=0.5, life_time=12)
|
||||
# debug.draw_line(a, a+carla.Location(z=1000), color=orange, thickness=0.2, life_time=12)
|
||||
debug.draw_point(a1, 1, red, 12)
|
||||
|
||||
spawn_point = carla.Transform()
|
||||
spawn_point.location.x = -18
|
||||
spawn_point.location.y = 1.2
|
||||
spawn_point.location.z = 18
|
||||
spawn_point.rotation.roll = 0.0
|
||||
spawn_point.rotation.pitch = 0.0
|
||||
|
||||
# player
|
||||
# print(world.get_blueprint_library())
|
||||
# exit(1)
|
||||
blueprint = random.choice(world.get_blueprint_library().filter('walker.pedestrian.0002'))
|
||||
player = world.spawn_actor(blueprint, spawn_point)
|
||||
|
||||
# controller
|
||||
blueprint = random.choice(world.get_blueprint_library().filter('controller.ai.walker'))
|
||||
walker_controller = world.spawn_actor(blueprint, spawn_point, attach_to=player)
|
||||
walker_controller.start()
|
||||
time.sleep(0.5)
|
||||
walker_controller.go_to_location(carla.Location(-48, 1.2, 27))
|
||||
# walker_controller.set_max_speed(40)
|
||||
|
||||
while (1):
|
||||
time.sleep(1);
|
||||
|
||||
# a = carla.Location(-141.789, -143.839, 0.139954)
|
||||
# b = carla.Location(-29.7504, -26.8764, 0.270432)
|
||||
# points = []
|
||||
# points = client.create_walker(a, b)
|
||||
# for i in range(len(points)-1):
|
||||
# a1 = carla.Location(points[i].x, points[i].y, points[i].z)
|
||||
# b1 = carla.Location(points[i+1].x, points[i+1].y, points[i+1].z)
|
||||
# # print(a.x, a.y, a.z)
|
||||
# debug.draw_line(a1, b1, color=orange, thickness=0.5, life_time=12)
|
||||
# # debug.draw_line(a, a+carla.Location(z=1000), color=orange, thickness=0.2, life_time=12)
|
||||
# debug.draw_point(a1, 1, red, 12)
|
||||
|
||||
finally:
|
||||
pass
|
||||
|
|
Loading…
Reference in New Issue