Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cli tools documentation #653

Merged
merged 17 commits into from
May 22, 2024
2 changes: 1 addition & 1 deletion tf2_ros/docs/mainpage.dox
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ List of exceptions thrown in this library:
- tf2::TimeoutException
- tf2::TransformException

For more information, see the tf2 tutorials: http://wiki.ros.org/tf2/Tutorials
For more information, see the tf2 tutorials: https://docs.ros.org/en/rolling/Tutorials/Intermediate/Tf2/Tf2-Main.html#

Or, get an <A HREF="http://wiki.ros.org/tf2/Tutorials/Migration/DataConversions">overview</A> of data type conversion methods in geometry_experimental packages.
*/
99 changes: 99 additions & 0 deletions tf2_ros/docs/source/cli_tools.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
Command Line Tools
==================

There are a number of tools to help you debug tf related problems. Most of them are located inside the bin directory or the scripts directory. This page gives a description of each tool, and explains what type of problems you can resolve with each tool.

Frame Poses
===========

1. tf2_echo
-----------
tf2_echo is the simplest tool to look at the numeric values of a specific transform. tf2_echo takes two arguments: the reference frame and the target frame. The output of tf2_echo is the target frame represented in the reference frame. E.g. to get the transformation from turtle1 to turtle2, type:
CursedRock17 marked this conversation as resolved.
Show resolved Hide resolved

.. code-block:: bash

ros2 run tf2_ros tf2_echo turtle1 turtle2

The expected output looks something like this:

.. code-block:: bash

At time 1253924110.083
- Translation: [-1.877, 0.415, 0.000]
- Rotation: in Quaternion [0.000, 0.000, -0.162, 0.987]
in RPY [0.000, -0.000, -0.325]
At time 1253924111.082
- Translation: [-1.989, 0.151, 0.000]
- Rotation: in Quaternion [0.000, 0.000, -0.046, 0.999]
in RPY [0.000, -0.000, -0.092]

2. RVIZ2
CursedRock17 marked this conversation as resolved.
Show resolved Hide resolved
--------
Run `rviz2` with `tf` enabled and begin viewing frames to see transforms

.. image:: images/rviz_screenshot.png
CursedRock17 marked this conversation as resolved.
Show resolved Hide resolved

TF tree introspection
======================
1. Viewing TF trees
---------------------
1.1 Save as a file by view_frames
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
View frames can generate a pdf file with a graphical representation of the complete tf tree. It also generates a number of time-related statistics. To run view frames, type:

.. code-block:: bash

ros2 run tf2_tools view_frames

In the current working folder, you should now have a file called "frames_$(data)_$(time).pdf". Open the file, you should see something like this:

.. image:: images/view_frames.png

Fields
^^^^^^^^^
* Recorded at time: shows the absolute timestamp when this graph was generated.
* Broadcaster: gives the name of the node that broadcasted the corresponding transform.
* Average rate: gives the average frequency at which the broadcaster sent out the corresponding transform. Note that this is an average, and does not guarantee that the broadcaster was sending transforms the whole time.
* Buffer length: tells you how many seconds of data is available in the tf buffer. When you run view frames without specifying a node, this buffer length should be about 5 seconds.
* Most recent transform: states how long ago the last transform was received. This is the time delay of a transform.
* Oldest transform: states how long ago the first transform was received.

1.2 Query a running node
^^^^^^^^^^^^^^^^^^^^^^^^
If a specific node is having trouble its exact data can be queried using the following command:

.. code-block:: bash

ros2 run tf2_tools view_frames --node=NODE_NAME

1.3 Dynamically introspect during runtime
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
`rqt_tf_tree <https://github.com/ros-visualization/rqt_tf_tree/tree/master>`_ provides a GUI to introspect tf tree during runtime.
CursedRock17 marked this conversation as resolved.
Show resolved Hide resolved

2. tf2_monitor
--------------
tf2_monitor can give you a lot of detailed information about a specific transformation you care about. The monitor will break down the chain between two frames into individual transforms, and provide statistics about timing, broadcasters, etc.

