zoukankan      html  css  js  c++  java
  • ROS tf监听编写

    博客转载自:https://www.ncnynl.com/archives/201702/1311.html

    ROS与C++入门教程-tf-编写tf listener(监听)

    说明:

    • 介绍如何使用tf访问坐标系转换

    创建tf的监听

    $ roscd learning_tf
    $ touch src/turtle_tf_listener.cpp
    $ vim src/turtle_tf_listener.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;
    
      ros::service::waitForService("spawn");
      ros::ServiceClient add_turtle =
        node.serviceClient<turtlesim::Spawn>("spawn");
      turtlesim::Spawn srv;
      add_turtle.call(srv);
    
      ros::Publisher turtle_vel =
        node.advertise<geometry_msgs::Twist>("turtle2/cmd_vel", 10);
    
      tf::TransformListener listener;
    
      ros::Rate rate(10.0);
      while (node.ok()){
        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();
          continue;
        }
    
        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;
    };
    
    • 如果在运行时遇到错误"Lookup would require extrapolation into the past",您可以尝试此替代代码来调用侦听器:
    try {
        listener.waitForTransform(destination_frame, original_frame, ros::Time(0), ros::Duration(10.0) );
        listener.lookupTransform(destination_frame, original_frame, ros::Time(0), transform);
    } catch (tf::TransformException ex) {
        ROS_ERROR("%s",ex.what());
    }

    代码解释:

    • 代码: #include <tf/transform_listener.h>
    • 作用:
      • tf包提供了TransformListener的实现,以帮助使接收变换的任务更容易。
      • 要使用TransformListener,我们需要包括tf/transform_listener.h头文件。
    • 代码:tf::TransformListener listener;

    • 作用:

      • 这里,我们创建一个TransformListener对象。
      • 一旦监听器被创建,它开始接收tf转换,并缓冲它们长达10秒。
      • TransformListener对象应该被限定为持久化,否则它的缓存将无法填充,并且几乎每个查询都将失败。
      • 一个常见的方法是使TransformListener对象成为一个类的成员变量。
    • 代码:

    try{
        listener.lookupTransform("/turtle2", "/turtle1",
                                   ros::Time(0), transform);
    }
    • 作用:这里,真正的工作完成了,我们查询监听器进行特定的转换。

    • 让我们来看看四个参数:

    • 1.我们想从/turtle2坐标系开始

    • 2.变换到/turtle1坐标系

    • 3.变换的时间,提供ros::Time(0)即会给出最近的可用的变换。

    • 4.结果存放的变换对象。

    • 这个代码放在try-catch结构,可以获取抛出的异常

    • 代码:

    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) +
    • 作用:
      • 这里,变换用于计算龟的新的线性和角速度,基于它与龟的距离和角度。
      • 新的速度发布在话题"turtle2/cmd_vel"中,turtlesim将使用它来更新turtle2的运动。

    运行监听

    • 打开CMakeLists.txt文件,并在底部添加以下行:
    add_executable(turtle_tf_listener src/turtle_tf_listener.cpp)
    target_link_libraries(turtle_tf_listener ${catkin_LIBRARIES})
    • 编译:
    $ cd ~/catkin_ws
    $ catkin_make
    • 如果一切顺利,你应该在devel/lib/learning_tf文件夹中有一个名为turtle_tf_listener的二进制文件。
    • 之前已经创建start_demo.launch,在 块,合并代码:
     <launch>
        ...
        <node pkg="learning_tf" type="turtle_tf_listener"
              name="listener" />
      </launch>
    • 启动:
     $ roslaunch learning_tf start_demo.launch
    • 你应该看到turtlesim有两只海龟。

    检查结果:

    • 要查看是否有效,只需使用箭头键(确保您的终端窗口处于活动状态,而不是模拟器窗口)绕过第一只乌龟,您会在第一只乌龟之后看到第二只乌龟!
    • 当turtlesim启动时,你可能会看到:
    [ERROR] 1253915565.300572000: Frame id /turtle2 does not exist! When trying to transform between /turtle1 and /turtle2.
    [ERROR] 1253915565.401172000: Frame id /turtle2 does not exist! When trying to transform between /turtle1 and /turtle2.
    
    • 这是因为我们的监听器试图在接收关于龟2的消息之前计算变换,因为它需要一点时间在turtlesim中生成并开始广播一个tf坐标系。
  • 相关阅读:
    WEB 应用缓存解析以及使用 Redis 实现分布式缓存
    MVC 架构模式
    用两个栈实现队列
    重建二叉树
    从尾到头打印链表
    替换空格
    二维数组中的查找
    二叉树与线索二叉树
    OpenYurt:延伸原生 Kubernetes 到边缘场景下的落地实践
    开放下载!解锁 Serverless 从入门到实战大“橙”就
  • 原文地址:https://www.cnblogs.com/flyinggod/p/10810215.html
Copyright © 2011-2022 走看看