ROS之tf坐标变换

2023-05-16

1、什么是tf变换

        ROS中的很多软件包都需要机器人发布tf变换树,那么什么是tf变换树呢?抽象的来讲,一棵tf变换树定义了不同坐标系之间的平移与旋转变换关系。具体来说,我们假设有一个机器人,包括一个机器人移动平台和一个安装在平台之上的激光雷达,以这个机器人为例,定义两个坐标系,一个坐标系以机器人移动平台的中心为原点,称为base_link参考系,另一个坐标系以激光雷达的中心为原点,称为base_laser参考系。

image

        假设在机器人运行过程中,激光雷达可以采集到距离前方障碍物的数据,这些数据当然是以激光雷达为原点的测量值,换句话说,也就是base_laser参考系下的测量值。现在,如果我们想使用这些数据帮助机器人完成避障功能,当然,由于激光雷达在机器人之上,直接使用这些数据不会产生太大的问题,但是激光雷达并不在机器人的中心之上,在极度要求较高的系统中,会始终存在一个雷达与机器人中心的偏差值。这个时候,如果我们采用一种坐标变换,将及激光数据从base_laser参考系变换到base_link参考下,问题不就解决了么。这里我们就需要定义这两个坐标系之间的变换关系。

         为了定义这个变换关系,假设我们已知激光雷达安装的位置在机器人的中心点上方20cm,前方10cm处。这就根据这些数据,就足以定义这两个参考系之间的变换关系:当我们获取激光数据后,采用(x: 0.1m, y: 0.0m, z: 0.2m)的坐标变换,就可以将数据从base_laser参考系变换到base_link参考系了。当然,如果要方向变化,采用(x: -0.1m, y: 0.0m, z: -0.20m)的变换即可。

        从上边的示例看来,参考系之间的坐标变换好像并不复杂,但是在复杂的系统中,存在的参考系可能远远大于两个,如果我们都使用这种手动的方式进行变换,估计很快你就会被繁杂的坐标关系搞蒙了。ROS提供的tf变换就是为解决这个问题而生的,tf功能包提供了存储、计算不同数据在不同参考系之间变换的功能,我们只需要告诉tf树这些参考系之间的变换公式即可,这颗tf树就可以树的数据结构,管理我们所需要的参考系变换。

image

       还是以上边的示例为基础,为了定义和存储base_linkbase_laser两个参考系之间的关系,我们需要将他们添加到tf树中。从树的概念上来讲,tf树中的每个节点都对应一个参考系,而节点之间的边对应于参考系之间的变换关系。tf就是使用这样的树结构,保证每两个参考系之间只有一种遍历方式,而且所有变换关系,都是母节点到子节点的变换。

        为了定义上边示例中的参考系,我们需要定义两个节点,一个对应于base_link参考系,一个对应于base_laser参考系。为了创建两个节点之间的边,我们首先需要决定哪一个节点作为母节点,哪一个节点作为子节点,这一点在tf树中是非常重要的。这里我们选择base_link作为母节点,这样会方便后边为机器人添加更多的传感器作为子节点。所以,根据之前的分析,从base_link节点到base_laser节点的变换关系为(x: 0.1m, y: 0.0m, z: 0.2m)。设置完毕后,我们就可以通过调用tf库,直接完成base_laser参考系到base_link参考系的数据坐标变换了。

2、代码流程

       通过上边的分析,应该可以从理论上帮助你理解什么是tf,以及tf的功能了。在实际应用中,我们需要使用代码来完成这些理论,下边我们就来看看如何使用代码来调用tf的变换。

       代码的总体思路分为两个部分:

       1)编写一个节点,广播两个参考系之间的tf变换关系

       2)编写另外一个节点,订阅tf树,然后从tf树中遍历到两个参考系之间的变换公式,然后通过公式计算数据的变换。

        我们先来完成第一步。首先我们来创建一个功能包,用于后边程序的放置,这里需要依赖roscpptfgeometry_msgs

  1. 
    $ cd %TOP_DIR_YOUR_CATKIN_WS%/src  
  2. 
    $ catkin_create_pkg robot_setup_tf roscpp tf geometry_msgs  

