tf API Overview: Data Types | Transformations and Frames | Broadcasting Transforms | Using Published Transforms | Exceptions

Coodinate Frames, Transforms, and TF

References

An excellent reference for coordinate frames and transforms is the first chapter of John Craig's book, Introduction to Robotics [1986, 1989]. We follow his conventions for transform and point indices.

Geometric objects in tf are represented by tf types, which are equivalent to corresponding bullet types; see tf data types. Bullet class references for transforms and quaternions are handy.

Frames and Points

A frame is a coordinate system. Coordinate systems in ROS are always in 3D, and are right-handed, with X forward, Y left, and Z up.

Points within a frame are represented using tf::Point, which is equivalent to the bullet type btVector3. The coordinates of a point p in a frame W are written as Wp.

Frame Poses

The relationship between two frames is represented by a 6 DOF relative pose, a translation followed by a rotation. If W and A are two frames, the pose of A in W is given by the translation from W's origin to A's origin, and the rotation of A's coordinate axes in W.

The translation is a vector in W's coordinates, WtA. It is represented by tf::Vector3, which is equivalent to btVector3.

The rotation of A is given by a rotation matrix, represented as WAR, using our convention of the reference frame as a preceeding superscript. The way to read this is: "the rotation of the frame A in W's coordinate system." The columns of R are formed from the three unit vectors of A's axes in W: WXA, WYA, and WZA.

There is no tf type for a rotation matrix; instead, tf represents rotations via tf::Quaternion, equivalent to btQuaternion. The bullet quaternion type has methods for creating quaternions from rotation matrices, and vice versa.

It's convenient to describe the translation + rotation in homogeneous coordinates, as a single 4x4 matrix WAT. This can be read as: "the pose of frame A relative to frame W." The relative pose is constructed as follows:

WAR

WtA

0

1

In tf, relative poses are represented as tf::Pose, which is equivalent to the bullet type btTransform. The member functions are getRotation() or getBasis() for the rotation, and getOffset() for the translation of the pose. See the bullet btTransform class reference.

Frame poses as Point Mappings

There is a duality between frame poses and mapping points from one frame to another. The pose WAT can also be read as, "transform a point in A's frame to W." The syntax gives a "cancellation" of the A frame: WATAp = Wp.

Mappings or transforms have their own type, tf::Transform. This is equivalent to the bullet btTransform, so essentially pose offsets and transforms are the same type. Transforms can be created using rotation matrices or quaternions for the rotation, and vectors for the translation. See the bullet btTransform class reference.

Transform Inverse

The inverse of a transform WAT is the transform AWT. The inverse maps points in the reverse direction from the original transform. Inverses are conveniently calculated using the inverse() member function of btTransform.

Publishing Frame Poses

The tf system keeps track of a tree of frames; every link in the tree represents a relative pose between two frames. In C++, the function TransformBroadcaster::sendTransform() adds links to this tree. This function's argument is a stamped transform:

tf::StampedTransform(tf::Pose &T, ros::Time &t, std::string parent, std::string child)

The pose here is pose of child in the frame of parent.

In Python, tf.TransformBroadcaster().SendTransform will output a tf link. Note two things: the transform is specified as a separate rotation and translation; and the order of the parent and child is reversed from the C++ call:

tf.TransformBroadcaster().SendTransform(R,t,time,child,parent)

Retrieving Frame Poses and Transforms

The relative pose between two frames can be retrieved with the tf::transformListener::lookupTransform function. The format is:

void tf::TransformListener::lookupTransform (std::string &W, std::string &A, ros::Time &time, StampedTransform &transform)

The transform returned is WAT, that is, the pose of A in W's coordinate system. This transform can also be used to take points in A's coordinate system and convert them to W. Typically, the transformXXX functions will be used for this task, though.

In python, the translation WtA and rotation WAR are returned:

(trans,rot) = tf.TransformListener().lookupTransform("W", "A", now)

Code

Here is a small python example of broadcasting and receiving pose frame offsets between two frames, W and A. The offset is specified as a translation of 0.5 m in X and 1.0 m in Y, followed by a rotation around Z (yaw) of 30 degrees.

Broadcast

import roslib
roslib.load_manifest('cs225b')
import rospy
import tf
import math

if __name__ == '__main__':
    rospy.init_node('tf_broadcaster')

    br = tf.TransformBroadcaster()

    rate = rospy.Rate(10.0)
    while not rospy.is_shutdown():
        br.sendTransform((0.5, 1.0, 0),
                         tf.transformations.quaternion_from_euler(0, 0, 30*math.pi/180),
                         rospy.Time.now(),
                         "A",     # child
                         "W"      # parent
                         )
        rate.sleep()

Receive

import roslib
roslib.load_manifest('cs225b')
import rospy
import math
import tf
from tf.transformations import euler_from_quaternion

if __name__ == '__main__':
    rospy.init_node('tf_listen')
    listener = tf.TransformListener()

    rate = rospy.Rate(10.0)
    while not rospy.is_shutdown():
        try:
            (trans,rot) = listener.lookupTransform('W', 'A', rospy.Time(0))
        except (tf.LookupException, tf.ConnectivityException):
            continue

        print 'translation: ',trans
        angles = euler_from_quaternion(rot)
        print 'rotation: ',[(180.0/math.pi)*i for i in angles]

        rate.sleep()

Wiki: tf/Overview/Transformations (last edited 2011-10-17 17:33:07 by konolige)