/navigate_through_waypoints
#
Caution
This documentation page has been auto-generated.
It may be missing some details.
/navigate_through_waypoints
Quick Facts
- Category
- Message type
pal_nav2_msgs/action/NavigateThroughWaypoints
Nav2 BT Navigator implemented for PAL robots. It integrates the functionalities of the Nav2 Navigate Through Poses documentation (see /navigate_through_poses) with the ones of the Nav2 Waypoint Follower documentation (see /follow_waypoints). It uses a Behavior Tree to navigate from a starting point, through a series of waypoints, eventually executing a list of Waypoint Actions upon each Waypoint arrival.
For more information, check the 🚩 Waypoint Navigation.
Quick snippets#
$ ros2 action send_goal /navigate_through_waypoints pal_nav2_msgs/action/NavigateThroughWaypoints # press Tab to complete the message prototype
How to use in your code#
#!/usr/bin/env python
import rclpy
from rclpy.action import ActionClient
from rclpy.node import Node
from pal_nav2_msgs.action import NavigateThroughWaypoints
class NavigateThroughWaypointsActionClient(Node):
def __init__(self):
super().__init__('navigate_through_waypoints_client')
self._action_client = ActionClient(self, NavigateThroughWaypoints, '/navigate_through_waypoints')
def send_goal(self, a, b):
goal_msg = NavigateThroughWaypoints.Goal()
# TODO: adapt to the action's parameters
# check the pal_nav2_msgs/action/NavigateThroughWaypointsGoal message
# definition for the possible goal parameters
# goal_msg.a = a
# goal_msg.b = b
self._action_client.wait_for_server()
return self._action_client.send_goal_async(goal_msg)
if __name__ == '__main__':
rclpy.init(args=args)
action_client = NavigateThroughWaypointsActionClient()
# TODO: adapt to your action's parameters
future = action_client.send_goal(a, b)
rclpy.spin_until_future_complete(action_client, future)
rclpy.shutdown()
#include <functional>
#include <future>
#include <memory>
#include <string>
#include <sstream>
#include <chrono>
#include "pal_nav2_msgs/action/navigate_through_waypoints.hpp"
#include "rclcpp/rclcpp.hpp"
#include "rclcpp_action/rclcpp_action.hpp"
#include "rclcpp_components/register_node_macro.hpp"
using namespace std::chrono_literals;
using namespace std;
class NavigateThroughWaypointsActionClient : public rclcpp::Node
{
public:
using NavigateThroughWaypoints = pal_nav2_msgs::action::NavigateThroughWaypoints;
using GoalHandleNavigateThroughWaypoints = rclcpp_action::ClientGoalHandle<NavigateThroughWaypoints>;
explicit NavigateThroughWaypointsActionClient(const rclcpp::NodeOptions & options)
: Node("navigate_through_waypoints_action_client", options)
{
this->client_ptr_ = rclcpp_action::create_client<NavigateThroughWaypoints>(
this,
"/navigate_through_waypoints");
this->timer_ = this->create_wall_timer(
500ms,
bind(&NavigateThroughWaypointsActionClient::send_goal, this));
}
void send_goal()
{
using namespace std::placeholders;
this->timer_->cancel();
if (!this->client_ptr_->wait_for_action_server()) {
RCLCPP_ERROR(this->get_logger(), "Action server not available after waiting");
rclcpp::shutdown();
}
auto goal_msg = NavigateThroughWaypoints::Goal();
// check the pal_nav2_msgs/action/NavigateThroughWaypointsGoal message
// definition for the possible goal parameters
// goal_msg.... = ...;
RCLCPP_INFO(this->get_logger(), "Sending goal");
auto send_goal_options = rclcpp_action::Client<NavigateThroughWaypoints>::SendGoalOptions();
send_goal_options.goal_response_callback =
bind(&NavigateThroughWaypointsActionClient::goal_response_callback, this, _1);
send_goal_options.feedback_callback =
bind(&NavigateThroughWaypointsActionClient::feedback_callback, this, _1, _2);
send_goal_options.result_callback =
bind(&NavigateThroughWaypointsActionClient::result_callback, this, _1);
this->client_ptr_->async_send_goal(goal_msg, send_goal_options);
}
private:
rclcpp_action::Client<NavigateThroughWaypoints>::SharedPtr client_ptr_;
rclcpp::TimerBase::SharedPtr timer_;
void goal_response_callback(const GoalHandleNavigateThroughWaypoints::SharedPtr & goal_handle)
{
if (!goal_handle) {
RCLCPP_ERROR(this->get_logger(), "Goal was rejected by server");
} else {
RCLCPP_INFO(this->get_logger(), "Goal accepted by server, waiting for result");
}
}
void feedback_callback(
GoalHandleNavigateThroughWaypoints::SharedPtr,
const shared_ptr<const NavigateThroughWaypoints::Feedback> feedback)
{
stringstream ss;
ss << "Next number in sequence received: ";
for (auto number : feedback->partial_sequence) {
ss << number << " ";
}
RCLCPP_INFO(this->get_logger(), ss.str().c_str());
}
void result_callback(const GoalHandleNavigateThroughWaypoints::WrappedResult & result)
{
switch (result.code) {
case rclcpp_action::ResultCode::SUCCEEDED:
break;
case rclcpp_action::ResultCode::ABORTED:
RCLCPP_ERROR(this->get_logger(), "Goal was aborted");
return;
case rclcpp_action::ResultCode::CANCELED:
RCLCPP_ERROR(this->get_logger(), "Goal was canceled");
return;
default:
RCLCPP_ERROR(this->get_logger(), "Unknown result code");
return;
}
stringstream ss;
ss << "Result received: ";
for (auto number : result.result->sequence) {
ss << number << " ";
}
RCLCPP_INFO(this->get_logger(), ss.str().c_str());
rclcpp::shutdown();
}
}; // class NavigateThroughWaypointsActionClient
RCLCPP_COMPONENTS_REGISTER_NODE(NavigateThroughWaypointsActionClient)