Nav2 Navigation Stack - rolling  main
ROS 2 Navigation Stack
odometry_utils.hpp
1 // Copyright (c) 2018 Intel Corporation
2 // Copyright (c) 2020 Sarthak Mittal
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 NAV2_UTIL__ODOMETRY_UTILS_HPP_
17 #define NAV2_UTIL__ODOMETRY_UTILS_HPP_
18 
19 #include <cmath>
20 #include <chrono>
21 #include <memory>
22 #include <mutex>
23 #include <string>
24 #include <deque>
25 
26 #include "geometry_msgs/msg/twist.hpp"
27 #include "geometry_msgs/msg/twist_stamped.hpp"
28 #include "nav_msgs/msg/odometry.hpp"
29 #include "nav2_ros_common/lifecycle_node.hpp"
30 #include "rclcpp/rclcpp.hpp"
31 #include "nav2_ros_common/node_utils.hpp"
32 
33 namespace nav2_util
34 {
35 
42 {
43 public:
51  template<typename NodeT>
52  explicit OdomSmoother(
53  const NodeT & parent,
54  double filter_duration = 0.3,
55  const std::string & odom_topic = "odom")
56  : odom_history_duration_(rclcpp::Duration::from_seconds(filter_duration))
57  {
58  // Could be using a user rclcpp::Node, so need to use the Nav2 factory to create the
59  // subscription to convert nav2::LifecycleNode, rclcpp::Node or rclcpp_lifecycle::LifecycleNode
60  odom_sub_ = nav2::interfaces::create_subscription<nav_msgs::msg::Odometry>(
61  parent, odom_topic,
62  std::bind(&OdomSmoother::odomCallback, this, std::placeholders::_1));
63 
64  odom_cumulate_.twist.twist.linear.x = 0;
65  odom_cumulate_.twist.twist.linear.y = 0;
66  odom_cumulate_.twist.twist.linear.z = 0;
67  odom_cumulate_.twist.twist.angular.x = 0;
68  odom_cumulate_.twist.twist.angular.y = 0;
69  odom_cumulate_.twist.twist.angular.z = 0;
70  }
71 
76  inline geometry_msgs::msg::Twist getTwist()
77  {
78  std::lock_guard<std::mutex> lock(odom_mutex_);
79  if (!received_odom_) {
80  RCLCPP_ERROR(rclcpp::get_logger("OdomSmoother"),
81  "OdomSmoother has not received any data yet, returning empty Twist");
82  geometry_msgs::msg::Twist twist;
83  return twist;
84  }
85  return vel_smooth_.twist;
86  }
87 
92  inline geometry_msgs::msg::TwistStamped getTwistStamped()
93  {
94  std::lock_guard<std::mutex> lock(odom_mutex_);
95  if (!received_odom_) {
96  RCLCPP_ERROR(rclcpp::get_logger("OdomSmoother"),
97  "OdomSmoother has not received any data yet, returning empty Twist");
98  geometry_msgs::msg::TwistStamped twist_stamped;
99  return twist_stamped;
100  }
101  return vel_smooth_;
102  }
103 
108  inline geometry_msgs::msg::Twist getRawTwist()
109  {
110  std::lock_guard<std::mutex> lock(odom_mutex_);
111  if (!received_odom_) {
112  RCLCPP_ERROR(rclcpp::get_logger("OdomSmoother"),
113  "OdomSmoother has not received any data yet, returning empty Twist");
114  geometry_msgs::msg::Twist twist;
115  return twist;
116  }
117  return odom_history_.back().twist.twist;
118  }
119 
124  inline geometry_msgs::msg::TwistStamped getRawTwistStamped()
125  {
126  std::lock_guard<std::mutex> lock(odom_mutex_);
127  geometry_msgs::msg::TwistStamped twist_stamped;
128  if (!received_odom_) {
129  RCLCPP_ERROR(rclcpp::get_logger("OdomSmoother"),
130  "OdomSmoother has not received any data yet, returning empty Twist");
131  return twist_stamped;
132  }
133  twist_stamped.header = odom_history_.back().header;
134  twist_stamped.twist = odom_history_.back().twist.twist;
135  return twist_stamped;
136  }
137 
138 protected:
143  void odomCallback(nav_msgs::msg::Odometry::SharedPtr msg);
144 
148  void updateState();
149 
150  bool received_odom_{false};
151  nav2::Subscription<nav_msgs::msg::Odometry>::SharedPtr odom_sub_;
152  nav_msgs::msg::Odometry odom_cumulate_;
153  geometry_msgs::msg::TwistStamped vel_smooth_;
154  std::mutex odom_mutex_;
155 
156  rclcpp::Duration odom_history_duration_;
157  std::deque<nav_msgs::msg::Odometry> odom_history_;
158 };
159 
160 } // namespace nav2_util
161 
162 #endif // NAV2_UTIL__ODOMETRY_UTILS_HPP_
void odomCallback(nav_msgs::msg::Odometry::SharedPtr msg)
Callback of odometry subscriber to process.
void updateState()
Update internal state of the smoother after getting new data.
geometry_msgs::msg::TwistStamped getRawTwistStamped()
Get raw twist stamped msg from smoother (without smoothing)
geometry_msgs::msg::Twist getRawTwist()
Get raw twist msg from smoother (without smoothing)
OdomSmoother(const NodeT &parent, double filter_duration=0.3, const std::string &odom_topic="odom")
Overloadded Constructor for nav_util::LifecycleNode parent that subscribes to an Odometry topic.
geometry_msgs::msg::Twist getTwist()
Get twist msg from smoother.
geometry_msgs::msg::TwistStamped getTwistStamped()
Get twist stamped msg from smoother.