赞
踩
以下是基于ROS实现A*算法的C++代码示例:
#include <ros/ros.h> #include <queue> #include <vector> #include <algorithm> #include <cmath> struct Node { int x, y; double f, g, h; Node* parent; Node(int x, int y) : x(x), y(y), f(0), g(0), h(0), parent(nullptr) {} }; class AStar { public: AStar(int sx, int sy, int gx, int gy) : start_(new Node(sx, sy)), goal_(new Node(gx, gy)) { ROS_ASSERT(sx >= 0 && sy >= 0 && gx >= 0 && gy >= 0); ROS_INFO("Start: (%d, %d), Goal: (%d, %d)", sx, sy, gx, gy); open_list_.push(start_); } ~AStar() { for (auto& row : nodes_) { for (auto node : row) { delete node; } } } bool plan() { while (!open_list_.empty()) { auto current = open_list_.top(); open_list_.pop(); if (current->x == goal_->x && current->y == goal_->y) { ROS_INFO("Found path with cost: %f", current->g); path_.push_back(current); while (current->parent) { path_.push_back(current->parent); current = current->parent; } std::reverse(path_.begin(), path_.end()); return true; } if (closed_list_.count(current) > 0) { continue; } closed_list_.insert(current); expandNode(current); } ROS_WARN("Failed to find path"); return false; } std::vector<Node*> getPath() const { return path_; } void setObstacle(int x, int y) { ROS_ASSERT(x >= 0 && y >= 0); if (nodes_.size() <= x) { nodes_.resize(x + 1); } if (nodes_[x].size() <= y) { nodes_[x].resize(y + 1); } if (!nodes_[x][y]) { nodes_[x][y] = new Node(x, y); } nodes_[x][y]->g = std::numeric_limits<double>::infinity(); } private: void expandNode(Node* node) { static const std::vector<std::pair<int, int>> dirs = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}}; for (auto& dir : dirs) { int x = node->x + dir.first; int y = node->y + dir.second; if (x < 0 || y < 0) { continue; } if (x >= nodes_.size() || y >= nodes_[x].size()) { continue; } if (!nodes_[x][y]) { nodes_[x][y] = new Node(x, y); } auto child = nodes_[x][y]; if (child->g <= node->g + 1) { continue; } child->parent = node; child->g = node->g + 1; child->h = heuristic(child, goal_); child->f = child->g + child->h; open_list_.push(child); } } double heuristic(Node* a, Node* b) { return std::sqrt(std::pow(a->x - b->x, 2) + std::pow(a->y - b->y, 2)); } Node* start_; Node* goal_; std::vector<std::vector<Node*>> nodes_; std::priority_queue<Node*, std::vector<Node*>, [](Node* a, Node* b) { return a->f > b->f; }> open_list_; std::unordered_set<Node*> closed_list_; std::vector<Node*> path_; }; int main(int argc, char** argv) { ros::init(argc, argv, "astar"); ros::NodeHandle nh("~"); int sx, sy, gx, gy; nh.param("start_x", sx, 0); nh.param("start_y", sy, 0); nh.param("goal_x", gx, 10); nh.param("goal_y", gy, 10); AStar astar(sx, sy, gx, gy); int num_obstacles; nh.param("num_obstacles", num_obstacles, 0); for (int i = 0; i < num_obstacles; ++i) { int x, y; nh.getParam("obstacle_" + std::to_string(i) + "_x", x); nh.getParam("obstacle_" + std::to_string(i) + "_y", y); astar.setObstacle(x, y); } if (astar.plan()) { auto path = astar.getPath(); for (auto node : path) { ROS_INFO("(%d, %d)", node->x, node->y); } } return 0; }
在这个例子中,AStar
类负责实现A算法,Node
结构体表示地图中的一个节点。setObstacle
方法用于设置障碍物,plan
方法用于执行A算法,getPath
方法用于获取计算出的路径。main
函数中读取ROS参数,并设置障碍物。运行时,可以使用以下命令启动节点:
rosrun astar astar _start_x:=0 _start_y:=0 _goal_x:=10 _goal_y:=10 _num_obstacles:=2 _obstacle_0_x:=2 _obstacle_0_y:=3 _obstacle_1_x:=4 _obstacle_1_y:=5
其中,_start_x
、_start_y
、_goal_x
、_goal_y
分别表示起点和终点。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。