E.g. you want more information about the transformation between the frame "turtle1" and the frame "turtle2", simply type:

.. code-block:: bash

ros2 run tf2_ros tf2_monitor turtle1 turtle2

The output should look something like this:

.. code-block:: bash

RESULTS: for turtle1 to turtle2
Chain is: turtle2
Net delay avg = 0.00296015: max = 0.0239079

Frames:
Frame: turtle2, published by <no authority available>, Average Delay: 0.00385465, Max Delay: 0.00637698

Broadcasters:
Node: /turtle1_tf_broadcaster 40.01705 Hz, Average Delay: 0.0001427 Max Delay: 0.0003479
Node: /turtle2_tf_broadcaster 40.01705 Hz, Average Delay: 0.0001515 Max Delay: 0.00034

Each of these frames can be published by a different broadcaster.

4 changes: 2 additions & 2 deletions tf2_ros/docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.imgmath']
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.imgmath', 'sphinx_rtd_theme']

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
Expand Down Expand Up @@ -91,7 +91,7 @@

# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
html_theme = 'default'
html_theme = 'sphinx_rtd_theme'

# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
Expand Down
Binary file added tf2_ros/docs/source/images/rviz_screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tf2_ros/docs/source/images/view_frames.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
95 changes: 73 additions & 22 deletions tf2_ros/docs/source/index.rst
Original file line number Diff line number Diff line change
@@ -1,44 +1,95 @@
tf2_ros Overview
================
Overview
========

This is the Python API reference for the tf2_ros package.
This package contains the ROS 2 bindings for the tf2 library, for both Python and C++.

To broadcast transforms using ROS:
- Call :meth:`rospy.init` to initialize a node.
- Construct a :class:`tf2_ros.TransformBroadcaster`.
- Pass a :class:`geometry_msgs.TransformStamped` message to :meth:`tf2_ros.TransformBroadcaster.sendTransform`.
1.1 Broadcasting Transforms
---------------------------
* **tf2_ros::TransformBroadcaster()**, constructor
* **tf2_ros::TransformBroadcaster::sendTransform** to send transforms

- Alternatively, pass a vector of :class:`geometry_msgs.TransformStamped` messages.
Similarly static transforms can be sent by:

To listen for transforms using ROS:
- Construct an instance of a class that implements :class:`tf2_ros.BufferInterface`.
* **tf2_ros::StaticTransformBroadcaster()**, constructor,
* **tf2_ros::StaticTransformBroadcaster::sendTransform** to send static transforms

- :class:`tf2_ros.Buffer` is the standard implementation which offers a tf2_frames service that can respond to requests with a :class:`tf2_msgs.FrameGraph`.
- :class:`tf2_ros.BufferClient` uses an :class:`actionlib.SimpleActionClient` to wait for the requested transform to become available.
1.2 Using Published Transforms
------------------------------
For most purposes using tf2_ros will be done using tf2_ros::Buffer. It's main public API is defined by tf2_ros::BufferInterface. Typically it will be populated using a tf2_ros::TransformListener which subscribes to the appropriate topics.

- Pass the :class:`tf2_ros.Buffer` to the constructor of :class:`tf2_ros.TransformListener`.
- Optionally, pass a :class:`ros.NodeHandle` (otherwise TransformListener will connect to the node for the process).
- Optionally, specify if the TransformListener runs in its own thread or not.
* **tf2_ros::Buffer::transform** is the main method for applying transforms.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these still create links to the Doxygen content?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now the loacl links are done through rst which puts them next to what we're trying to list. I assumed this would be the easiest thing to do when it came to overall documentation.
Here's a video of what it should look like:

Geometry2_Docs.mov

To recreate do the following in the terminal

  1. Clone the repo
  2. cd tf2_ros/docs
  3. make html
  4. rosdoc2 build --package-path ./..
  5. rosdoc2 open ./docs_output/tf2_ros/index.html
  6. Run it on the web so something like python3 -m http.server will work for localhost

Are packages like rosdoc2, exhale, and breathe able to run on the docs, or is this overengineered?

