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/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(
81  rclcpp::get_logger("OdomSmoother"),
82  "OdomSmoother has not received any data yet, returning empty Twist");
83  geometry_msgs::msg::Twist twist;
84  return twist;
85  }
86  return vel_smooth_.twist;
87  }
88 
93  inline geometry_msgs::msg::TwistStamped getTwistStamped()
94  {
95  std::lock_guard<std::mutex> lock(odom_mutex_);
96  if (!received_odom_) {
97  RCLCPP_ERROR(
98  rclcpp::get_logger("OdomSmoother"),
99  "OdomSmoother has not received any data yet, returning empty Twist");
100  geometry_msgs::msg::TwistStamped twist_stamped;
101  return twist_stamped;
102  }
103  return vel_smooth_;
104  }
105 
110  inline geometry_msgs::msg::Twist getRawTwist()
111  {
112  std::lock_guard<std::mutex> lock(odom_mutex_);
113  if (!received_odom_) {
114  RCLCPP_ERROR(
115  rclcpp::get_logger("OdomSmoother"),
116  "OdomSmoother has not received any data yet, returning empty Twist");
117  geometry_msgs::msg::Twist twist;
118  return twist;
119  }
120  return odom_history_.back().twist.twist;
121  }
122 
127  inline geometry_msgs::msg::TwistStamped getRawTwistStamped()
128  {
129  std::lock_guard<std::mutex> lock(odom_mutex_);
130  geometry_msgs::msg::TwistStamped twist_stamped;
131  if (!received_odom_) {
132  RCLCPP_ERROR(
133  rclcpp::get_logger("OdomSmoother"),
134  "OdomSmoother has not received any data yet, returning empty Twist");
135  return twist_stamped;
136  }
137  twist_stamped.header = odom_history_.back().header;
138  twist_stamped.twist = odom_history_.back().twist.twist;
139  return twist_stamped;
140  }
141 
142 protected:
147  void odomCallback(const nav_msgs::msg::Odometry::ConstSharedPtr & msg);
148 
152  void updateState();
153 
154  bool received_odom_{false};
155  nav2::Subscription<nav_msgs::msg::Odometry>::SharedPtr odom_sub_;
156  nav_msgs::msg::Odometry odom_cumulate_;
157  geometry_msgs::msg::TwistStamped vel_smooth_;
158  std::mutex odom_mutex_;
159 
160  rclcpp::Duration odom_history_duration_;
161  std::deque<nav_msgs::msg::Odometry> odom_history_;
162 };
163 
164 } // namespace nav2_util
165 
166 #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.