tf坐标变换
首先安装tf功能包
sudo apt-get install ros-melodic-trtle-tf
运行tf功能包demo
roslaunch turtle_tf turtle_tf_demo.launch
运行键盘节点rosrun turtlesim turtle_teleop_key
可观察到出现两只海龟,其中一只跟随始终跟随第一只位置变化
在这里插入图片描述

观察tf坐标系关系

1、运行rosrun tf view_frames,生成tf可视化工具生成pdf文件,保存在当前目录,如图体现三个坐标系
turtle1坐标系,world坐标系,turtle2坐标系位置关系

在这里插入图片描述

2、rosrun tf tf_echo turtle1 turtle2
可观察到实时姿态,包括位置信息和旋转信息
3、利用rviz可视化工具观察坐标变换
rosrun rviz rviz -d ‘rospack find turtle_tf’/rviz/turtle_rviz.rviz
在这里插入图片描述

tf坐标系监听与广播编程实现

创建tf功能包
catkin_create pkg learning_tf roscpp rospy turtlesim tf

创建tf广播器代码

#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数据
    tf::Transform transform;//4*4矩阵
    transform.setOrigin(tf::Vector3(msg->x,msg->y,0.0));//设置平移参数
    tf::Quaternion q;//通过四元数设置旋转
    q.setRPY(0,0,msg->theta);//两个坐标系姿态变化设置
    transform.setRotation(q);

    //广播world与海龟坐标系之间的tf数据,添加当前时间戳,广播world和turtle_name
    br.sendTransform(tf::StampedTransform(transform,ros::Time::now(),"world",turtle_name));
}




int main(int argc , char** argv)
{
    //初始化ROS节点
    ros::init(argc,argv,"my_tf_broadcaster");

    //输入参数作为海龟名字,重映射
    if(argc !=2)
    {
        ROS_ERROR("NEED TURTLE NAME AS ARGUMENT");
        return -1;
    }
    turtle_name = argv[1];

    //创建订阅者sub,订阅海龟位资话题
    ros::NodeHandle node;//创建句柄
    ros::Subscriber sub = node.subscribe(turtle_name+"/pose",10,&poseCallback);

    //循环等待回调函数
    ros::spin();

    return 0;

}

创建tf监听器代码

#include<ros/ros.h>
#include<tf/transform_listener.h>//tf监听器
#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");//发布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())
    {
        //获取turtle1与turtle2坐标之间的tf数据
        tf::StampedTransform transform;
        try
        {
            //等待变换,等待当前时间,等待3秒后超时提示错误
            listener.waitForTransform("/turtle2","/turtle1",ros::Time(0),ros::Duration(3.0));
            //查询变换,查询当前时间,结果保存在transform中
            listener.lookupTransform("/turtle2","/turtle1",ros::Time(0),transform);
        }
        catch (tf::TransformException &ex)
        {

        }

        //根据turtle1与turtle2坐标系之间的位置关系,发布turtle2的速度指令控制
        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;

}

配置tf广播器与监听器代码编译规则

add_executable(turtle_tf_broadcaster src/turtle_tf_broadcaster.cpp)
target_link_libraries(turtle_tf_broadcaster ${catkin_LIBRARIES})
add_executable(turtle_tf_listener src/turtle_tf_listener.cpp)
target_link_libraries(turtle_tf_listener ${catkin_LIBRARIES})

使用catkin_make编译工作空间

编译运行

roscore
rosrun turtlesim turtlesim_node
rosrun learning_tf turtle_tf_broadcaster__name:=turtle1_tf_broadcaster /turtle1
rosrun learning_tf turtle_tf_broadcaster__name:=turtle2_tf_broadcaster /turtle2
rosrun learning_tf turtle_tf_listener
rosrun turtlesim turtle_teleop_key

launch文件语法

launch文件中的根元素采用标签定义

启动节点

在这里插入图片描述

pkg:节点所在功能包名称
type:节点的可执行文件名称
name:节点运行时的名称
output:打印节点日志信息到当前终端
respawn:控制节点挂掉自动重启
required:某个节点必须启动
ns:命名空间,避免命名冲突
args:给节点输入参数

参数设置

在这里插入图片描述

重映射

在这里插入图片描述

嵌套

在这里插入图片描述

Rviz

在这里插入图片描述