Nav2 Navigation Stack - lyrical  lyrical
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/duration.hpp"
31 #include "rclcpp/logger.hpp"
32 #include "rclcpp/logging.hpp"
33 #include "rclcpp/node.hpp"
34 #include "nav2_ros_common/node_utils.hpp"
35 
36 namespace nav2_util
37 {
38 
45 {
46 public:
54  template<typename NodeT>
55  explicit OdomSmoother(
56  const NodeT & parent,
57  double filter_duration = 0.3,
58  const std::string & odom_topic = "odom")
59  : odom_history_duration_(rclcpp::Duration::from_seconds(filter_duration))
60  {
61  // Could be using a user rclcpp::Node, so need to use the Nav2 factory to create the
62  // subscription to convert nav2::LifecycleNode, rclcpp::Node or rclcpp_lifecycle::LifecycleNode
63  odom_sub_ = nav2::interfaces::create_subscription<nav_msgs::msg::Odometry>(
64  parent, odom_topic,
65  std::bind(&OdomSmoother::odomCallback, this, std::placeholders::_1));
66 
67  odom_cumulate_.twist.twist.linear.x = 0;
68  odom_cumulate_.twist.twist.linear.y = 0;
69  odom_cumulate_.twist.twist.linear.z = 0;
70  odom_cumulate_.twist.twist.angular.x = 0;
71  odom_cumulate_.twist.twist.angular.y = 0;
72  odom_cumulate_.twist.twist.angular.z = 0;
73  }
74 
79  inline geometry_msgs::msg::Twist getTwist()
80  {
81  std::lock_guard<std::mutex> lock(odom_mutex_);
82  if (!received_odom_) {
83  RCLCPP_ERROR(
84  rclcpp::get_logger("OdomSmoother"),
85  "OdomSmoother has not received any data yet, returning empty Twist");
86  geometry_msgs::msg::Twist twist;
87  return twist;
88  }
89  return vel_smooth_.twist;
90  }
91 
96  inline geometry_msgs::msg::TwistStamped getTwistStamped()
97  {
98  std::lock_guard<std::mutex> lock(odom_mutex_);
99  if (!received_odom_) {
100  RCLCPP_ERROR(
101  rclcpp::get_logger("OdomSmoother"),
102  "OdomSmoother has not received any data yet, returning empty Twist");
103  geometry_msgs::msg::TwistStamped twist_stamped;
104  return twist_stamped;
105  }
106  return vel_smooth_;
107  }
108 
113  inline geometry_msgs::msg::Twist getRawTwist()
114  {
115  std::lock_guard<std::mutex> lock(odom_mutex_);
116  if (!received_odom_) {
117  RCLCPP_ERROR(
118  rclcpp::get_logger("OdomSmoother"),
119  "OdomSmoother has not received any data yet, returning empty Twist");
120  geometry_msgs::msg::Twist twist;
121  return twist;
122  }
123  return odom_history_.back().twist.twist;
124  }
125 
130  inline geometry_msgs::msg::TwistStamped getRawTwistStamped()
131  {
132  std::lock_guard<std::mutex> lock(odom_mutex_);
133  geometry_msgs::msg::TwistStamped twist_stamped;
134  if (!received_odom_) {
135  RCLCPP_ERROR(
136  rclcpp::get_logger("OdomSmoother"),
137  "OdomSmoother has not received any data yet, returning empty Twist");
138  return twist_stamped;
139  }
140  twist_stamped.header = odom_history_.back().header;
141  twist_stamped.twist = odom_history_.back().twist.twist;
142  return twist_stamped;
143  }
144 
145 protected:
150  void odomCallback(const nav_msgs::msg::Odometry::ConstSharedPtr & msg);
151 
155  void updateState();
156 
157  bool received_odom_{false};
158  nav2::Subscription<nav_msgs::msg::Odometry>::SharedPtr odom_sub_;
159  nav_msgs::msg::Odometry odom_cumulate_;
160  geometry_msgs::msg::TwistStamped vel_smooth_;
161  std::mutex odom_mutex_;
162 
163  rclcpp::Duration odom_history_duration_;
164  std::deque<nav_msgs::msg::Odometry> odom_history_;
165 };
166 
167 } // namespace nav2_util
168 
169 #endif // NAV2_UTIL__ODOMETRY_UTILS_HPP_
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.
void odomCallback(const nav_msgs::msg::Odometry::ConstSharedPtr &msg)
Callback of odometry subscriber to process.
geometry_msgs::msg::TwistStamped getTwistStamped()
Get twist stamped msg from smoother.