3、编写广播节点      

       进入功能包,创建src/tf_broadcaster.cpp文件,来完成广播节点的代码:

  1. 
    #include <ros/ros.h>  
  2. 
    #include <tf/transform_broadcaster.h>  
  3. 
       
  4. 
    int main(int argc, char** argv){  
  5. 
      ros::init(argc, argv, "robot_tf_publisher");  
  6. 
      ros::NodeHandle n;  
  7. 
       
  8. 
      ros::Rate r(100);  
  9. 
       
  10. 
      tf::TransformBroadcaster broadcaster;  
  11. 
       
  12. 
      while(n.ok()){  
  13. 
        broadcaster.sendTransform(  
  14. 
          tf::StampedTransform(  
  15. 
            tf::Transform(tf::Quaternion(0, 0, 0, 1), tf::Vector3(0.1, 0.0, 0.2)),  
  16. 
            ros::Time::now(),"base_link", "base_laser"));  
  17. 
        r.sleep();  
  18. 
      }  
  19. 
    }  

   逐行分析如上代码:

  1. 
    #include <tf/transform_broadcaster.h>  

        因为后边会使用到tf::TransformBroadcaster类的实例,来完成tf树的广播,所以需要先包含相关的头文件。

  1. 
    tf::TransformBroadcaster broadcaster;  

     创建一个tf::TransformBroadcaster类的实例,用来广播 base_link → base_laser的变换关系。

  1. 
       broadcaster.sendTransform(  
  2. 
          tf::StampedTransform(  
  3. 
            tf::Transform(tf::Quaternion(0, 0, 0, 1), tf::Vector3(0.1, 0.0, 0.2)),  
  4. 
            ros::Time::now(),"base_link", "base_laser"));  

    这部分是代码的关键所在。通过TransformBroadcaster 类来发布变换关系的接口,需要五个参数。首先是两个参考系之间的旋转变换,通过btQuaternion四元数来存储旋转变换的参数,因为我们用到的两个参考系没有发生旋转变换,所以倾斜角、滚动角、偏航角都是0。第二个参数是坐标的位移变换,我们用到的两个参考系在X轴和Z轴发生了位置,根据位移值填入到btVector3 向量中。第三个参数是时间戳,直接太难过ROSAPI完成。第四个参数是母节点存储的参考系,即base_link,最后一个参数是子节点存储的参考系,即base_laser

