ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

[ROS2 Foxy] lookupTransform target doesn't exist despite using waitForTransform

asked 2021-09-29 03:27:41 -0600

morten gravatar image

updated 2021-09-29 03:35:33 -0600

For a node I am writing I need to lookup a static transform from a sensor frame, gps, to the base_link. I do this in the initialization and save it as a private member of the node class.

This is resulting in

morten@thinkpad:~/ros2_ws$ ros2 run gps velocity_estimation_node 
[ERROR] [1632903136.082895496] [gps_transform]: couldn't wait for gps message
[INFO] [1632903136.087996564] [gps_transform]: Waiting for transform from gps to base_link
terminate called after throwing an instance of 'tf2::LookupException'
  what():  "base_link" passed to lookupTransform argument target_frame does not exist.

I can confirm that the relevant frames exist by ros2 run tf2_tools view_frames.py: frames.pdf

I can also check if the transform exists by ros2 run tf2_ros tf2_echo gps base_link, but this results in strange behavior as well despite showing the correct transformation:

morten@thinkpad:~/ros2_ws$ ros2 run tf2_ros tf2_echo gps base_link
[INFO] [1632903501.716568775] [tf2_echo]: Waiting for transform gps ->  base_link: Invalid frame ID "gps" passed to canTransform argument target_frame - frame does not exist
At time 0.0
- Translation: [-1.100, 0.000, -3.000]
- Rotation: in Quaternion [0.000, 0.000, 0.000, 1.000]

The frames originate from a urdf file which is called from a separate launch file, the frames can also be seen clearly in rviz. An abbreviated version of my code for getting the transform is

...
public:
    Estimator() : Node("gps_transform"){...
        tf_buffer_ = std::make_unique<tf2_ros::Buffer>(this->get_clock());
        transform_listener = std::make_shared<tf2_ros::TransformListener>(*tf_buffer_);
        auto timer_interface = std::make_shared<tf2_ros::CreateTimerROS>(
                this->get_node_base_interface(), this->get_node_timers_interface());
        tf_buffer_->setCreateTimerInterface(timer_interface);

        RCLCPP_INFO(this->get_logger(), "Waiting for transform from %s to %s",
                    "gps", "base_link");
        tf_buffer_->waitForTransform("base_link", "gps", this->now(),
                                     rclcpp::Duration(10),
                                     std::bind(&Estimator::tf_cb, this));
    }
private:
    void tf_cb(){
        tf_buffer_->lookupTransform("base_link", "gps", tf2::TimePointZero);
    }...

  std::shared_ptr<tf2_ros::TransformListener> transform_listener_{nullptr};
  std::unique_ptr<tf2_ros::Buffer> tf_buffer_;
  geometry_msgs::msg::TransformStamped gps_to_baselink_;
};

Note: Using ROS2 Foxy on Ubuntu 20.04 LTS.

edit retag flag offensive close merge delete

Comments

I'm not sure if this will help but just take a look at this tutorial: https://docs.ros.org/en/galactic/Tuto...

pmuthu2s gravatar image pmuthu2s  ( 2021-09-29 04:46:03 -0600 )edit

I should've noted in the original post, given that this is a static transform I would prefer not having to look it up in the callback.

Also just because I figure this is worth knowing how to use the waitForTransform functionality and as far as I can see, it is not well documented/demonstrated for ros2.

morten gravatar image morten  ( 2021-09-29 04:49:44 -0600 )edit

1 Answer

Sort by ยป oldest newest most voted
0

answered 2023-02-16 17:19:20 -0600

AndyZe gravatar image

updated 2023-02-16 17:20:37 -0600

I found a workaround after about 8 hours of tears. The commented code is the first attempt that did not work.

              import asyncio
...
                tf_future = self.tf_buffer.wait_for_transform_async(
                    target_frame=pose_stamped.header.frame_id,
                    source_frame=reference_frame,
                    time=rclpy.time.Time()
                )

                rclpy.spin_until_future_complete(self, tf_future)
                print("Got it!")

#                world_to_reference_transform = self.tf_buffer.lookup_transform(
#                    pose_stamped.header.frame_id,
#                    reference_frame,
#                    rclpy.time.Time(),
#                    timeout=rclpy.duration.Duration(seconds=5.0))

                world_to_reference_transform = asyncio.run(self.tf_buffer.lookup_transform_async(
                    pose_stamped.header.frame_id,
                    reference_frame,
                    rclpy.time.Time()
                ))
edit flag offensive delete link more

Question Tools

3 followers

Stats

Asked: 2021-09-29 03:27:41 -0600

Seen: 1,500 times

Last updated: Feb 16 '23