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

What is the mathematical relationship between parent and child frame in tf?

asked 2019-12-02 14:40:26 -0500

ignite gravatar image

updated 2022-04-30 13:48:04 -0500

lucasw gravatar image

I am very confused by the coordinate frame in this tutorial.

In this command line syntax

rosrun tf static_transform_publisher x y z yaw pitch roll frame_id child_frame_id period_in_ms
  1. Does the value x y z yaw pitch roll represents the transform from child_frame_id to frame_id? Or the other way around?
  2. And what is the relationship between frame_id and child_frame_id? What is the order of the yaw pitch row in the transformation? Which one is the correct relationship?

    • Extrinsic rotation (occurs about the axes of the fixed coordinate system):

      • child_frame_id = R(yaw) * R(pitch) * R(roll) * frame_id + [x,y,z]
      • child_frame_id = R(roll) * R(pitch) * R(yaw) * frame_id + [x,y,z]
    • Intrinsic rotation (occurs about the axes of a coordinate system XYZ attached to a moving body):

      • child_frame_id = frame_id * R(yaw) * R(pitch) * R(roll) + [x,y,z]
      • child_frame_id = frame_id * R(roll) * R(pitch) * R(yaw) + [x,y,z]
edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted

answered 2019-12-02 14:57:51 -0500

updated 2019-12-02 14:57:57 -0500

I think the documentation makes this pretty clear, see below.

edit flag offensive delete link more


Thanks for pointing to the document. But could you please (in question 2) let me know which one is the correct mathematical formula? I don't think the document is very clear on what is child. I mean, the tf is the transform from child_frame_id to frame_if? Or the other way around?

ignite gravatar image ignite  ( 2019-12-02 15:01:46 -0500 )edit

Also, is the roll, pitch, yaw in this syntax intrinsic rotation or extrinsic rotation?

ignite gravatar image ignite  ( 2019-12-02 15:06:25 -0500 )edit

I believe you can do the leg work yourself to find out :-) its all there for you

stevemacenski gravatar image stevemacenski  ( 2019-12-02 15:25:14 -0500 )edit

@stevemacenski I am trying to do it myself right now. But I was just hoping that someone who is an expert like you can point it out; that is the reason I ask to ROS community here. Also, I don't think the document is very clear, especially about rotation (Euler & quaternion) conventions. (I'm quite sure I will ramp up once I'm familar with ROS convention.) But to newcomers like me, perhaps, in my humble opinion, it would be much easier if we write down the mathematical equations in the document; because the math would say it all.

ignite gravatar image ignite  ( 2019-12-02 15:26:26 -0500 )edit

answered 2022-01-03 11:35:06 -0500

goksankobe gravatar image

updated 2022-01-04 00:00:57 -0500

Hi, I believe this is a perfectly valid question still in 2022, and not immediately clear from the tf/tf2 documentation and papers or REP 103, due to lack of the "intrinsic" and "extrinsic" rotation in the terminology.

Firstly, verbal overview in states that

"the rotation of the frame A in W's coordinate system."

which hints that rotation of A is represented in the external coordinate system of W, hence extrinsic rotation

Secondly, doing a bit reverse-engineering, one could see that

static_transform_publisher x y z yaw pitch roll frame_id child_frame_id

way of using static tf, calls the following lines:

tf2::Quaternion quat;
quat.setRPY(atof(argv[6]), atof(argv[5]), atof(argv[4]));
msg.transform.rotation.x = quat.x();
msg.transform.rotation.y = quat.y();
msg.transform.rotation.z = quat.z();
msg.transform.rotation.w = quat.w();

which in turn calls :

  /**@brief Set the quaternion using fixed axis RPY
   * @param roll Angle around X 
   * @param pitch Angle around Y
   * @param yaw Angle around Z*/
  void setRPY(const tf2Scalar& roll, const tf2Scalar& pitch, const tf2Scalar& yaw)
        tf2Scalar halfYaw = tf2Scalar(yaw) * tf2Scalar(0.5);  
        tf2Scalar halfPitch = tf2Scalar(pitch) * tf2Scalar(0.5);  
        tf2Scalar halfRoll = tf2Scalar(roll) * tf2Scalar(0.5);  
        tf2Scalar cosYaw = tf2Cos(halfYaw);
        tf2Scalar sinYaw = tf2Sin(halfYaw);
        tf2Scalar cosPitch = tf2Cos(halfPitch);
        tf2Scalar sinPitch = tf2Sin(halfPitch);
        tf2Scalar cosRoll = tf2Cos(halfRoll);
        tf2Scalar sinRoll = tf2Sin(halfRoll);
        setValue(    sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, //x
                     cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw, //y
                     cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw, //z
                     cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); //formerly yzx

This is the exact notation in, which is indicated as lab1-2-3 sequence, where lab frame is fixed during the rotation. Therefore, it seems that it's following extrinsic rotation

Furthermore, in REP103 (, it's mentioned that the rotation convention is "fixed axis roll, pitch, yaw". Although, this does not make it immediately clear, since fixed axis could also be interpreted as rotation around a fixed axis of a rigid body.

A nice summary of the conventions used in similar 3d tools can be found in:

edit flag offensive delete link more

Question Tools

1 follower


Asked: 2019-12-02 14:40:26 -0500

Seen: 1,324 times

Last updated: Jan 04 '22