在命令行工具中也有一个与transformcaster相类似的工具叫做static_transform_publisher,它能够接受命令行参数来接受位置信息、旋转信息、父框架、子框架以及周期信息,通常在launch文件中来指定。static_transform_publisher主要是变换两个固定坐标系之间的转换,eg:base_link和base_laser是底座与激光雷达之间的变换。

eg:

<node pkg="tf" type="static_transform_publisher" name="broadcaster" args="1 0 0 0 0 0 1 parent child 100">

下面来实现tf的订阅者

新建一个源文件turtle_tf_listener.cpp

在这个订阅者的任务里面主要是调用一个服务再生一个turtle,然后再发布cmd_vel这个主题在turtle2上面用于控制turtle2的轨迹,同时turtle2的轨迹是由transform_listener中得到的transform是由turtle1到turtle2的变换。

#include<ros/ros.h>

#include<tf/transform_listener.h>

#include<geometry_msg/Twist.h>

#include<turtlesim/Spawn.h>

int main(int argc,char **argv)

{

  ros::init(argc,argv,"turtle_tf_listener");//节点名字turtle_tf_listener

  ros::NodeHandle node;

//下面写服务,等待spawn服务,如果服务没有到达就一直等待

  ros::service::waitForService("spawn");

  //创建一个服务的客户端,其类型为turtlesim::Spawn,服务类型为spawn

  ros::ServiceClient add_turtle=node.service<turtlesim::Spawn>("spawn");

  //创建一个turtlesim::Spawn变量

  turtlesim::Spawn srv;

  //调用该服务

  add_turtle.call(srv);

  //下面来写一个publisher,其类型为geometry_msgs::Twist,发布到turtle2/cmd_vel上,消息队列为10

  ros::Pubisher turtle_vel=node.advertise<geometry_msgs::Twist>("turtle2/cmd_vel",10);

  //下面创建一个transform_listener对象

  tf::transformListener listener;

  //指定一个频率

  ros::Rate rate(10.0);

  //判断节点是否被关闭

  while(ros::ok())

{

  //创建一个stampedtransform对象来储存变换的信息

  tf::StampedTransform transform;

  try //在try里面使用lookuptransform

  {

  //其参数使targetframe,sourceframe,time,以及transform它用来储存变换的信息。父框架是turtle2,子框架是turtle1,时间为ros::Time(0)是指把最新的有效信息发布出去,在之前的broadcater中用的是time.now()是把现在的信息发送出去。

  listener.lookupTransform("/turtle2","/turtle1",ros::Time(0),transform);

  }

  catch(tf::TransformException &ex)

  {

    ROS_ERROR("%s",ex.what());//把异常显示在终端上

  ros::Duration(1.0).sleep();//显示的时间为1s。

  continue;

  }

  //从transform中得到一个Twist的消息,然后发布给turtle2,下面实例化一个geometry_msgs

  geometry_msgs::Twist vel_msg;

  //角速度z的值,先指定一个系数4.0,然后其计算方法为atan2。

 vel_msg.angular.z = 4.0* atan2(transform.getOrigin().y(),  transform.getOrigin().x());    

//线速度只指定x,系数设为0.5.其计算方法是使用平方函数。

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 1;

}

回顾一下上面程序包含了哪些内容:

首先,初始化节点,然后调用Spawn服务再生一只乌龟,接着再定义一个publisher发布消息在turtle2/cmd_vel上面,发布的消息为geometry_msg:Twist类型的vel_msg,其内容为transform储存的turtle2到turtle1的变换。

下面到CMakeList.txt里面添加内容

add_executable(turtle_tf_listener src/turtle_tf_listener.cpp)

target_link_libraries(turtle_tf_listener ${catkin_LIBRARIES})

下面再来写一个launch文件。

demo.launch

<launch>

<node  pkg="turtlesim" type="turtlesim_node" name="sim"/>

<node  pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen"/>

<node pkg="learning_tf" type="turtle_tf_broadcaster" args="/turtle1" name="turtle1_tf">

<node pkg="learning_tf" type="turtle_tf_broadcaster" args="/turtle2" name="turtle2_tf">//将/turtle1和/turtle2两个的在世界坐标系中的速度和位置信息发布到tf树上

<node pkg="learning_tf" type="turtle_tf_listener" name="listener">//用来获取/turtle1与/turtle2之间的变换.

</launch>

launch文件的逻辑为首先启动turtlesim_node,然后再启动turtle_teleop_key通过按键来控制它的运动,然后再learning_tf中再生一只乌龟,有两只乌龟,在tf_listener中会发布turtle2/cmd_vel这个主题来控制turtle2的运动,在turtle_tf_broadcaster中同时启动两个节点,一个节点订阅的是turtle1的pose,另一个节点订阅的是turtle2的pose,然后在tf树中广播turtle1和turtle2的位置;然后listener订阅在世界坐标系中的turtle1个turtle2的相对位置,储存在transform中,通过transform中存储的位置信息转化为控制信息。

args是指从命令行输入的参数!!

下面去编译,别忘了增加tf的依赖项。!!!!!!!!

运行roslaunch learning_tf demo.launch

运行仿真工具rosrun rviz rviz

运行之后把tf添加进去。记得把Fixed frame选择为world。

第七课 ROS的空间描述和变换的更多相关文章

  1. 第六课 ROS的空间描述和变换

    1.空间描述与变换 有两个坐标系A和B,B坐标系中有一个点P,如何把B坐标系中的P映射到A坐标系呢,这就涉及到空间描述与变换, 先看一下旋转矩阵: 上面中间的行向量中的元素表示在B坐标系当中的元素用A ...

  2. 第八课 ROS的空间描述和变换

    1.tf的实际应用 1)在机器人的配置中 从上面可以看出激光雷达中心距离机器人底座的中心有20cm,激光雷达的中心距机器人底座中心有10cm,如果激光雷达在障碍物前面0.3米,那么机器人底座离障碍物多 ...

  3. NeHe OpenGL教程 第七课:光照和键盘

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  4. [译]Quartz.NET 框架 教程(中文版)2.2.x 之第七课 触发监听器和作业任务监听器

    第七课:触发监听器和作业任务监听器 监听器是在调度器中基于事件机制执行操作的对象.你大概可以猜到,触发监听器接收响应跟触发器有关的事件,作业任务监听器接收响应跟作业任务有关的事件. 跟触发器有关的事件 ...

  5. Kali Linux Web 渗透测试视频教程— 第七课 OpenVas

    Kali Linux Web 渗透测试视频教程— 第七课 OpenVas 文/玄魂 视频教程地址:http://edu.51cto.com/course/course_id-1887.html 目录 ...

  6. NeHe OpenGL教程 第五课:3D空间

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  7. 【C语言探索之旅】 第二部分第七课:文件读写

    内容简介 1.课程大纲 2.第二部分第七课: 文件读写 3.第二部分第八课预告: 动态分配 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言编写三个游戏 ...

  8. 【C语言探索之旅】 第一部分第七课:循环语句

    内容简介 1.课程大纲 2.第一部分第七课: 循环语句 3.第一部分第八课预告: 第一个C语言小游戏 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言编 ...

  9. 【Cocos游戏实战】功夫小子第七课之游戏主功能场景逻辑功能和暂停功能场景的分析和实现

    CSDN的markdown编辑器是吃屎了么! !.什么玩意.!写了一半写不了东西还全没了,搞个毛线! 本节课的视频教程地址是:第七课在此 假设本教程有帮助到您,希望您能点击进去观看一下,并且如今注冊成 ...

