improved walkbot

This commit is contained in:
2026-04-12 12:05:40 +03:00
parent bb974da0e2
commit ea07d17dbb
2 changed files with 34 additions and 11 deletions

View File

@@ -5,16 +5,24 @@
#include "navigation_mesh.hpp" #include "navigation_mesh.hpp"
#include "omath/linear_algebra/vector3.hpp" #include "omath/linear_algebra/vector3.hpp"
#include <functional> #include <functional>
#include <memory>
namespace omath::pathfinding namespace omath::pathfinding
{ {
class WalkBot class WalkBot
{ {
public: public:
void update(const Vector3<float>& bot_position, const Vector3<float>& target_position, float min_node_distance) const; WalkBot() = default;
explicit WalkBot(std::shared_ptr<NavigationMesh> mesh);
void set_nav_mesh(std::shared_ptr<NavigationMesh> mesh);
void update(const Vector3<float>& bot_position, const Vector3<float>& target_position, float min_node_distance);
void on_path(std::function<void(const Vector3<float>&)> callback); void on_path(std::function<void(const Vector3<float>&)> callback);
private: private:
std::weak_ptr<NavigationMesh> m_mav_mesh; std::weak_ptr<NavigationMesh> m_mav_mesh;
std::optional<std::function<void(const Vector3<float>&)>> m_on_next_path_node = nullptr; std::optional<std::function<void(const Vector3<float>&)>> m_on_next_path_node;
std::optional<Vector3<float>> m_last_visited;
}; };
} // namespace omath::pathfinding } // namespace omath::pathfinding

View File

@@ -7,26 +7,41 @@
namespace omath::pathfinding namespace omath::pathfinding
{ {
void WalkBot::update(const Vector3<float>& bot_position, const Vector3<float>& target_position, WalkBot::WalkBot(std::shared_ptr<NavigationMesh> mesh) : m_mav_mesh(std::move(mesh)) {}
const float min_node_distance) const
{
const auto nav_mesh = m_mav_mesh.lock();
void WalkBot::set_nav_mesh(std::shared_ptr<NavigationMesh> mesh)
{
m_mav_mesh = std::move(mesh);
}
void WalkBot::update(const Vector3<float>& bot_position, const Vector3<float>& target_position,
const float min_node_distance)
{
if (!m_on_next_path_node.has_value())
return;
const auto nav_mesh = m_mav_mesh.lock();
if (!nav_mesh) if (!nav_mesh)
return; return;
const auto path = Astar::find_path(bot_position, target_position, *nav_mesh); const auto path = Astar::find_path(bot_position, target_position, *nav_mesh);
if (path.empty()) if (path.empty())
return; return;
if (!m_on_next_path_node.has_value()) const auto& nearest = path.front();
return;
if (path.size() > 1 && path.front().distance_to(bot_position) <= min_node_distance) // Record the nearest node as visited once we are close enough to it.
if (nearest.distance_to(bot_position) <= min_node_distance)
m_last_visited = nearest;
// If the nearest node was already visited, advance to the next one so
// we never oscillate back to a node we just left.
// If the bot was displaced (blown back), nearest will be an unvisited
// node, so we route to it first before continuing forward.
if (m_last_visited.has_value() && *m_last_visited == nearest && path.size() > 1)
m_on_next_path_node->operator()(path[1]); m_on_next_path_node->operator()(path[1]);
else else
m_on_next_path_node->operator()(path.front()); m_on_next_path_node->operator()(nearest);
} }
void WalkBot::on_path(std::function<void(const Vector3<float>&)> callback) void WalkBot::on_path(std::function<void(const Vector3<float>&)> callback)
{ {