Nav2 Navigation Stack - rolling  main
ROS 2 Navigation Stack
following_server.hpp
1 // Copyright (c) 2024 Open Navigation LLC
2 // Copyright (c) 2024 Alberto J. Tudela Roldán
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #ifndef OPENNAV_FOLLOWING__FOLLOWING_SERVER_HPP_
17 #define OPENNAV_FOLLOWING__FOLLOWING_SERVER_HPP_
18 
19 #include <vector>
20 #include <memory>
21 #include <string>
22 #include <mutex>
23 #include <functional>
24 
25 #include "geometry_msgs/msg/pose_stamped.hpp"
26 #include "rclcpp/rclcpp.hpp"
27 #include "rclcpp_lifecycle/lifecycle_publisher.hpp"
28 #include "nav2_msgs/action/follow_object.hpp"
29 #include "nav2_ros_common/lifecycle_node.hpp"
30 #include "nav2_ros_common/node_utils.hpp"
31 #include "nav2_ros_common/simple_action_server.hpp"
32 #include "nav2_util/twist_publisher.hpp"
33 #include "nav2_util/odometry_utils.hpp"
34 #include "opennav_docking/controller.hpp"
35 #include "opennav_docking/pose_filter.hpp"
36 #include "tf2_ros/buffer.hpp"
37 #include "tf2_ros/transform_listener.hpp"
38 
39 namespace opennav_following
40 {
46 {
47 public:
48  using FollowObject = nav2_msgs::action::FollowObject;
50 
55  explicit FollowingServer(const rclcpp::NodeOptions & options = rclcpp::NodeOptions());
56 
60  ~FollowingServer() = default;
61 
66  void publishFollowingFeedback(uint16_t state);
67 
75  virtual bool approachObject(
76  geometry_msgs::msg::PoseStamped & object_pose,
77  const std::string & target_frame = std::string(""));
78 
85  virtual bool rotateToObject(
86  geometry_msgs::msg::PoseStamped & object_pose,
87  const std::string & target_frame = std::string(""));
88 
95  template<typename ActionT>
97  typename std::shared_ptr<const typename ActionT::Goal> goal,
98  const typename nav2::SimpleActionServer<ActionT>::SharedPtr & action_server);
99 
106  template<typename ActionT>
108  typename nav2::SimpleActionServer<ActionT>::SharedPtr & action_server,
109  const std::string & name);
110 
117  template<typename ActionT>
119  typename nav2::SimpleActionServer<ActionT>::SharedPtr & action_server,
120  const std::string & name);
121 
127  nav2::CallbackReturn on_configure(const rclcpp_lifecycle::State & state) override;
128 
134  nav2::CallbackReturn on_activate(const rclcpp_lifecycle::State & state) override;
135 
141  nav2::CallbackReturn on_deactivate(const rclcpp_lifecycle::State & state) override;
142 
148  nav2::CallbackReturn on_cleanup(const rclcpp_lifecycle::State & state) override;
149 
155  nav2::CallbackReturn on_shutdown(const rclcpp_lifecycle::State & state) override;
156 
160  void publishZeroVelocity();
161 
162 protected:
166  void followObject();
167 
174  virtual bool getRefinedPose(geometry_msgs::msg::PoseStamped & pose);
175 
182  virtual bool getFramePose(geometry_msgs::msg::PoseStamped & pose, const std::string & frame_id);
183 
190  virtual bool getTrackingPose(
191  geometry_msgs::msg::PoseStamped & pose, const std::string & frame_id);
192 
200  geometry_msgs::msg::PoseStamped getPoseAtDistance(
201  const geometry_msgs::msg::PoseStamped & pose, double distance);
202 
209  bool isGoalReached(const geometry_msgs::msg::PoseStamped & goal_pose);
210 
215  rcl_interfaces::msg::SetParametersResult
216  dynamicParametersCallback(std::vector<rclcpp::Parameter> parameters);
217 
218  // Dynamic parameters handler
219  rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtr dyn_params_handler_;
220 
221  // Mutex for dynamic parameters
222  std::mutex dynamic_params_lock_;
223 
224  // Frequency to run control loops
225  double controller_frequency_;
226  // Timeout to detect the object while rotating to it
227  double rotate_to_object_timeout_;
228  // Timeout after which a static object is considered as goal reached
229  double static_object_timeout_;
230  // Time when object became static
231  rclcpp::Time static_object_start_time_;
232  // Flag to track if we've initialized the static timer
233  bool static_timer_initialized_;
234  // Tolerance for transforming coordinates
235  double transform_tolerance_;
236  // Tolerances for arriving at the safe_distance pose
237  double linear_tolerance_, angular_tolerance_;
238  // Maximum number of times the robot will retry to approach the object
239  int max_retries_, num_retries_;
240  // This is the root frame of the robot - typically "base_link"
241  std::string base_frame_;
242  // This is our fixed frame for controlling - typically "odom"
243  std::string fixed_frame_;
244  // Desired distance to keep from the object
245  double desired_distance_;
246  // Skip perception orientation
247  bool skip_orientation_;
248  // Should the robot search for the object by rotating or go to last known heading
249  bool search_by_rotating_;
250  // Search angle relative to current robot orientation when rotating to find objects
251  double search_angle_;
252 
253  // Timestamp of the last time a iteration was started
254  rclcpp::Time iteration_start_time_;
255 
256  // This is a class member so it can be accessed in publish feedback
257  rclcpp::Time action_start_time_;
258 
259  // Subscribe to the dynamic pose
260  nav2::Subscription<geometry_msgs::msg::PoseStamped>::SharedPtr dynamic_pose_sub_;
261 
262  // Publish the filtered dynamic pose
263  nav2::Publisher<geometry_msgs::msg::PoseStamped>::SharedPtr
264  filtered_dynamic_pose_pub_;
265 
266  // Latest message
267  geometry_msgs::msg::PoseStamped detected_dynamic_pose_;
268 
269  // Filtering of detected poses
270  std::unique_ptr<opennav_docking::PoseFilter> filter_;
271  double detection_timeout_;
272 
273  std::unique_ptr<nav2_util::TwistPublisher> vel_publisher_;
274  std::unique_ptr<nav2_util::OdomSmoother> odom_sub_;
275  typename FollowingActionServer::SharedPtr following_action_server_;
276 
277  std::unique_ptr<opennav_docking::Controller> controller_;
278 
279  std::shared_ptr<tf2_ros::Buffer> tf2_buffer_;
280  std::unique_ptr<tf2_ros::TransformListener> tf2_listener_;
281 };
282 
283 } // namespace opennav_following
284 
285 #endif // OPENNAV_FOLLOWING__FOLLOWING_SERVER_HPP_
A lifecycle node wrapper to enable common Nav2 needs such as manipulating parameters.
An action server wrapper to make applications simpler using Actions.
An action server which implements a dynamic following behavior.
bool checkAndWarnIfCancelled(typename nav2::SimpleActionServer< ActionT >::SharedPtr &action_server, const std::string &name)
Checks and logs warning if action canceled.
nav2::CallbackReturn on_shutdown(const rclcpp_lifecycle::State &state) override
Called when in shutdown state.
void followObject()
Main action callback method to complete following request.
virtual bool getFramePose(geometry_msgs::msg::PoseStamped &pose, const std::string &frame_id)
Get the pose of a specific frame in the fixed frame.
virtual bool approachObject(geometry_msgs::msg::PoseStamped &object_pose, const std::string &target_frame=std::string(""))
Use control law and perception to approach the object.
virtual bool getTrackingPose(geometry_msgs::msg::PoseStamped &pose, const std::string &frame_id)
Get the tracking pose based on the current tracking mode.
void publishFollowingFeedback(uint16_t state)
Publish feedback from a following action.
geometry_msgs::msg::PoseStamped getPoseAtDistance(const geometry_msgs::msg::PoseStamped &pose, double distance)
Get the pose at a distance in front of the input pose.
virtual bool getRefinedPose(geometry_msgs::msg::PoseStamped &pose)
Method to obtain the refined dynamic pose.
nav2::CallbackReturn on_deactivate(const rclcpp_lifecycle::State &state) override
Deactivate member variables.
void publishZeroVelocity()
Publish zero velocity at terminal condition.
void getPreemptedGoalIfRequested(typename std::shared_ptr< const typename ActionT::Goal > goal, const typename nav2::SimpleActionServer< ActionT >::SharedPtr &action_server)
Gets a preempted goal if immediately requested.
bool isGoalReached(const geometry_msgs::msg::PoseStamped &goal_pose)
Check if the goal has been reached.
rcl_interfaces::msg::SetParametersResult dynamicParametersCallback(std::vector< rclcpp::Parameter > parameters)
Callback executed when a parameter change is detected.
virtual bool rotateToObject(geometry_msgs::msg::PoseStamped &object_pose, const std::string &target_frame=std::string(""))
Rotate the robot to find the object again.
bool checkAndWarnIfPreempted(typename nav2::SimpleActionServer< ActionT >::SharedPtr &action_server, const std::string &name)
Checks and logs warning if action preempted.
nav2::CallbackReturn on_activate(const rclcpp_lifecycle::State &state) override
Activate member variables.
nav2::CallbackReturn on_configure(const rclcpp_lifecycle::State &state) override
Configure member variables.
nav2::CallbackReturn on_cleanup(const rclcpp_lifecycle::State &state) override
Reset member variables.
~FollowingServer()=default
A destructor for opennav_following::FollowingServer.
FollowingServer(const rclcpp::NodeOptions &options=rclcpp::NodeOptions())
A constructor for opennav_following::FollowingServer.