随机推荐

  1. 记录一下 C51 里的位运算

    记录一下 C51 里的位运算 一篇上个世纪的文章<单片机的C语言中位操作用法>1 今天看到一个这样的运算,这相当于清了 XICFG. #define INT1IS1 0x80 #defin ...

  2. base64图片上传,并根据不同项目进行智能修改图片

    前台传图片的base64格式,后台处理方式//处理图片信息 返回对应的路径public function uploadBaseIma($imgArr){ $result = array(); //将路 ...

  3. [三卷天书]ajax请求时接收到乱码的处理方案

    $.ajax({ url: "getmore.ashx", type: "post", dataType: "text", data: { ...

  4. 1017 Queueing at Bank

    题意:银行有K个窗口用于服务,给出所有人的达到时间T和服务时间P,计算所有被服务的客户的平均等待时间.任何客户的服务时间不得超过60分钟.早于08:00到的,要等到08:00:在17:00:01及之后 ...

  5. xml处理模块

    xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,古时候,在json还没诞生的黑暗年代,大家只能选择用xml呀,至今很多传统公司如金融行业的很多系统的 ...

  6. 微信JS-SDK实现自定义分享功能,分享给朋友,分享到朋友圈

    分享出去的内容,可以通过jssdk进行修改. 1.配置jssdk Wx_config.html <?php import("@.ORG.jssdk"); $jssdk = n ...

  7. AD芯片的基准参考电压问题

    基准参考电压的精度一般非常高的! AD芯片 : AD9226的基准参考电压  误差一般是  千分之一! 我之前用万用表测量AD9226的参考电压大概是1.89V(这款AD的正确参考电压应该是2V),所 ...

  8. logistic回归和线性回归

    1.输出: 线性回归输出是连续的.具体的值(如具体房价123万元) 回归 逻辑回归的输出是0~1之间的概率,但可以把它理解成回答“是”或者“否”(即离散的二分类)的问题 分类 2.假设函数 线性回归: ...

  9. Flask之数据库迁徙

    4.3 数据库迁移 在开发过程中,需要修改数据库模型,而且还要在修改之后更新数据库.最直接的方式就是删除旧表,但这样会丢失数据. 更好的解决办法是使用数据库迁移框架,它可以追踪数据库模式的变化,然后把 ...

  10. flask系列二之基础知识

    一.调试模式(debug模式) 1.设置debug模式 在app.run()中传入关键字参数debug,app.run(debug=Ture),就设置当前项目为debug模式.如下所示: # 从fla ...