zoukankan      html  css  js  c++  java
  • tf变换(1)

    TF库的目的是实现系统中任一个点在所有坐标系之间的坐标变换,也就是说,只要给定一个坐标系下的一个点的坐标,就能获得这个点在其他坐标系的坐标.

     使用tf功能包,a. 监听tf变换: 接收并缓存系统中发布的所有参考系变换,并从中查询所需要的参考系变换。

                             b.广播 tf变换: 向系统中广播参考系之间的坐标变换关系。系统中更可能会存在多个不同部分的tf变换广播,每个广播都可以直接将参考系变换关系直接插入tf树中,不需要再进行同步。

     

    首先介绍关于TF的API的一些数据结构:

    基本的数据类型有(Quaternion, Vector, Point, Pose, Transform)

      

    这其中Quaternion 是表示四元数,vector3是一个3*1 的向量,point是一个表示一个点坐标,Pose是位姿(位姿是包括坐标以及方向) Transform是一个转换的模版

    tf::Stamped <T>

    是一种包含了除了Transform的其他几种基本的数据结构的一种数据结构:

    template <typename T>    //模版结构可以是tf::Pose tf:Point 这些基本的结构
    class Stamped : public T{
     public:
      ros::Time stamp_;    //记录时间
      std::string frame_id_;   //ID
    
      Stamped() :frame_id_ ("NO_ID_STAMPED_DEFAULT_CONSTRUCTION"){}; //Default constructor used only for preallocation
    
      Stamped(const T& input, const ros::Time& timestamp, const std::string & frame_id);
      
      void setData(const T& input);
    };

    tf::StampedTransform

    TF::stampedtransform是TF的一种特殊情况:它需要frame_id和stamp以及child_frame_id。

    /** rief The Stamped Transform datatype used by tf */
    class StampedTransform : public tf::Transform
    {
    public:
      ros::Time stamp_; ///< The timestamp associated with this transform 时间戳                                                                                                                                                                                                                                                       
      std::string frame_id_; ///< The frame_id of the coordinate frame  in which this transform is defined  定义转换坐标框架的frameID                                                                                                                                                                                                                    
      std::string child_frame_id_; ///< The frame_id of the coordinate frame this transform defines 的坐标系变换定义的id                                                                                                                                                                                                                            
      StampedTransform(const tf::Transform& input, const ros::Time& timestamp, const std::string & frame_id, const std::string & child_frame_id):
        tf::Transform (input), stamp_ ( timestamp ), frame_id_ (frame_id), child_frame_id_(child_frame_id){ };
    
      /** rief Default constructor only to be used for preallocation */
      StampedTransform() { };
    
      /** rief Set the inherited Traonsform data */
      void setData(const tf::Transform& input){*static_cast<tf::Transform*>(this) = input;};
    
    };

     举个例子

    在机器人的定位领域有蒙特卡罗定位(AMCL)的算法,这个算法是根据给定的地图,结合粒子滤波获取最佳定位点Mp,这个定位点是相对于地图map上的坐标,也就是base_link(也就是机器人的基坐标)相对map上的坐标。我们知道 odom 的原点是机器人启动时刻的位置,它在map上的位置或转换矩阵是未知的。但是AMCL可以根据最佳粒子的位置推算出 odom->map(就是说通过最佳粒子推算出机器人在地图的中的位置)的tf转换信息并发布到 tf主题上。因为base_link->odom的tf转换信息是每时每刻都在发布的,所以它是已知的

    ,所以这里有个这样的tf关系

    map->base_link(就是地图中机器人的位置  是根据最佳粒子推算的)

    base_link->odom(这是现实中机器人的位姿可以说是里程计的信息)

    可以理解:机器人的里程计的信息 = 当前地图中的机器人的的位置    减去  地图中机器人的起点位置。

     转为公式可以写成 :map->odom = map->base_link   -  base_link->odom

    或者写为:

     base_link->odom = map->base_link - map->odom  (这样更容易理解)

    提示:首先我们可以先了解关于PRY这三个概念关于pitch yaw roll的博客 http://blog.csdn.net/yuzhongchun/article/details/22749521

    pitch是围绕X轴旋转,也叫做俯仰角,

    yaw是围绕Y轴旋转,也叫偏航角,

    roll是围绕Z轴旋转,也叫翻滚角

    1.    ROS_DEBUG("New pose: %6.3f %6.3f %6.3f",  
    2.             hyps[max_weight_hyp].pf_pose_mean.v[0],  
    3.             hyps[max_weight_hyp].pf_pose_mean.v[1],  
    4.             hyps[max_weight_hyp].pf_pose_mean.v[2]);  
    5.     // hyps[max_weight_hyp].pf_pose_mean.v[0], [1], [2] 就代表了Mp  也就是机器人的位姿那么位姿的格式是(x,y,theta)最后一个是yaw偏航角,
    6.    // subtracting base to odom from map to base and send map to odom instead  
    7.    tf::Stamped<tf::Pose> odom_to_map;  
    8.    try  
    9.    {  
    10.      tf::Transform tmp_tf(tf::createQuaternionFromYaw(hyps[max_weight_hyp].pf_pose_mean.v[2]),   tf::Vector3(hyps[max_weight_hyp].pf_pose_mean.v[0],  
    11.                                       hyps[max_weight_hyp].pf_pose_mean.v[1],  
    12.                                       0.0));  
    13.    // tmp_tf = 从map原点看base_link的位置  为yaw生成四元数,最后的0.0是(x,y,z)的Z的值为0  因为这是在二维平面中。
    14.      tf::Stamped<tf::Pose> tmp_tf_stamped (tmp_tf.inverse(),  
    15.                                            laser_scan->header.stamp,  
    16.                                            base_frame_id_);  
    17.    //tmp_tf.inverse()  = 以为Mp为坐标的原点,地图map原点相对于Mp的位置,就是在base_link坐标系下map 原点的位置
    18.      this->tf_->transformPose(odom_frame_id_,  
    19.                               tmp_tf_stamped,  
    20.                               odom_to_map); 
    21.     //进行 base_link坐标系下的点转换到odom坐标系,也就是把map原点转换到odom坐标系下,等于从odom原点看map原点的位置。放到latest_tf_变量里面
    22.    }  
    23.    catch(tf::TransformException)  
    24.    {  
    25.      ROS_DEBUG("Failed to subtract base to odom transform");  
    26.      return;  
    27.    }  

    TF命令行工具

    (1) tf_monitor工具的功能是打印tf树中的所有参考系信息,通过输入参数来查看指定参考系之间的信息  用法: rosrun tf tf_monitor

      tf_monitor <source_frame> <target_target>  监视一个特定的转换 For example, to monitor the transform from /base_footprint to /odom:

      (2) tf_echo工具的功能是查看指定参考系之间的变换关系。命令的格式: tf_echo <source_frame> <target_frame>

     (3)static_transform_publisher工具的功能是发布两个参考系之间的静态坐标变换,两个参考系一般不发生相对位置变化

    (4)view_frames 是可视化的调试工具,可以生成pdf文件,来显示整棵tf树的信息。用法:rosrun tf view_frames 

    具体可以查看http://wiki.ros.org/tf/

    博客园的编辑界面真实难以编辑啊  受不鸟了  所以还是不写了  转向CSDN了

  • 相关阅读:
    一周信创舆情观察(11.2~11.8)
    一周信创舆情观察(10.26~11.1)
    一周信创舆情观察(10.19~10.25)
    一周信创舆情观察(10.12~10.18)
    Python脚本导出AWS EC2资源清单
    C++typename的由来和用法
    百篇已过,又是一个新篇章,谈谈感受吧
    【硬件篇之电源纹波噪声测试】
    C++的转换手段并与explicit关键词配合使用
    shell脚本的使用该熟练起来了,你说呢?(篇二)
  • 原文地址:https://www.cnblogs.com/li-yao7758258/p/7672521.html
Copyright © 2011-2022 走看看