#################################### ##FILL ME IN #################################### ## for a custom note with links: ## note =This tutorial assumes you have completed the writing a tf broadcaster tutorial [[tf/Tutorials/Writing a tf broadcaster (Python)|(Python)]] [[tf/Tutorials/Writing a tf broadcaster (C++)|(C++)]] ## for the canned note of "This tutorial assumes that you have completed the previous tutorials:" just add the links ## note.0= ## descriptive title for the tutorial ## title =Writing a tf listener (C++) ## multi-line description to be displayed in search ## description = This tutorial teaches you how to use tf to get access to frame transformations. ## the next tutorial description (optional) ## next = Adding a frame ## links to next tutorial (optional) ## next.0.link=[[tf/Tutorials/Adding a frame (C++)|(C++)]] ## next.1.link= ## what level user is this tutorial for ## level= BeginnerCategory ## keywords = #################################### <> {{{#!wiki caution tf is deprecated in favor of [[tf2]]. [[tf2]] provides a superset of the functionality of tf and is actually now the implementation under the hood. If you're just learning now it's strongly recommended to use the [[tf2/Tutorials]] instead. }}} <> <> ##introstart In the previous tutorials we created a tf broadcaster to publish the pose of a turtle to tf. In this tutorial we'll create a tf listener to start using tf. == How to create a tf listener == Let's first create the source files. Go to the package we created in the previous tutorial: {{{ $ roscd learning_tf }}} ##introend === The Code === Fire up your favorite editor and paste the following code into a new file called `src/turtle_tf_listener.cpp`. <> It's important to note that the above code is essential to finish the tf tutorials and it will '''NOT''' compile on '''ROS Hydro''', due to a slight change in the naming of certain messages and topics. The ''turtlesim/Velocity.h'' header is not used anymore, it has been replaced by ''geometry_msgs/Twist.h''. Furthermore, the topic ''/turtle/command_velocity'' is now called ''/turtle/cmd_vel''. In light of this, a few changes are necessary to make it work: <> If you get an error "Lookup would require extrapolation into the past" while running, you can try this alternative code to call the listener: {{{ try { listener.waitForTransform(destination_frame, original_frame, ros::Time(0), ros::Duration(10.0) ); listener.lookupTransform(destination_frame, original_frame, ros::Time(0), transform); } catch (tf::TransformException ex) { ROS_ERROR("%s",ex.what()); } }}} === The Code Explained === Now, let's take a look at the code that is relevant to publishing the turtle pose to tf. <> The tf package provides an implementation of a `TransformListener` to help make the task of receiving transforms easier. To use the `TransformListener`, we need to include the `tf/transform_listener.h` header file. <> Here, we create a `TransformListener` object. Once the listener is created, it starts receiving tf transformations over the wire, and buffers them for up to 10 seconds. The `TransformListener` object should be scoped to persist otherwise it's cache will be unable to fill and almost every query will fail. A common method is to make the `TransformListener` object a member variable of a class. <> Here, the real work is done, we query the listener for a specific transformation. Let's take a look at the four arguments: 1. We want the transform from frame /turtle1 to frame /turtle2. 2. The time at which we want to transform. Providing `ros::Time(0)` will just get us the latest available transform. 3. The object in which we store the resulting transform. All this is wrapped in a `try-catch` block to catch possible exceptions. <> Here, the transform is used to calculate new linear and angular velocities for turtle2, based on its distance and angle from turtle1. The new velocity is published in the topic "turtle2/cmd_vel" and the sim will use that to update turtle2's movement. == Running the listener == Now that we created the code, lets compile it first. Open the `CMakeLists.txt` file, and add the following line on the bottom: {{{{#!wiki buildsystem catkin {{{ add_executable(turtle_tf_listener src/turtle_tf_listener.cpp) target_link_libraries(turtle_tf_listener ${catkin_LIBRARIES}) }}} Build your package at the top folder of your `catkin` workspace: {{{ $ catkin_make }}} If everything went well, you should have a binary file called `turtle_tf_listener` in your `devel/lib/learning_tf` folder. }}}} {{{{#!wiki buildsystem rosbuild {{{ rosbuild_add_executable(turtle_tf_listener src/turtle_tf_listener.cpp) }}} Build your package: {{{ $ make }}} If everything went well, you should have a binary file called `turtle_tf_listener` in your `bin` folder. }}}} If so, we're ready add it the launch file for this demo. With your text editor, open the launch file called `start_demo.launch`, and merge the node block below inside the `` block: {{{ ... }}} ##checkingstart First, make sure you stopped the launch file from the previous tutorial (use ctrl-c). Now you're ready to start your full turtle demo: {{{ $ roslaunch learning_tf start_demo.launch }}} You should see the turtlesim with '''two''' turtles. == Checking the results == To see if things work, simply drive around the first turtle using the arrow keys (make sure your terminal window is active, not your simulator window), and you'll see the second turtle following the first one! When the turtlesim starts up you may see: . {{{ [ERROR] 1253915565.300572000: Frame id /turtle2 does not exist! When trying to transform between /turtle1 and /turtle2. [ERROR] 1253915565.401172000: Frame id /turtle2 does not exist! When trying to transform between /turtle1 and /turtle2. }}} This happens because our listener is trying to compute the transform before messages about turtle 2 have been received because it takes a little time to spawn in turtlesim and start broadcasting a tf frame. Now you're ready to move on to the next tutorial, where you'll learn how to add a frame [[tf/Tutorials/Adding a frame (Python)|(Python)]] [[tf/Tutorials/Adding a frame (C++)|(C++)]] ##checkingend ## AUTOGENERATED DO NOT DELETE ## TutorialCategory ## TutorialTurtlesim ## C++Category ## LearningCategory