4、编写订阅节点

        上一节讲解了如何使用代码编写一个广播tf变换的节点,这一节,我们编写一个订阅tf广播的节点,并且使用tf树中base_linkbase_laser的变换关系,完成数据的坐标变换。在robot_setup_tf功能包中创建src/tf_listener.cpp文件,代码如下:

  1. 
    #include <ros/ros.h>  
  2. 
    #include <geometry_msgs/PointStamped.h>  
  3. 
    #include <tf/transform_listener.h>  
  4. 
       
  5. 
    void transformPoint(const tf::TransformListener& listener){  
  6. 
      //we'll create a point in the base_laser frame that we'd like to transform to the base_link frame  
  7. 
      geometry_msgs::PointStamped laser_point;  
  8. 
      laser_point.header.frame_id = "base_laser";  
  9. 
       
  10. 
      //we'll just use the most recent transform available for our simple example  
  11. 
      laser_point.header.stamp = ros::Time();  
  12. 
       
  13. 
      //just an arbitrary point in space  
  14. 
      laser_point.point.x = 1.0;  
  15. 
      laser_point.point.y = 0.2;  
  16. 
      laser_point.point.z = 0.0;  
  17. 
       
  18. 
      try{  
  19. 
        geometry_msgs::PointStamped base_point;  
  20. 
        listener.transformPoint("base_link", laser_point, base_point);  
  21. 
       
  22. 
        ROS_INFO("base_laser: (%.2f, %.2f. %.2f) -----> base_link: (%.2f, %.2f, %.2f) at time %.2f",  
  23. 
            laser_point.point.x, laser_point.point.y, laser_point.point.z,  
  24. 
            base_point.point.x, base_point.point.y, base_point.point.z, base_point.header.stamp.toSec());  
  25. 
      }  
  26. 
      catch(tf::TransformException& ex){  
  27. 
        ROS_ERROR("Received an exception trying to transform a point from \"base_laser\" to \"base_link\": %s", ex.what());  
  28. 
      }  
  29. 
    }  
  30. 
       
  31. 
    int main(int argc, char** argv){  
  32. 
      ros::init(argc, argv, "robot_tf_listener");  
  33. 
      ros::NodeHandle n;  
  34. 
       
  35. 
      tf::TransformListener listener(ros::Duration(10));  
  36. 
       
  37. 
      //we'll transform a point once every second  
  38. 
      ros::Timer timer = n.createTimer(ros::Duration(1.0), boost::bind(&transformPoint, boost::ref(listener)));  
  39. 
       
  40. 
      ros::spin();  
  41. 
       
  42. 
    }  

   进行详细的分析:

  1. 
    #include <tf/transform_listener.h>  

   在后边的代码中,我们会使用到tf::TransformListener对象,该对象会自动订阅ROS中的tf消息,并且管理所有的变换关系数据。所以需要先包含相关的头文件。

  1. 
    void transformPoint(const tf::TransformListener& listener){  

   我们创建一个回调函数,每次收到tf消息时,都会自动调用该函数,上一节我们设置了发布tf消息的频率是1Hz,所以回调函数执行的频率也是1Hz。在回调函数中,我们需要完成数据从base_laserbase_link参考系的坐标变换。

  1. 
    //we'll create a point in the base_laser frame that we'd like to transform to the base_link frame  
  2. 
      geometry_msgs::PointStamped laser_point;  
  3. 
      laser_point.header.frame_id = "base_laser";  
  4. 
       
  5. 
      //we'll just use the most recent transform available for our simple example  
  6. 
      laser_point.header.stamp = ros::Time();  
  7. 
       
  8. 
      //just an arbitrary point in space  
  9. 
      laser_point.point.x = 1.0;  
  10. 
      laser_point.point.y = 0.2;  
  11. 
      laser_point.point.z = 0.0;  

   我们创建了一个geometry_msgs::PointStamped类型的虚拟点,该点的坐标为(1.00.20.0)。该类型包含标准的header消息结构,这样,我们可以就可以在消息中加入发布数据的时间戳和参考系的id

  1. 
    try{  
  2. 
        geometry_msgs::PointStamped base_point;  
  3. 
        listener.transformPoint("base_link", laser_point, base_point);  
  4. 
       
  5. 
        ROS_INFO("base_laser: (%.2f, %.2f. %.2f) -----> base_link: (%.2f, %.2f, %.2f) at time %.2f",  
  6. 
            laser_point.point.x, laser_point.point.y, laser_point.point.z,  
  7. 
            base_point.point.x, base_point.point.y, base_point.point.z, base_point.header.stamp.toSec());  
  8. 
      }  

   这里是代码的关键位置。我们已经在base_laser参考系下虚拟了一个数据点,那么怎样将该点的数据转换到base_base参考系下呢?使用TransformListener 对象中的transformPoint()函数即可,该函数包含三个参数:第一个参数是需要转换到的参考系id,当然是base_link了;第二个参数是需要转换的原始数据;第三个参数用来存储转换完成的数据。该函数执行完毕后,base_point就是我们转换完成的点坐标了!

  1. 
    catch(tf::TransformException& ex){  
  2. 
        ROS_ERROR("Received an exception trying to transform a point from \"base_laser\" to \"base_link\": %s", ex.what());  
  3. 
      }  

   为了保证代码的稳定性,我们也需要应对出错处理,例如当tf并没有发布需要的变换关系时,在执行transformPoint时就会出现错误。

5、编译代码

     到此为止,我们已经完成了代码编写的全部流程,接下来就是编译代码了!打开功能包的CMakeLists.txt文件,加入相应的编译选项:

  1. 
    add_executable(tf_broadcaster src/tf_broadcaster.cpp)  
  2. 
    add_executable(tf_listener src/tf_listener.cpp)  
  3. 
    target_link_libraries(tf_broadcaster ${catkin_LIBRARIES})  
  4. 
    target_link_libraries(tf_listener ${catkin_LIBRARIES})  

     然后保存文件,经行编译:

  1. 
    $ cd %TOP_DIR_YOUR_CATKIN_WS%  
  2. 
    $ catkin_make  

6、运行代码

     终于来到最激动人心的一步,见证奇迹的时刻就要来临!

     打开一个终端,运行roscore

  1. 
    roscore  

     再打开一个终端,运行tf广播tf_broadcaster

  1. 
    rosrun robot_setup_tf tf_broadcaster  

     还要再打开一个终端,运行tf监听tf_listener,将我们虚拟的点坐标,从base_laser转换到base_link参考系下:

  1. 
    rosrun robot_setup_tf tf_listener  

     如果一切正常,你应该已经可以在第三个终端中看到如下的数据了:

[ INFO] 1248138528.200823000: base_laser: (1.00, 0.20. 0.00) -----> base_link: (1.10, 0.20, 0.20) at time 1248138528.19

[ INFO] 1248138529.200820000: base_laser: (1.00, 0.20. 0.00) -----> base_link: (1.10, 0.20, 0.20) at time 1248138529.19

[ INFO] 1248138530.200821000: base_laser: (1.00, 0.20. 0.00) -----> base_link: (1.10, 0.20, 0.20) at time 1248138530.19

[ INFO] 1248138531.200835000: base_laser: (1.00, 0.20. 0.00) -----> base_link: (1.10, 0.20, 0.20) at time 1248138531.19

[ INFO] 1248138532.200849000: base_laser: (1.00, 0.20. 0.00) -----> base_link: (1.10, 0.20, 0.20) at time 1248138532.19

     从上边的信息中,我们可以清晰的看到,我们虚拟的坐标点,成功转换到了base_link参考系下,坐标位置变换成了(1.10, 0.20, 0.20)。

     到此为止,我们已经完成了例程的所有讲解,在你需要完整的真实系统中,请根据需求将PointStamped数据类型修改成你所使用传感器发布的实际消息对应类型。

 

参考链接:http://wiki.ros.org/navigation/Tutorials/RobotSetup/TF

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ROS之tf坐标变换 的相关文章

  • Python:TypeError: 'int' object is not callable

    一个函数的部分代码如下 xff1a python view plain copy def loadData len 61 dataSet len trainingSet extend dataSet len 3 4 testSet exte
  • FreeRTOS — 消息队列

    以下内容转载自安富莱电子 xff1a http forum armfly com forum php FreeRTOS 的一个重要的通信机制 消息队列 xff0c 消息队列在实际项目中应用较多 1 消息队列 1 1 消息队列的概念及其作用
  • 学校人力资源管理系统——物理结构设计

    新 建学校人力资源管理系统 数据库 1 创建相关表 1 1 创建部门信息表 部门信息表的创建代码如下 xff0c 部门信息表在SQL中的信息显示如图6 1所示 create table 部门信息表 部门编号 char 6 not null
  • python 安装serial模块

    想用Python来实现对串口的控制 xff0c 写好了脚本 xff0c 现在将这个脚本拿到另外一个电脑上去运行 xff1b 运行时提示错误 xff0c 说是没有安装serial模块 xff0c 于是乎安装 pip install seria
  • Doxygen使用教程(个人总结)

    简介Doxygen 一 xff0e 什么是Doxygen Doxygen 是一个程序的文件产生工具 xff0c 可将程序中的特定批注转换成为说明文件 通常我们在写程序时 xff0c 或多或少都会写上批注 xff0c 但是对于其它人而言 xf
  • STM32F401 I2S(full duplex)全双工示例代码

    USER CODE BEGIN Header 64 file main c 64 brief Main program body This notice applies to any and all portions of this fil
  • 一、认识与学习Linux中的BASH 之 1.1 什么是bash

    1 1 什么是bash 1 1 1 什么是bash bash全称为The Bourne Again shell xff0c 是Bourne Shell的扩展 xff0c 是基于GUN构架发展出来的语言 xff0c 有很灵活和强大的编程接口
  • 阿里云ECS服务器环境搭建(1) —— ubuntu 16.04 图形界面的安装

    阿里云ECS服务器环境搭建 xff08 1 xff09 ubuntu 16 04 图形界面的安装 1 背景 在我们购买阿里云ECS服务器之后 xff0c 默认的系统环境是很干净的 xff0c 我购买的是ubuntu16 04 xff0c 远
  • Python+pandas+每天股票涨了多少

    第一步 xff1a 得到某支股票历年来的交易数据 方法见 xff1a https blog csdn net zwy 0309 article details 108217342 在此 xff0c 我使用以下脚本得到股票 xff08 代码
  • 2021-06-02

    在ROS中仿真模型中添加gps传感器 获取gps传感器模型包为自己的机器人添加gps传感器将gps之中的经度纬度坐标转化为自己地图中的坐标 1 获取gps传感器模型包 link http wiki ros org hector gazebo
  • Dockerfile如何编写(指令详解)

    本文个人博客地址 xff1a https www leafage top posts detail 21525V8AP Dockerfile Dockerfile 描述了组装镜像的步骤 xff0c 其中每条指令都是单独执行的 除了FROM指
  • 关于Home Lab的搭建——硬件选择篇(迷你主机)(一)

    关于Home Lab 这个名词出自哪里 xff0c 我也不清楚 不过 xff0c 可以这样来理解Home Lab xff0c Home Lab是一台作为实验使用的电脑 xff0c 试验的内容多数是关于计算机网络的搭建 系统安装 测试 xff
  • Adaboost基本二分类算法

    最早类型的Adaboost是由Yoav Freund和Robert E Schapire提出的 xff0c 一种用于二分类的boosting集成学习方法 也是李航 统计学习方法 中所介绍的Adaboost 它将一系列弱分类器的线性组合 xf
  • Springboot 项目金蝶中间件AAS-9.0启动报错 javax.persistence.Table.indexes()[Ljavax/persistence/Index 问题解决

    Springboot 项目金蝶中间件AAS 9 0启动报错 java lang NoSuchMethodError javax persistence Table indexes Ljavax persistence Index问题解决方法
  • CMakeLists配置(常用的)

    一 xff1a 最小组成 cmake 最小版本需求 cmake minimum required VERSION 2 8 project 名字 project MyEsp32AllCode 可执行文件生成 add executable PR
  • SLAM学习笔记(四)定位

    原创博客 xff1a http blog csdn net renshengrumenglibing viewmode 61 contents 机器人定位的目的是为了知道 自己在什么地方 xff0c 目前 xff0c 机器人定位的方法可以分
  • SLAM实习岗位面经

    一 地平线 一面主要是在问关于SLAM岗位的技术问题 xff0c 然后还问了一些比较简单的C 43 43 基础知识 其实总体而言 xff0c 面试的问题都比较基础 xff0c 比较考验SLAM基本功 xff0c 如果只知道一些SLAM皮毛的
  • Canal数据库监听

    1 什么是canal canal是用java开发的基于数据库增量日志解析 xff0c 提供增量数据订阅 amp 消费的中间件 目前 xff0c canal主要支持了MySQL的binlog解析 xff0c 解析完成后才利用canal cli
  • linux下安裝mitmproxy 详解傻瓜式文档

    前言 xff1a mitmproxy 就是用于 MITM 的 proxy xff0c MITM 即中间人攻击 xff08 Man in the middle attack xff09 用于中间人攻击的代理首先会向正常的代理一样转发请求 xf
  • ROS学习笔记(2)——ROS架构

    ROS学习笔记 xff08 2 xff09 ROS架构 0 学习来源1 ROS架构2 文件系统级2 1 工作空间 3 计算图级4 ROS开源社区级4 1 发行版 xff08 Distribution xff09 4 2 软件库 xff08

随机推荐

  • STM32_中断

    STM32 中断 一 介绍 1 1解释 打断CPU执行正常的程序 xff0c 转而处理紧急程序 xff0c 然后返回原暂停的程序继续运行 xff0c 就叫中断 1 2作用和意义 作用 xff1a 实时控制 xff1a 在确定时间内对相应事件
  • Oracle创建用户并授权

    很多时候 xff0c 我们不需要用系统原始的sys xff0c sysdba等系统账户 xff0c 需要创建个性化的用户并授权 xff0c 那就需要我们首先登录到dba账户 xff0c 然后通过dba账户进行用户创建并授权 1 用dba权限
  • 【Linux】vim 中批量添加注释

    本期主题 xff1a vim 中批量添加注释博客主页 xff1a 小峰同学分享小编的在Linux中学习到的知识和遇到的问题小编的能力有限 xff0c 出现错误希望大家不吝赐 此文主要介绍两种方法 xff1a 方法一 xff1a 块选择模式
  • 对gazebo启动后黑屏或者没有模型的解决

    1 问题 卡在加载模型界面 xff1b 加载太慢或者黑屏 xff1a 报错信息如下 xff1a 图1 打开界面 xff1a 图2 2 解决办法 直接下载所有模型到用户的根目录下的 gazebo models 下 xff1a 方法1 xff1
  • 【Python与机器学习】5.K-Means聚类

    聚类 xff08 clustering xff09 什么是聚类 聚类属于无监督学习 xff08 unsupervised learning xff09 xff0c 即无类别标记 是数据挖掘经典算法之一 算法接收参数k xff1b 然后将样本
  • 穿过已知点画平滑曲线(3次贝塞尔曲线)

    为了把一串点连成光滑的曲线 xff0c 先研究贝塞尔曲线 xff0c 又搞B样条插值 都没有成功 数学没那么强 后来在 翻译 AGG 之贝塞尔插值 http liyiwen javaeye com blog 705489 看到一种比较好的方
  • 二值信号量和互斥锁到底有什么区别?

    原文链接 xff1a https www cnblogs com codescrew p 8970514 html 在说明之前我先抛出结论 xff1a 互斥锁和二值信号量在使用上非常相似 xff0c 但是互斥锁解决了优先级翻转的问题 假定我
  • 使用stm32CubeMX自动配置的工程文件,进行串口的不定长接收(非DMA方式)

    方法描述 xff1a 使用stm32CubeMX自动配置的工程文件 xff0c 进行串口的不定长接收 xff08 非DMA方式 xff09 实际问题解决尝试 xff1a 1 HAL库函数只有接收定长数据HAL UART Receive xf
  • 基于STM32平台的BMP180测试(模拟IIC)

    1 测试描述 xff1a 使用模拟IIC xff0c 从BMP180中获取ID号 温度值 气压值以及计算海拔高度 2 测试准备 xff1a 硬件平台 xff1a 原子战舰V3开发板 测试工具 xff1a 逻辑分析仪 串口调试工具 3 数据手
  • gitee 添加ssh公钥

    首先需要安装git 打开 Git Bash 在Bash中输入 ssh keygen t rsa C 34 xxxx 64 yyy com 34 用你的邮件地址进行替换 连着按三次回车 xff0c 第一次提示 34 Enter file in
  • ROS中使用<serial/serial.h>头文件

    ROS中使用 lt serial serial h gt 头文件 问题描述 编译后出现fatal error serial serial h 没有那个文件或目录 include lt serial serial h gt 解决办法 缺少se
  • realsenseD435i使用IMU出错

    realsense 使用IMU出错 已经参照blogs xff1a https blog csdn net weixin 46363611 article details 114643088 将 realsense ws src reals
  • 对极几何,PNP,ICP求解位姿的方法原理、优缺点

    文章目录 一 对极几何估计位姿1 本质矩阵或基础矩阵估计2 单应矩阵估计3 2D 2D时 xff0c 空间点位置计算 二 PNP估计位姿1 P3P方法估计位姿2 DLT方法估计位姿3 EPnP方法估计位姿3 BA方法估计位姿 三 ICP方法
  • 顺序表查找与散列表(哈希表)

    文章目录 一 数据结构二 平均查找长度 xff08 ASL xff09 三 顺序表查找1 顺序查找2 折半查找3 分块查找4 顺序表查找的对比 四 散列表1 散列表构造2 开放地址散列表构造3 散列表查找效率分析 一 数据结构 二 平均查找
  • You‘ll have to kill the Xtightvnc process manually

    You 39 ll have to kill the Xtightvnc process manually 然后 pkill u user
  • ubuntu Linux多个内核选择

    一 问题 ununtu经常自动升级 xff0c 或者是我们在update时 xff0c 系统自动升级内核 此时会导致较高版本的内核与系统相互矛盾 xff0c 而导致卡机等问题 此时需要对多余内核进行设置为默认内核或者将不正确内核删除 两种方
  • 东北天(ENU)和北东地(NED)

    文章目录 一 坐标系定义1 东北天坐标系 xff08 ENU xff09 2 北东地坐标系 xff08 NED xff09 二 在ENU坐标系向量变换到NED坐标系向量三 将载体相对ENU的姿态和位置 xff0c 变换为载体相对NED的姿态
  • opencv for arm

    大家好 xff0c 这篇文章介绍了在arm开发板上移植opencv的过程 虚拟机 xff1a Ubuntu16 04 64位 单板 xff1a jz2440 编译器 xff1a arm linux gcc 4 4 3 opencvbanbo
  • 多传感器数据融合算法综述

    多传感器数据融合是一个新兴的研究领域 xff0c 是针对一个系统使用多种传感器这一特定问题而展开的一种关于数据处理的研究 多传感器数据融合技术是近几年来发展起来的一门实践性较强的应用技术 xff0c 是多学科交叉的新技术 xff0c 涉及到
  • ROS之tf坐标变换

    1 什么是tf 变换 ROS 中的很多软件包都需要机器人发布tf 变换树 xff0c 那么什么是tf 变换树呢 xff1f 抽象的来讲 xff0c 一棵tf 变换树定义了不同坐标系之间的平移与旋转变换关系 具体来说 xff0c 我们假设有一