19 #include "geometry_msgs/msg/pose_stamped.hpp"
20 #include "rclcpp/rclcpp.hpp"
21 #include "nav2_ros_common/tf2_factories.hpp"
23 #include "nav2_theta_star_planner/theta_star_planner.hpp"
24 #include "nav2_theta_star_planner/theta_star.hpp"
26 namespace nav2_theta_star_planner
29 const nav2::LifecycleNode::WeakPtr & parent,
30 std::string name, nav2::TransformBuffer::SharedPtr tf,
31 std::shared_ptr<nav2_costmap_2d::Costmap2DROS> costmap_ros)
33 parent_node_ = parent;
34 auto node = parent_node_.lock();
35 logger_ = node->get_logger();
36 clock_ = node->get_clock();
39 global_frame_ = costmap_ros->getGlobalFrameID();
43 param_handler_ = std::make_unique<ParameterHandler>(
44 node, name_, logger_);
45 params_ = param_handler_->getParams();
46 planner_ = std::make_unique<ThetaStar>(params_);
47 planner_->costmap_ = costmap_ros->getCostmap();
52 RCLCPP_INFO(logger_,
"CleaningUp plugin %s of type nav2_theta_star_planner", name_.c_str());
58 RCLCPP_INFO(logger_,
"Activating plugin %s of type nav2_theta_star_planner", name_.c_str());
59 param_handler_->activate();
64 RCLCPP_INFO(logger_,
"Deactivating plugin %s of type nav2_theta_star_planner", name_.c_str());
65 auto node = parent_node_.lock();
66 param_handler_->deactivate();
70 const geometry_msgs::msg::PoseStamped & start,
71 const geometry_msgs::msg::PoseStamped & goal,
72 const std::vector<geometry_msgs::msg::PoseStamped> & viapoints,
73 std::function<
bool()> cancel_checker)
75 if (!viapoints.empty()) {
76 RCLCPP_WARN(logger_,
"Received %zu viapoints, but this planner ignores them",
80 std::lock_guard<std::mutex> lock_reinit(param_handler_->getMutex());
81 nav_msgs::msg::Path global_path;
82 auto start_time = std::chrono::steady_clock::now();
84 std::unique_lock<nav2_costmap_2d::Costmap2D::mutex_t> lock(*(planner_->costmap_->getMutex()));
87 unsigned int mx_start, my_start, mx_goal, my_goal;
88 if (!planner_->costmap_->worldToMap(
89 start.pose.position.x, start.pose.position.y, mx_start, my_start))
92 "Start Coordinates of(" + std::to_string(start.pose.position.x) +
", " +
93 std::to_string(start.pose.position.y) +
") was outside bounds");
96 if (!planner_->costmap_->worldToMap(
97 goal.pose.position.x, goal.pose.position.y, mx_goal, my_goal))
100 "Goal Coordinates of(" + std::to_string(goal.pose.position.x) +
", " +
101 std::to_string(goal.pose.position.y) +
") was outside bounds");
104 if (planner_->costmap_->getCost(mx_goal, my_goal) == nav2_costmap_2d::LETHAL_OBSTACLE) {
106 "Goal Coordinates of(" + std::to_string(goal.pose.position.x) +
", " +
107 std::to_string(goal.pose.position.y) +
") was in lethal cost");
110 if (mx_start == mx_goal && my_start == my_goal) {
111 global_path.header.stamp = clock_->now();
112 global_path.header.frame_id = global_frame_;
113 geometry_msgs::msg::PoseStamped pose;
114 pose.header = global_path.header;
115 pose.pose.position.z = 0.0;
117 pose.pose = start.pose;
121 if (start.pose.orientation != goal.pose.orientation &&
122 !params_->use_final_approach_orientation)
124 pose.pose.orientation = goal.pose.orientation;
126 global_path.poses.push_back(pose);
130 planner_->clearStart();
131 planner_->setStartAndGoal(start, goal);
133 logger_,
"Got the src and dst... (%i, %i) && (%i, %i)",
134 planner_->src_.x, planner_->src_.y, planner_->dst_.x, planner_->dst_.y);
135 getPlan(global_path, cancel_checker);
137 size_t plan_size = global_path.poses.size();
139 global_path.poses.back().pose.orientation = goal.pose.orientation;
146 if (params_->use_final_approach_orientation) {
147 if (plan_size == 1) {
148 global_path.poses.back().pose.orientation = start.pose.orientation;
149 }
else if (plan_size > 1) {
150 double dx, dy, theta;
151 auto last_pose = global_path.poses.back().pose.position;
152 auto approach_pose = global_path.poses[plan_size - 2].pose.position;
153 dx = last_pose.x - approach_pose.x;
154 dy = last_pose.y - approach_pose.y;
155 theta = atan2(dy, dx);
156 global_path.poses.back().pose.orientation =
157 nav2_util::geometry_utils::orientationAroundZAxis(theta);
161 auto stop_time = std::chrono::steady_clock::now();
162 auto dur = std::chrono::duration_cast<std::chrono::microseconds>(stop_time - start_time);
163 RCLCPP_DEBUG(logger_,
"the time taken is : %i",
static_cast<int>(dur.count()));
164 RCLCPP_DEBUG(logger_,
"the nodes_opened are: %i", planner_->nodes_opened);
169 nav_msgs::msg::Path & global_path,
170 std::function<
bool()> cancel_checker)
172 std::vector<coordsW> path;
173 if (planner_->isUnsafeToPlan()) {
174 global_path.poses.clear();
176 }
else if (planner_->generatePath(path, cancel_checker)) {
179 global_path.poses.clear();
182 global_path.header.stamp = clock_->now();
183 global_path.header.frame_id = global_frame_;
187 const std::vector<coordsW> & raw_path,
188 const double & dist_bw_points)
190 nav_msgs::msg::Path pa;
192 geometry_msgs::msg::PoseStamped p1;
193 for (
unsigned int j = 0; j < raw_path.size() - 1; j++) {
195 p1.pose.position.x = pt1.x;
196 p1.pose.position.y = pt1.y;
197 pa.poses.push_back(p1);
200 double distance = std::hypot(pt2.x - pt1.x, pt2.y - pt1.y);
201 int loops =
static_cast<int>(distance / dist_bw_points);
202 double sin_alpha = (pt2.y - pt1.y) / distance;
203 double cos_alpha = (pt2.x - pt1.x) / distance;
204 for (
int k = 1; k < loops; k++) {
205 p1.pose.position.x = pt1.x + k * dist_bw_points * cos_alpha;
206 p1.pose.position.y = pt1.y + k * dist_bw_points * sin_alpha;
207 pa.poses.push_back(p1);
216 #include "pluginlib/class_list_macros.hpp"
Abstract interface for global planners to adhere to with pluginlib.
nav_msgs::msg::Path createPlan(const geometry_msgs::msg::PoseStamped &start, const geometry_msgs::msg::PoseStamped &goal, const std::vector< geometry_msgs::msg::PoseStamped > &viapoints, std::function< bool()> cancel_checker) override
Creating a plan from start and goal poses.
void getPlan(nav_msgs::msg::Path &global_path, std::function< bool()> cancel_checker)
the function responsible for calling the algorithm and retrieving a path from it
void cleanup() override
Method to cleanup resources used on shutdown.
static nav_msgs::msg::Path linearInterpolation(const std::vector< coordsW > &raw_path, const double &dist_bw_points)
interpolates points between the consecutive waypoints of the path
void deactivate() override
Method to deactivate planner and any threads involved in execution.
void configure(const nav2::LifecycleNode::WeakPtr &parent, std::string name, nav2::TransformBuffer::SharedPtr tf, std::shared_ptr< nav2_costmap_2d::Costmap2DROS > costmap_ros) override
void activate() override
Method to active planner and any threads involved in execution.