ROS中创建tf的两种方法对比

第一种方法:来源于 http://wiki.ros.org/urdf/Tutorials/Using urdf with robot_state_publisher
cpp源码如下:(相比较于官方的源码,删去了sensor_msgs::JointState部分,只考虑tf的创建与发布)

int main(int argc, char** argv) {
    ros::init(argc, argv, "state_publisher");
    ros::NodeHandle n;
    tf::TransformBroadcaster broadcaster;

    const double degree = M_PI/120;
    double angle = 0;

    // message declarations
/*    This expresses a transform from coordinate frame header.frame_id 
                               to the coordinate frame child_frame_id*/
    geometry_msgs::TransformStamped odom_trans;
    odom_trans.header.frame_id = "odom";
    odom_trans.child_frame_id  = "box";

    ros::Rate loop_rate(30);
    while (ros::ok()) {
        // update transform
        // (moving in a circle with radius=2)
        odom_trans.header.stamp = ros::Time::now();
        odom_trans.transform.translation.x = cos(angle)*2;  //公转半径
        odom_trans.transform.translation.y = sin(angle)*2;  //公转半径
        odom_trans.transform.translation.z = 0;
        odom_trans.transform.rotation = tf::createQuaternionMsgFromYaw(angle+M_PI/2);

        //send the joint state and transform
        broadcaster.sendTransform(odom_trans);

        angle += degree;

        // This will adjust as needed per iteration
        loop_rate.sleep();
    }
    return 0;
}

这段代码的中心在于:

  • 创建tf的发布者
  • tf::TransformBroadcaster broadcaster;
  • 创建tf数据
  • geometry_msgs::TransformStamped odom_trans;
  • 设置odom_trans的内容
  • rosmsg show geometry_msgs/TransformStamped
  • 发布tf变换
  • broadcaster.sendTransform(odom_trans);

这里需要注意的是,这个包的src里只有这一个cpp文件,那么发布的tf变换由谁接受呢?
launch源码如下:

<launch>
        <param name="robot_description" command="cat $(find r2d2)/model.xml" />
        <node name="robot_state_publisher"  pkg="robot_state_publisher" type="state_publisher" />
        <node name="state_publisher"        pkg="r2d2"                  type="state_publisher" />

        <node name = "rviz" pkg = "rviz" type = "rviz" />

</launch>

可以看到,这个包一共开启了三个node。除去刚刚cpp文件创建的state_publisher的node之外。rviz的node用来显示现象。并无太多可说。
robot_state_publisher包用来发布机器人的状态。它一共有两个输入。一个是urdf文件表示机器人。这里从param_server中的robot_description读取。以下是ros.wiki上对于这个包的解释。

This package allows you to publish the state of a robot to tf. Once the state gets published, it is available to all components in the system that also use tf. The package takes the joint angles of the robot as input and publishes the 3D poses of the robot links, using a kinematic tree model of the robot. The package can both be used as a library and as a ROS node.

robot_state_publisher uses the URDF specified by the parameter robot_description and the joint positions from the topic joint_states to calculate the forward kinematics of the robot and publish the results via tf.

需要注意的一点是,ros提供的另外一个包joint_state_publisher可以发布joint_states主题下的消息,所以两个包往往一起使用。
第二种方法:来源于 http://www.guyuehome.com/355
源码如下:
tf_broadcaster.cpp

#include <ros/ros.h>
#include <tf/transform_broadcaster.h>

int main(int argc, char** argv)
{
    ros::init(argc, argv, "robot_tf_publisher");
    ros::NodeHandle n;
    tf::TransformBroadcaster broadcaster;

    ros::Rate r(100);
    while(n.ok()){
        broadcaster.sendTransform
        (
            tf::StampedTransform
            (
                tf::Transform( tf::Quaternion(0, 0, 0, 1), tf::Vector3(0.1, 0.0, 0.2) ),
                ros::Time::now(),
                "base_link",
                "base_laser"
            )
        );
        r.sleep();
    }
}

tf_listener.cpp

#include <ros/ros.h>
#include <geometry_msgs/PointStamped.h>
#include <tf/transform_listener.h>

void transformPoint(const tf::TransformListener& listener){
    //we'll create a point in the base_laser frame that we'd like to transform to the base_link frame
    geometry_msgs::PointStamped laser_point;
    laser_point.header.frame_id = "base_laser";
    //we'll just use the most recent transform available for our simple example
    laser_point.header.stamp = ros::Time();
    //just an arbitrary point in space
    laser_point.point.x = 1.0;
    laser_point.point.y = 0.2;
    laser_point.point.z = 0.0;

    try{
        geometry_msgs::PointStamped base_point;
        listener.transformPoint("base_link", laser_point, base_point);
        ROS_INFO(
            "base_laser: (%.2f, %.2f. %.2f) -----> base_link: (%.2f, %.2f, %.2f) at time %.2f",
            laser_point.point.x, laser_point.point.y, laser_point.point.z,
            base_point.point.x,  base_point.point.y,  base_point.point.z, base_point.header.stamp.toSec()
            );
    }
    catch(tf::TransformException& ex){
        ROS_ERROR(
            "Received an exception trying to transform a point from \"base_laser\" to \"base_link\": %s", ex.what()
            );
    }
}

int main(int argc, char** argv){
    ros::init(argc, argv, "robot_tf_listener");
    ros::NodeHandle n;
    tf::TransformListener listener(ros::Duration(10));

    //we'll transform a point once every second
    ros::Timer timer = n.createTimer(
        ros::Duration(1.0),
        boost::bind( &transformPoint, boost::ref(listener) )
        );

    ros::spin();
}

代码的中心在于:tf_broadcaster.cpp中的

broadcaster.sendTransform
        (
            tf::StampedTransform
            (
                tf::Transform( tf::Quaternion(0, 0, 0, 1), tf::Vector3(0.1, 0.0, 0.2) ),
                ros::Time::now(),
                "base_link",
                "base_laser"
            )
        );

用来发布一个tf变换的位姿矩阵
以及tf_listener.cpp中的

listener.transformPoint("base_link", laser_point, base_point);

进行tf变换。
需要注意的是,这里的

void transformPoint(const tf::TransformListener& listener)

是一个callback函数。它的调用是由

n.createTimer

函数执行的。
这里的tf变换一共有两个输入。一个是变换需要的位姿矩阵,一个是需要变换的点。位姿矩阵是在tf_broadcaster.cpp中的

 tf::Transform( tf::Quaternion(0, 0, 0, 1), tf::Vector3(0.1, 0.0, 0.2) ),

设置完成。
第二个要变换的点,是在tf_listener.cpp中

    geometry_msgs::PointStamped laser_point;

中设置的。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值