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坐标系。

 

 

转载于:https://www.cnblogs.com/flyinggod/p/10810215.html

### ROS TFROSTF 在机器人编程中的作用 ROS (Robot Operating System) 提供了一组工具和服务来支持机器人开发,其中 `tf` 是一个非常重要的组件。它用于处理坐标变换关系,在多传感器融合和导航等领域具有广泛的应用。 #### 什么是 ROS TFTF(Transformations Frames)是一个功能强大的库,允许开发者轻松管理多个坐标系之间的转换关系[^1]。通过定义不同坐标系间的相对位置和方向,它可以实现复杂场景下的空间计算。例如,在移动机器人中,可能需要知道激光雷达相对于底盘的位置变化,或者摄像头相对于世界坐标的姿态调整。这些都可以借助 tf 来完成。 以下是关于如何设置并使用 tf 的一些基本概念: - **广播器(Broadcaster)**: 负责发布某个特定帧与其他已知帧之间的时间序列化数据流。 - **监听器(Listener)**: 订阅由广播器发布的消息,并查询任意时刻两个指定框架间的关系。 下面展示了一个简单的 Python 实现例子: ```python import rospy from geometry_msgs.msg import TransformStamped import tf2_ros def broadcast_tf(): br = tf2_ros.TransformBroadcaster() t = TransformStamped() t.header.stamp = rospy.Time.now() t.header.frame_id = "world" t.child_frame_id = "robot_base" t.transform.translation.x = 0.1 t.transform.translation.y = 0.2 t.transform.translation.z = 0.0 q = quaternion_from_euler(0, 0, pi/4) t.transform.rotation.x = q[0] t.transform.rotation.y = q[1] t.transform.rotation.z = q[2] t.transform.rotation.w = q[3] rate = rospy.Rate(10.0) while not rospy.is_shutdown(): br.sendTransform(t) rate.sleep() if __name__ == '__main__': rospy.init_node('my_tf_broadcaster') try: broadcast_tf() except rospy.ROSInterruptException as e: pass ``` 上述代码片段展示了如何创建一个新的 transform 广播节点,该节点会持续发送从 `"world"` 到 `"robot_base"` 坐标系的转换信息[^2]。 #### 使用 C++ 编写类似的程序如下所示: ```cpp #include <ros/ros.h> #include <geometry_msgs/TransformStamped.h> #include <tf2/LinearMath/Quaternion.h> #include <tf2_ros/transform_broadcaster.h> int main(int argc, char** argv){ ros::init(argc, argv, "my_tf_publisher"); ros::NodeHandle nh; tf2_ros::TransformBroadcaster broadcaster; geometry_msgs::TransformStamped transform_stamped; ros::Rate rate(10); while(nh.ok()){ transform_stamped.header.stamp = ros::Time::now(); transform_stamped.header.frame_id = "world"; transform_stamped.child_frame_id = "base_link"; transform_stamped.transform.translation.x = 0.1; transform_stamped.transform.translation.y = 0.2; transform_stamped.transform.translation.z = 0.0; tf2::Quaternion quat; quat.setRPY(0, 0, M_PI / 4); transform_stamped.transform.rotation.x = quat.getX(); transform_stamped.transform.rotation.y = quat.getY(); transform_stamped.transform.rotation.z = quat.getZ(); transform_stamped.transform.rotation.w = quat.getW(); broadcaster.sendTransform(transform_stamped); rate.sleep(); } } ``` 此部分介绍了基于 C++ 的方法去构建同样的功能模块[^3]。 ### 总结 无论是 Python 还是 C++ 接口,ROS 提供了灵活易用的方式让用户可以快速搭建起自己的项目架构。对于初学者而言,《Learning ROS for Robotics Programming Second Edition》是一本不错的入门书籍;而对于更深入的学习,则推荐《ROS机器人编程:原理与应用》作为参考资料。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值