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

transformStamped to transformation matrix (python)

asked 2019-09-05 14:06:44 -0500

SamsAutonomy gravatar image

This may be trivial but I cannot find it anywhere, can someone help me? Goal: Find a transformStamped by a tf2 transform lookup, then convert this to a matrix so I can multiply it. Something like the below:

import tf2_ros
import tf

#(more code here, but not important to question)

tfBuffer = tf2_ros.Buffer()
listener = tf2_ros.TransformListener(tfBuffer)
trans = tfBuffer.lookup_transform("gps", "base_link", rospy.Time.now(), rospy.Duration(0.1))
matrix = tf.transformations.translation_matrix(trans)
# (More code after this point as well.)

Again, this may be trivial but I cannot find the solution to this nor a question that answers my problem.

edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted
2

answered 2022-07-25 04:51:57 -0500

peci1 gravatar image

Although ros_numpy ( https://github.com/eric-wieser/ros_numpy ) is not a "native" way, it is a well established package that can do what you want.

from ros_numpy import numpify
matrix = numpify(msg)
edit flag offensive delete link more
9

answered 2019-09-05 15:21:28 -0500

updated 2019-09-05 15:23:38 -0500

I don't know of a native way to do this, but I wrote the following conversion functions a while ago that I've been using. A call to msg_to_se3 can return a 4x4 SE(3) matrix for a few different ROS message types.

import tf.transformations as tr

from geometry_msgs.msg import Point
from geometry_msgs.msg import Pose
from geometry_msgs.msg import PoseStamped
from geometry_msgs.msg import Quaternion
from geometry_msgs.msg import Transform
from geometry_msgs.msg import TransformStamped
from geometry_msgs.msg import Vector3

import numpy as np

def pose_to_pq(msg):
    """Convert a C{geometry_msgs/Pose} into position/quaternion np arrays

    @param msg: ROS message to be converted
    @return:
      - p: position as a np.array
      - q: quaternion as a numpy array (order = [x,y,z,w])
    """
    p = np.array([msg.position.x, msg.position.y, msg.position.z])
    q = np.array([msg.orientation.x, msg.orientation.y,
                  msg.orientation.z, msg.orientation.w])
    return p, q


def pose_stamped_to_pq(msg):
    """Convert a C{geometry_msgs/PoseStamped} into position/quaternion np arrays

    @param msg: ROS message to be converted
    @return:
      - p: position as a np.array
      - q: quaternion as a numpy array (order = [x,y,z,w])
    """
    return pose_to_pq(msg.pose)


def transform_to_pq(msg):
    """Convert a C{geometry_msgs/Transform} into position/quaternion np arrays

    @param msg: ROS message to be converted
    @return:
      - p: position as a np.array
      - q: quaternion as a numpy array (order = [x,y,z,w])
    """
    p = np.array([msg.translation.x, msg.translation.y, msg.translation.z])
    q = np.array([msg.rotation.x, msg.rotation.y,
                  msg.rotation.z, msg.rotation.w])
    return p, q


def transform_stamped_to_pq(msg):
    """Convert a C{geometry_msgs/TransformStamped} into position/quaternion np arrays

    @param msg: ROS message to be converted
    @return:
      - p: position as a np.array
      - q: quaternion as a numpy array (order = [x,y,z,w])
    """
    return transform_to_pq(msg.transform)


def msg_to_se3(msg):
    """Conversion from geometric ROS messages into SE(3)

    @param msg: Message to transform. Acceptable types - C{geometry_msgs/Pose}, C{geometry_msgs/PoseStamped},
    C{geometry_msgs/Transform}, or C{geometry_msgs/TransformStamped}
    @return: a 4x4 SE(3) matrix as a numpy array
    @note: Throws TypeError if we receive an incorrect type.
    """
    if isinstance(msg, Pose):
        p, q = pose_to_pq(msg)
    elif isinstance(msg, PoseStamped):
        p, q = pose_stamped_to_pq(msg)
    elif isinstance(msg, Transform):
        p, q = transform_to_pq(msg)
    elif isinstance(msg, TransformStamped):
        p, q = transform_stamped_to_pq(msg)
    else:
        raise TypeError("Invalid type for conversion to SE(3)")
    norm = np.linalg.norm(q)
    if np.abs(norm - 1.0) > 1e-3:
        raise ValueError(
            "Received un-normalized quaternion (q = {0:s} ||q|| = {1:3.6f})".format(
                str(q), np.linalg.norm(q)))
    elif np.abs(norm - 1.0) > 1e-6:
        q = q / norm
    g = tr.quaternion_matrix(q)
    g[0:3, -1] = p
    return g
edit flag offensive delete link more

Comments

Worked like charm! Thanks, I was going crazy trying to find a native way to do this. If someone knows of a native way, I'd be glad to hear about it, otherwise this way works just fine!

SamsAutonomy gravatar image SamsAutonomy  ( 2019-09-06 10:26:54 -0500 )edit

Question Tools

3 followers

Stats

Asked: 2019-09-05 14:06:44 -0500

Seen: 7,730 times

Last updated: Jul 25 '22