• TF坐标


    1.简介

    TF是一个让用户随时间跟踪多个坐标系的功能包,它使用树形数据结构,根据时间缓冲并维护多个坐标系之间的坐标变换关系。

    2.TF工具

    • tf_monitor :查看TF树中所有坐标系的发布状态
    • tf_monitor <source_frame> <target_target> :查看指定坐标系之间的发布状态
    • tf_echo <source_frame> <target_target> :查看指定坐标系之间的变换关系
    • view_frames :可视化工具,生成pdf文件 rosrun tf view_frames

    3.实践

    turtle_tf_broadcaster.cpp

    #include <ros/ros.h>
    #include <tf/transform_broadcaster.h>
    #include <turtlesim/Pose.h>
    
    std::string turtle_name;
    
    void poseCallback(const turtlesim::PoseConstPtr& msg)
    {
        // tf广播器
        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", turtle_name));
    }
    
    int main(int argc, char** argv)
    {
        // 初始化节点
        ros::init(argc, argv, "my_tf_broadcaster");
        if (argc != 2)
        {
            ROS_ERROR("need turtle name as argument"); 
            return -1;
        };
        turtle_name = argv[1];
    
        // 订阅乌龟的pose信息
        ros::NodeHandle node;
        ros::Subscriber sub = node.subscribe(turtle_name+"/pose", 10, &poseCallback);
    
        ros::spin();
    
        return 0;
    };
    

    turtle_tf_lestener.cpp

    #include <ros/ros.h>
    #include <tf/transform_listener.h>
    #include <geometry_msgs/Twist.h>
    #include <turtlesim/Spawn.h>
    
    int main(int argc, char** argv)
    {
        // 初始化节点
        ros::init(argc, argv, "my_tf_listener");
    
        ros::NodeHandle node;
    
        // 通过服务调用,产生第二只乌龟turtle2
        ros::service::waitForService("spawn");
        ros::ServiceClient add_turtle =
        node.serviceClient<turtlesim::Spawn>("spawn");
        turtlesim::Spawn srv;
        add_turtle.call(srv);
    
        // 定义turtle2的速度控制发布器
        ros::Publisher turtle_vel =
        node.advertise<geometry_msgs::Twist>("turtle2/cmd_vel", 10);
    
        // tf监听器
        tf::TransformListener listener;
    
        ros::Rate rate(10.0);
        while (node.ok())
        {
            tf::StampedTransform transform;
            try
            {
                // 查找turtle2与turtle1的坐标变换
                listener.waitForTransform("/turtle2", "/turtle1", ros::Time(0), ros::Duration(3.0));
                listener.lookupTransform("/turtle2", "/turtle1", ros::Time(0), transform);
                //这里求的transform是turtle2到turtle1的变换
            }
            catch (tf::TransformException &ex) 
            {
                ROS_ERROR("%s",ex.what());
                ros::Duration(1.0).sleep();
                continue;
            }
    
            // 根据turtle1和turtle2之间的坐标变换,计算turtle2需要运动的线速度和角速度
            // 并发布速度控制指令,使turtle2向turtle1移动
            geometry_msgs::Twist vel_msg;
            vel_msg.angular.z = 4.0 * atan2(transform.getOrigin().y(),
                                            transform.getOrigin().x());
            vel_msg.linear.x = 0.5 * sqrt(pow(transform.getOrigin().x(), 2) +
                                          pow(transform.getOrigin().y(), 2));
            turtle_vel.publish(vel_msg);
    
            rate.sleep();
        }
        return 0;
    };
    
    rosrun rviz rviz -d 'rospack find turtle_tf' /rviz/turtle_rviz.rviz
    
  • 相关阅读:
    Preserving Remote IP/Host while proxying
    使用EF Core生成实体类 用来作为NetCore数据库访问上下文 Context
    【ASP.NET Core快速入门】(八)Middleware管道介绍、自己动手构建RequestDelegate管道
    NetCore WebApi 基于Jwt的验证授权方式
    Net Core 页面的生命周期 + OnActionExecuting
    C# 多线程发送邮件 代码版
    ASP.NET Core 中的过滤器(Action过滤器,控制器过滤器,全局应用程序过滤器)
    深入理解 NetCore 中的依赖注入的好处 及 、Singleton、Scoped、Transient 三种对象的差异
    巧用 display: contents 增强页面语义
    巧妙实现带圆角的渐变边框
  • 原文地址:https://www.cnblogs.com/penuel/p/15996927.html
Copyright © 2020-2023  润新知