FollowObject Action
Package: nav2_msgs
Category: Object Following
Follow a detected object using pose tracking or TF frame tracking
Message Definitions
Goal Message
| Field |
Type |
Description |
pose_topic |
string |
Topic to publish the pose of the object to follow |
tracked_frame |
string |
Target TF frame to follow (optional, used if pose_topic is not set) |
max_duration |
builtin_interfaces/Duration |
Maximum duration for the object following task |
Result Message
| Field |
Type |
Description |
NONE |
uint16 |
Success status code indicating the action completed without errors |
GOAL_REJECTED |
uint16 |
Error code indicating the goal was rejected by the server |
SEND_GOAL_FAILURE |
uint16 |
Error code indicating failure to send the goal |
TF_ERROR |
uint16 |
Error code indicating a transform/localization failure |
FAILED_TO_DETECT_OBJECT |
uint16 |
Error code indicating the target object could not be detected |
FAILED_TO_CONTROL |
uint16 |
Error code indicating control system failure during following |
TIMEOUT |
uint16 |
Error code indicating the action exceeded its maximum allowed time |
UNKNOWN |
uint16 |
Generic error code for unexpected or unclassified failures |
total_elapsed_time |
builtin_interfaces/Duration |
Total time elapsed during object following |
error_code |
uint16 |
Contextual error code, if any |
num_retries |
uint16 |
Number of retries attempted |
error_msg |
string |
Human-readable error message describing what went wrong during action execution |
Feedback Message
| Field |
Type |
Description |
NONE |
uint16 |
No active state |
INITIAL_PERCEPTION |
uint16 |
Initial object detection phase |
CONTROLLING |
uint16 |
Actively following the object |
STOPPING |
uint16 |
Decelerating to stop |
RETRY |
uint16 |
Retrying after a failure |
state |
uint16 |
Current following state |
following_time |
builtin_interfaces/Duration |
Time elapsed since following began |
num_retries |
uint16 |
Number of retries attempted |
Usage Examples
Python
import rclpy
from rclpy.node import Node
from rclpy.action import ActionClient
from nav2_msgs.action import FollowObject
class Nav2ActionClient(Node):
def __init__(self):
super().__init__('nav2_action_client')
self.action_client = ActionClient(self, FollowObject, 'follow_object')
def send_goal(self):
goal_msg = FollowObject.Goal()
goal_msg.pose_topic = '/detected_object_pose'
# Alternative: track a TF frame instead of a pose topic
# goal.tracked_frame = 'target_object'
goal_msg.max_duration = Duration(seconds=60.0)
self.action_client.wait_for_server()
future = self.action_client.send_goal_async(
goal_msg, feedback_callback=self.feedback_callback)
return future
def feedback_callback(self, feedback_msg):
self.get_logger().info(f'Received feedback: {feedback_msg.feedback}')
C++
#include "rclcpp/rclcpp.hpp"
#include "rclcpp_action/rclcpp_action.hpp"
#include "nav2_msgs/action/follow_object.hpp"
class Nav2ActionClient : public rclcpp::Node
{
public:
using FollowObjectAction = nav2_msgs::action::FollowObject;
using GoalHandle = rclcpp_action::ClientGoalHandle<FollowObjectAction>;
Nav2ActionClient() : Node("nav2_action_client")
{
action_client_ = rclcpp_action::create_client<FollowObjectAction>(
this, "follow_object");
}
void send_goal()
{
auto goal_msg = FollowObjectAction::Goal();
goal_msg.pose_topic = "/detected_object_pose";
// Alternative: track a TF frame instead of a pose topic
// goal_msg.tracked_frame = "target_object";
goal_msg.max_duration = rclcpp::Duration::from_seconds(60.0);
action_client_->wait_for_action_server();
auto send_goal_options = rclcpp_action::Client<FollowObjectAction>::SendGoalOptions();
send_goal_options.feedback_callback =
std::bind(&Nav2ActionClient::feedback_callback, this,
std::placeholders::_1, std::placeholders::_2);
action_client_->async_send_goal(goal_msg, send_goal_options);
}
private:
rclcpp_action::Client<FollowObjectAction>::SharedPtr action_client_;
void feedback_callback(GoalHandle::SharedPtr,
const std::shared_ptr<const FollowObjectAction::Feedback> feedback)
{
RCLCPP_INFO(this->get_logger(), "Received feedback");
}
};