tf与坐标转换

一、发布tf

方法一:wiki上的方法,tf::Transform

void poseCallback(const turtlesim::PoseConstPtr& msg){
    static tf::TransformBroadcaster br;
    tf::Transform transform;
    transform.setOrigin( tf::Vector3(msg->x, msg->y, 0.0) );
    tf::Quaternion q;
    q.setRPY(0, 0, msg->theta);
    transform.setRotation(q);
    br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), 
                    "world","base_link"));
}

方法二:geometry_msgs::TransformStamped

tf::TransformBroadcaster odom_broadcaster;
geometry_msgs::TransformStamped leg_odom_trans;
leg_odom_trans.header.stamp = ros::Time::now();
leg_odom_trans.header.frame_id = "odom";
leg_odom_trans.child_frame_id = "base_link";
leg_odom_trans.transform.translation.x = robot_state->pos_world[0];
leg_odom_trans.transform.translation.y = robot_state->pos_world[1];
leg_odom_trans.transform.translation.z = robot_state->pos_world[2];
auto q = tf::createQuaternionFromRPY(robot_state->rpy[0] / 180 * PI,
         robot_state->rpy[1] / 180 * PI, 
         robot_state->rpy[2] / 180 * PI);
tf::quaternionTFToMsg(q, leg_odom_trans.transform.rotation);
odom_broadcaster.sendTransform(leg_odom_trans);

备注:其中ros::Time::now()可换成真实的ros::Time时间戳。头文件需包含:

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

二、订阅tf

方法一:订阅截至当前最新的tf,不需要等待

tf::TransformListener listener;
tf::StampedTransform transform;
try{
    listener.lookupTransform("/turtle2", "/turtle1",  
                             ros::Time(0), transform);
}
catch (tf::TransformException ex){
    ROS_ERROR("%s",ex.what());
    ros::Duration(1.0).sleep();
}

方法二:订阅当前时刻的tf,需要等待

tf::TransformListener listener;
tf::StampedTransform transform;
try{
    listener.waitForTransform("/turtle2", "/turtle1",
                              ros::Time::now(), ros::Duration(3.0));
    listener.lookupTransform("/turtle2", "/turtle1",  
                             ros::Time::now(), transform);
}
catch (tf::TransformException ex){
    ROS_ERROR("%s",ex.what());
    ros::Duration(1.0).sleep();
}

备注:也可把ros::Time::now()改为ros::Time::now()-ros::Duration(1.0)订阅1秒前的tf,改为某个点云时间戳,用于点云坐标系转换。头文件需包含:

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

三、点云坐标轴转换——订阅tf并转为eigen

tf::TransformListener listener;
bool transformPointCloud(pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr pointCloud, pcl::PointCloud<pcl::PointXYZRGB>::Ptr pointCloudTransformed, const std::string& targetFrame)
{
const std::string inputFrameId(pointCloud->header.frame_id);
try{
    listener.waitForTransform(targetFrame, inputFrameId, 
                                        timeStamp, ros::Duration(1.0));
    listener.lookupTransform(targetFrame, inputFrameId, 
                                       timeStamp, transformTf);
} 
catch (tf::TransformException &ex) {
    ROS_ERROR("%s", ex.what());
    return false;
}

Eigen::Affine3d transform;
poseTFToEigen(transformTf, transform);
pcl::transformPointCloud(*pointCloud, *pointCloudTransformed,         
                         transform.cast<float>());
pointCloudTransformed->header.frame_id = targetFrame;
}

备注:头文件需包含

#include <ros/ros.h>
#include <tf/transform_listener.h>
#include <tf_conversions/tf_eigen.h>
#include <Eigen/Core>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/common/transforms.h>

四、点云坐标转换——构造eigen

Eigen::Matrix4f transform_1 = Eigen::Matrix4f::Identity();
float theta = M_PI/4;   //旋转的度数,这里是45度
transform_1 (0,0) = cos (theta);  //这里是绕的Z轴旋转
transform_1 (0,1) = -sin(theta);
transform_1 (1,0) = sin (theta);
transform_1 (1,1) = cos (theta);
        
//transform_1 (0,2) = 0.3;   //这样会产生缩放效果
//transform_1 (1,2) = 0.6;
//transform_1 (2,2) = 1;
 
transform_1 (0,3) = 25; //这里沿X轴平移
transform_1 (1,3) = 30;
transform_1 (2,3) = 380;
pcl::PointCloud<pcl::PointXYZ>::Ptr transform_cloud1 (new pcl::PointCloud<pcl::PointXYZ>);
pcl::transformPointCloud(*cloud,*transform_cloud1,transform_1);

五、点的坐标轴转换

tf::TransformListener listener
geometry_msgs::PointStamped pointBodyFrame,pointOdomFrame;
pointBodyFrame.header.frame_id="base_link";
pointBodyFrame.header.stamp=ros::Time(0);
pointBodyFrame.point.x=1.0;   
pointBodyFrame.point.y=2.0;
pointBodyFrame.point.z=0;
try{ 
    listener_.transformPoint("odom",pointBodyFrame,pointOdomFrame);
}catch (tf::TransformException &ex) {
    ROS_ERROR("%s",ex.what());
}

备注:转换关系的时间用的是被转换点的时间戳。头文件需包含:

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

使用点的时间戳对应的tf进行转换,ros::Time(0)表示使用最新的tf,不能用ros::Time::now()。

 

 

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ROS中的坐标转换函数是通过tf2库来实现的。这个函数采用固定轴的旋转方式,先绕定轴x旋转(横滚),然后再绕定轴y (俯仰),最后绕定轴z(偏航)。从数学形式上说,这是绕定轴XYZ矩阵依次左乘,即R=R(z)R(y)R(x)的顺序。这种方式的好处是直观且便于人机交互。\[1\] 在动态坐标变换中,ROS系统会根据时间戳进行坐标系和坐标点的匹配,来保证坐标变换的准确性。当时间戳相差较大时,系统会报错。为了解决这个问题,需要在循环中更新订阅端的无效时间戳,即每次循环都要更新时间戳。虽然buffer的时间戳一直不变,但是其内容是一直变得,在一直更新。因此,忽略时间戳并不会影响转换精度。\[2\] 在创建项目功能包时,需要依赖于tf2、tf2_ros、tf2_geometry_msgs、roscpp、rospy、std_msgs、geometry_msgs和turtlesim等库。在准备参数时,需要提供两组静态坐标变换的偏移量和四元数,即对应的son1和son2在世界坐标系下的坐标变换。\[3\] #### 引用[.reference_title] - *1* [SLAM中坐标轴旋转及ros的接口解释](https://blog.csdn.net/qq_42911741/article/details/127728007)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [ros tf坐标](https://blog.csdn.net/gyxx1998/article/details/128529862)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [ROS tf2 坐标变换学习(一)](https://blog.csdn.net/weixin_43134049/article/details/124017749)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值