* **canTransform** allows to know if a transform is available
* **lookupTransform** is a lower level method which returns the transform between two coordinate frames. This method is the core functionality of the tf2 library.
* **getFrames** is a service method providing the frames in the graph as a yaml tree

- Use :meth:`tf2_ros.BufferInterface.transform` to apply a transform on the tf server to an input frame.
- Or, check if a transform is available with :meth:`tf2_ros.BufferInterface.can_transform`.
- Then, call :meth:`tf2_ros.BufferInterface.lookup_transform` to get the transform between two frames.
1.3 Filtering Transforms
------------------------

For more information, see the tf2 tutorials: http://wiki.ros.org/tf2/Tutorials
tf2_ros provides a feature which allows to pass only the messages once there is transform data available. This follows the pattern from the message_filters package. Here is a brief list of functions that the user is most likely to use.

Or, get an `overview`_ of data type conversion methods in geometry_experimental packages.
* **tf2_ros::MessageFilter()**, constructor

See http://wiki.ros.org/tf2/Tutorials for more detailed usage.
* **connectInput()** allows to connect filters together

.. _overview: http://wiki.ros.org/tf2/Tutorials/Migration/DataConversions
* **setTargetFrame()** set the frame you want to be able to transform to before getting a message callback

* **setTargetFrames()** set the frames you want to be able to transform to before getting a message callback

* **setTolerance()** specifies the time tolerance for the transform data

* **clear()** flushes the message queue

* **setQueueSize()** creates a maximum number of messages in the queue

1.4 Exceptions
--------------

Here is the list of exceptions that can be thrown by tf2_ros and are inherited from tf2.

* tf2::ConnectivityException

* tf2::LookupException

* tf2::ExtrapolationException

* tf2::InvalidArgumentException

* tf2::TimeoutException

* tf2::TransformException

1.5 Tools
---------

1.5.1 static_transform_publisher
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

static_transform_publisher x y z yaw pitch roll frame_id child_frame_id
CursedRock17 marked this conversation as resolved.
Show resolved Hide resolved

Publish a static coordinate transform to tf2 using an x/y/z offset in meters and yaw/pitch/roll in radians. (yaw is rotation about Z, pitch is rotation about Y, and roll is rotation about X).

static_transform_publisher x y z qx qy qz qw frame_id child_frame_id
CursedRock17 marked this conversation as resolved.
Show resolved Hide resolved

Publish a static coordinate transform to tf2 using an x/y/z offset in meters and quaternion.
Unlike in tf, there is no period argument, and a latched topic is used.

static_transform_publisher is designed both as a command-line tool for manual use, as well as for use within roslaunch files for setting static transforms. For example:

.. code-block:: yaml

<launch>
<node pkg="tf2_ros" type="static_transform_publisher" name="link1_broadcaster" args="1 0 0 0 0 0 1 link1_parent link1" />
</launch>

Classes and Exceptions
======================

.. toctree::
:maxdepth: 2

self
tf2_ros
cli_tools


Indices and tables
Expand Down
10 changes: 5 additions & 5 deletions tf2_ros/docs/source/tf2_ros.rst
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
tf_ros2 Python API
tf2_ros Python API
==================

Exceptions
Expand All @@ -14,7 +14,7 @@ Exceptions
# do some tf2 work
except tf2.TransformException:
print "some tf2 exception happened"


.. exception:: tf2.ConnectivityException

Expand All @@ -27,8 +27,8 @@ Exceptions
Raised when a tf method has attempted to access a frame, but
the frame is not in the graph.
The most common reason for this is that the frame is not
being published, or a parent frame was not set correctly
causing the tree to be broken.
being published, or a parent frame was not set correctly
causing the tree to be broken.

.. exception:: tf2.ExtrapolationException

Expand All @@ -39,7 +39,7 @@ Exceptions
.. exception:: tf2.InvalidArgumentException

subclass of :exc:`TransformException`.
Raised when the arguments to the method are called improperly formed. An example of why this might be raised is if an argument is nan.
Raised when the arguments to the method are called improperly formed. An example of why this might be raised is if an argument is nan.

.. autoexception:: tf2_ros.buffer_interface.TypeException

Expand Down