21 #include "tf2/convert.hpp"
22 #include "tf2/utils.hpp"
23 #include "nav2_ros_common/tf2_factories.hpp"
24 #include "tf2_geometry_msgs/tf2_geometry_msgs.hpp"
26 #include "nav2_util/robot_utils.hpp"
27 #include "rclcpp/logger.hpp"
32 bool lookupTransformWithStalenessCheck(
33 nav2::TransformBuffer & tf_buffer,
34 const std::string & target_frame,
35 const std::string & source_frame,
36 const rclcpp::Time & current_time,
37 double staleness_threshold,
38 geometry_msgs::msg::TransformStamped & transform)
40 if (target_frame == source_frame) {
41 geometry_msgs::msg::TransformStamped identity;
42 identity.header.frame_id = target_frame;
43 identity.header.stamp = current_time;
44 identity.child_frame_id = source_frame;
45 identity.transform.rotation.w = 1.0;
50 geometry_msgs::msg::TransformStamped latest_transform;
52 latest_transform = tf_buffer.lookupTransform(
53 target_frame, source_frame, tf2::TimePointZero);
54 }
catch (
const tf2::TransformException & ex) {
56 rclcpp::get_logger(
"lookupTransformWithStalenessCheck"),
57 "Failed to get transform: %s", ex.what());
61 const bool has_timestamp =
62 latest_transform.header.stamp.sec != 0 || latest_transform.header.stamp.nanosec != 0;
63 if (staleness_threshold > 0.0 && has_timestamp) {
64 const auto transform_time = rclcpp::Time(
65 latest_transform.header.stamp, current_time.get_clock_type());
66 const double transform_age = (current_time - transform_time).seconds();
67 if (transform_age > staleness_threshold) {
69 rclcpp::get_logger(
"lookupTransformWithStalenessCheck"),
70 "Transform from frame '%s' to frame '%s' is stale: age %fs exceeds threshold %fs",
71 source_frame.c_str(), target_frame.c_str(), transform_age, staleness_threshold);
75 transform = latest_transform;
79 geometry_msgs::msg::PoseStamped transformToPoseStamped(
80 const geometry_msgs::msg::TransformStamped & transform)
82 geometry_msgs::msg::PoseStamped pose;
83 pose.header = transform.header;
84 pose.pose.position.x = transform.transform.translation.x;
85 pose.pose.position.y = transform.transform.translation.y;
86 pose.pose.position.z = transform.transform.translation.z;
87 pose.pose.orientation = transform.transform.rotation;
91 geometry_msgs::msg::TransformStamped poseToTransformStamped(
92 const geometry_msgs::msg::PoseStamped & pose,
const std::string & child_frame)
94 geometry_msgs::msg::TransformStamped transform;
95 transform.header = pose.header;
96 transform.child_frame_id = child_frame;
97 transform.transform.translation.x = pose.pose.position.x;
98 transform.transform.translation.y = pose.pose.position.y;
99 transform.transform.translation.z = pose.pose.position.z;
100 transform.transform.rotation = pose.pose.orientation;
105 nav2::TransformBuffer & tf_buffer,
106 const std::string & target_frame,
107 const std::string & source_frame,
108 const rclcpp::Time & current_time,
109 double staleness_threshold,
110 geometry_msgs::msg::PoseStamped & pose)
112 geometry_msgs::msg::TransformStamped transform;
113 if (lookupTransformWithStalenessCheck(
114 tf_buffer, target_frame, source_frame, current_time, staleness_threshold, transform))
116 pose = transformToPoseStamped(transform);
123 geometry_msgs::msg::PoseStamped & global_pose,
124 nav2::TransformBuffer & tf_buffer,
const std::string global_frame,
125 const std::string robot_frame,
const double transform_timeout,
126 const rclcpp::Time stamp)
128 tf2::toMsg(tf2::Transform::getIdentity(), global_pose.pose);
129 global_pose.header.frame_id = robot_frame;
130 global_pose.header.stamp = stamp;
132 return transformPoseInTargetFrame(
133 global_pose, global_pose, tf_buffer, global_frame, transform_timeout);
136 bool transformPoseInTargetFrame(
137 const geometry_msgs::msg::PoseStamped & input_pose,
138 geometry_msgs::msg::PoseStamped & transformed_pose,
139 nav2::TransformBuffer & tf_buffer,
const std::string target_frame,
140 const double transform_timeout)
142 static rclcpp::Logger logger = rclcpp::get_logger(
"transformPoseInTargetFrame");
144 if (input_pose.header.frame_id == target_frame) {
145 transformed_pose = input_pose;
150 transformed_pose = tf_buffer.transform(
151 input_pose, target_frame,
152 tf2::durationFromSec(transform_timeout));
154 }
catch (tf2::LookupException & ex) {
157 "No Transform available Error looking up target frame: %s\n", ex.what());
158 }
catch (tf2::ConnectivityException & ex) {
161 "Connectivity Error looking up target frame: %s\n", ex.what());
162 }
catch (tf2::ExtrapolationException & ex) {
165 "Extrapolation Error looking up target frame: %s\n", ex.what());
166 }
catch (tf2::TimeoutException & ex) {
169 "Transform timeout with tolerance: %.4f", transform_timeout);
170 }
catch (tf2::TransformException & ex) {
172 logger,
"Failed to transform from %s to %s",
173 input_pose.header.frame_id.c_str(), target_frame.c_str());
180 const std::string & source_frame_id,
181 const std::string & target_frame_id,
182 const tf2::Duration & transform_tolerance,
183 const nav2::TransformBuffer::SharedPtr tf_buffer,
184 geometry_msgs::msg::TransformStamped & transform_msg)
186 if (source_frame_id == target_frame_id) {
193 transform_msg = tf_buffer->lookupTransform(
194 target_frame_id, source_frame_id,
195 tf2::TimePointZero, transform_tolerance);
196 }
catch (tf2::TransformException & e) {
198 rclcpp::get_logger(
"getTransform"),
199 "Failed to get \"%s\"->\"%s\" frame transform: %s",
200 source_frame_id.c_str(), target_frame_id.c_str(), e.what());
207 const std::string & source_frame_id,
208 const std::string & target_frame_id,
209 const tf2::Duration & transform_tolerance,
210 const nav2::TransformBuffer::SharedPtr tf_buffer,
211 tf2::Transform & tf2_transform)
213 tf2_transform.setIdentity();
214 geometry_msgs::msg::TransformStamped transform;
215 if (getTransform(source_frame_id, target_frame_id, transform_tolerance, tf_buffer, transform)) {
217 tf2::fromMsg(transform.transform, tf2_transform);
224 const std::string & source_frame_id,
225 const rclcpp::Time & source_time,
226 const std::string & target_frame_id,
227 const rclcpp::Time & target_time,
228 const std::string & fixed_frame_id,
229 const tf2::Duration & transform_tolerance,
230 const nav2::TransformBuffer::SharedPtr tf_buffer,
231 geometry_msgs::msg::TransformStamped & transform_msg)
236 transform_msg = tf_buffer->lookupTransform(
237 target_frame_id, target_time,
238 source_frame_id, source_time,
239 fixed_frame_id, transform_tolerance);
240 }
catch (tf2::TransformException & ex) {
242 rclcpp::get_logger(
"getTransform"),
243 "Failed to get \"%s\"->\"%s\" frame transform: %s",
244 source_frame_id.c_str(), target_frame_id.c_str(), ex.what());
252 const std::string & source_frame_id,
253 const rclcpp::Time & source_time,
254 const std::string & target_frame_id,
255 const rclcpp::Time & target_time,
256 const std::string & fixed_frame_id,
257 const tf2::Duration & transform_tolerance,
258 const nav2::TransformBuffer::SharedPtr tf_buffer,
259 tf2::Transform & tf2_transform)
261 geometry_msgs::msg::TransformStamped transform;
262 tf2_transform.setIdentity();
264 source_frame_id, source_time, target_frame_id, target_time, fixed_frame_id,
265 transform_tolerance, tf_buffer, transform))
268 tf2::fromMsg(transform.transform, tf2_transform);
275 bool validateTwist(
const geometry_msgs::msg::Twist & msg)
277 if (std::isinf(msg.linear.x) || std::isnan(msg.linear.x)) {
281 if (std::isinf(msg.linear.y) || std::isnan(msg.linear.y)) {
285 if (std::isinf(msg.linear.z) || std::isnan(msg.linear.z)) {
289 if (std::isinf(msg.angular.x) || std::isnan(msg.angular.x)) {
293 if (std::isinf(msg.angular.y) || std::isnan(msg.angular.y)) {
297 if (std::isinf(msg.angular.z) || std::isnan(msg.angular.z)) {