# 4x4 Transformation Matrix to tf Transform

I am trying to convert a 4x4 transformation matrix (Eigen::Matrix4f) that is an output of PCL's ICP into a tf Transform that I can publish. The 4x4 consists of a 3x3 rotation matrix and a 3x1 translation matrix.

Is there an easy way to make this conversion?

The translation matrix is pretty straightforward to pull out of the 4x4 and then assign to the tf Transform.

I am confused on the data types and functions to get the rotation working. My plan was to create a 3x3 matrix (data type?), assign it proper values from the 4x4 (method?) that I could then convert into a quaternion (function?), which I then could assign to the transform (I've seen an example of this).

Any help is appreciated. Thank you.

edit retag close merge delete

Sort by » oldest newest most voted

Thanks.

I could not get the functions listed in that api to work properly, but it did lead to something else that worked. here is my code that I tested and worked. I know the while (true) is not the best way to publish, but it worked for a test.

  Eigen::Matrix4f Tm;
Tm <<     0.714191,   -0.54278,   0.441988,  0.0432322,
0.409255,   0.836069,    0.36542,  0.0571429,
-0.567861, -0.0800918,   0.819232,    1.22178,
0,          0,          0,       1;

tf::Vector3 origin;
origin.setValue(static_cast<double>(Tm(0,3)),static_cast<double>(Tm(1,3)),static_cast<double>(Tm(2,3)));

cout << origin << endl;
tf::Matrix3x3 tf3d;
tf3d.setValue(static_cast<double>(Tm(0,0)), static_cast<double>(Tm(0,1)), static_cast<double>(Tm(0,2)),
static_cast<double>(Tm(1,0)), static_cast<double>(Tm(1,1)), static_cast<double>(Tm(1,2)),
static_cast<double>(Tm(2,0)), static_cast<double>(Tm(2,1)), static_cast<double>(Tm(2,2)));

tf::Quaternion tfqt;
tf3d.getRotation(tfqt);

tf::Transform transform;
transform.setOrigin(origin);
transform.setRotation(tfqt);
while (true) br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "camera_rgb_optical_frame", "lifting_eye"));

more

You should use a Matrix4d and drop all the static_cast which makes the code unreadable. You can also use Eigen block operations to remove most of the temporary variables.

Thank you for the comment. The output of icp is 4f. I don't think it will work with 4d. If there is an easy conversion please let me know. I don't know what you mean by using Eigen block operations.

You can use the built in cast functions of Eigen:

Tm.cast<double>();


Will return an Eigen::Matrix4d See tf_eigen.h from the tf_conversion package.

more

Here's a simple solution to convert

Eigen::matrix4f eigen_matrix_4f_transform

to

geometry_msgs::TransformStamped tf_stamped

Eigen::Affine3d eigen_affine_transform;
eigen_affine_transform.matrix() = eigen_matrix_4f_transform.cast<double>();
tf_stamped = tf2::eigenToTransform(eigen_affine_transform);


tf_stamped can be later published with

tf::TransformBraodcaster

Remember that you need to set frame_id, child_frame_id nad stamp before publishing

  tf_stamped.header.frame_id = "odom_comb";
tf_stamped.child_frame_id = "platform";
tf_brodcast_.sendTransform(tf_stamped);

more

1

In your answer, where does final_transform_affine come from? is it meant to be the same as eigen_affine_transform, which you assign and then do nothing with?

Yes, the correct input to the function is eigen_affine_transform. Thank you for noticing this bug. I've corrected my answer.