ROS-TF库-添加坐标系-类似TransformBroadcaster

本文介绍了如何在ROS中使用tf库为/turtle1添加一个名为/carrot1的子坐标系。通过设置坐标系的原点和旋转,实现了随时间变化的坐标系转换,并详细展示了实现这一功能的C++代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 添加子坐标系

  • tf建立了一个框架的树结构;不允许在框架结构中有一个闭合循环。这意味着一个框架只有一个父级,但它可以有多个子级。对于前面的教程,我们的tf树包含三个帧:world、turtle1和turtle2。这两只乌龟是世界的孩子。如果我们想给tf添加一个新的帧,现有的三个帧中的一个需要是父帧,新的帧将成为子帧。
  • 为/turtle1添加一个子坐标系/carrot1代码如下:
#include <ros/ros.h>
#include <tf/transform_broadcaster.h>

int main(int argc, char** argv){
  ros::init(argc, argv, "my_tf_broadcaster");
  ros::NodeHandle node;

  tf::TransformBroadcaster br;
  tf::Transform transform;

  //以10hz的速率来循环执行
  ros::Rate rate(10.0);
  while (node.ok()){
    //transform.setOrigin( tf::Vector3(0.0, 2.0, 0.0) ); //静止tf
    transform.setOrigin( tf::Vector3(2.0*sin(ros::Time::now().toSec()), 2.0*cos(ros::Time::now().toSec()), 0.0) );  //随时间变换tf--- x(-2,2) y(-2 ,2)
    std::cout <<"时间:"<<ros::Time::now()<<" "<<ros::Time::now().toSec()<<" "<< sin(ros::Time::now().toSec())<< std::endl;
    
    transform.setRotation( tf::Quaternion(0, 0, 0, 1) );
    br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "turtle1", "carrot1"));
    rate.sleep();
  }
  return 0;
};

2 运行结果

在这里插入图片描述

### ROS2 中 `tf` 坐标的使用教程 在 ROS2 中,`tf2` 是用于处理坐标系之间转换的核心工具。它继承并改进了 ROS1 的功能,在性能和易用性上有所提升。以下是关于如何在 ROS2 中使用 `tf2` 进行坐标变换的相关说明。 #### 1. 安装必要的包 为了使用 `tf2` 功能,需要安装以下核心包: - `geometry_msgs`: 提供几何数据类型的定义。 - `tf2_ros`: 实现 `tf2` 的 ROS 接口。 - `tf2_geometry_msgs`: 支持将几何消息类型与 `tf2` 结合使用的工具函数。 可以通过以下命令安装这些依赖项: ```bash sudo apt-get install ros-{DISTRO}-geometry-msgs ros-{DISTRO}-tf2-ros ros-{DISTRO}-tf2-geometry-msgs ``` 其中 `{DISTRO}` 需要替换为当前使用的 ROS2 发行版名称(如 `humble`, `foxy` 等)[^3]。 --- #### 2. 创建静态和动态 TF 广播器 ##### (a) 静态广播器 静态广播器适用于不随时间变化的固定坐标系间的关系。可以使用 `static_transform_publisher` 工具来发布静态变换关系: ```bash ros2 run tf2_ros static_transform_publisher "0" "0" "0" "0" "0" "0" "world" "link1" ``` 上述命令表示创建了一个从 `world` 到 `link1` 的静止变换,位置偏移 `(x, y, z)` 和旋转四元数 `(qx, qy, qz, qw)` 均为零[^4]。 ##### (b) 动态广播器 对于随时间变化的坐标系,需编写自定义节点实现动态广播。下面是一个简单的 Python 节点示例: ```python import rclpy from geometry_msgs.msg import TransformStamped from tf2_ros import StaticTransformBroadcaster, TransformBroadcaster def main(args=None): rclpy.init(args=args) node = rclpy.create_node('dynamic_tf_broadcaster') broadcaster = TransformBroadcaster(node) transform = TransformStamped() transform.header.frame_id = 'base_link' transform.child_frame_id = 'laser' while rclpy.ok(): now = node.get_clock().now() transform.header.stamp = now.to_msg() # 设置时间戳 transform.transform.translation.x = 0.1 * now.nanoseconds / 1e9 # 时间相关的位移 transform.transform.rotation.w = 1.0 # 单位四元数 broadcaster.sendTransform(transform) # 发送变换 rclpy.spin_once(node, timeout_sec=0.1) if __name__ == '__main__': main() ``` 此代码实现了从 `base_link` 到 `laser` 的动态变换广播,其 X 方向的位置会随着时间线性增加[^5]。 --- #### 3. 查看 TF 树结构 通过运行以下命令可查看当前系统的 TF 树状态: ```bash ros2 run tf2_tools view_frames ``` 该命令生成一个名为 `frames.pdf` 的文件,描述了所有已发布的坐标系及其相互关系[^6]。 如果希望实时可视化 TF 数据,则可以在 Rviz2 中加载 TF 插件,并配置显示选项。 --- #### 4. 查询坐标变换 查询两个坐标系间的变换可通过 `lookupTransform()` 方法完成。例如,C++ 版本如下所示: ```cpp #include <tf2/LinearMath/Quaternion.h> #include <tf2_ros/buffer.h> #include <tf2_ros/transform_listener.h> int main(int argc, char **argv){ rclcpp::init(argc, argv); auto node = std::make_shared<rclcpp::Node>("tf_lookup"); tf2_ros::Buffer buffer(node->get_clock()); tf2_ros::TransformListener listener(buffer); try { geometry_msgs::msg::TransformStamped transform; transform = buffer.lookupTransform("map", "robot_base", tf2::TimePointZero); // 获取 map -> robot_base 变换 RCLCPP_INFO(node->get_logger(), "Translation: (%f, %f, %f)", transform.transform.translation.x, transform.transform.translation.y, transform.transform.translation.z); } catch(const tf2::TransformException &ex) { RCLCPP_ERROR(node->get_logger(), "%s", ex.what()); } rclcpp::shutdown(); } ``` 这段程序尝试获取 `map` 到 `robot_base` 的最新变换矩阵,并打印平移分量[^7]。 --- #### 5. 解决常见错误 当遇到无法找到指定坐标系或超时等问题时,可能的原因包括但不限于: - 目标坐标系尚未被广播到网络中; - 当前节点未正确订阅 TF 主题 `/tf` 或 `/tf_static`; - 计算机的时间同步设置存在问题(尤其是多机器环境下的 NTP 同步失败情况)。 针对这些问题,建议逐一排查以上可能性,并确保所有参与方均正常工作[^8]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值