GroundTrue和里程计输出的位姿的参考坐标系不一致的情况

news2024/11/15 22:58:26

这里写目录标题

    • 前言
    • 数据集描述
    • 使用TF工具包获取
    • 使用Eigen库计算
    • 置换输出
    • 误差对比
      • 没做转换之前
      • 转换之后

前言

最近遇到一个数据集的ground true参考坐标和vSLAM输出的位姿的参考坐标不一样的问题,记录一下。

在之前参加的一个PRCV 2022的多传感器融合SLAM挑战赛中也同样遇到类似的问题:

image-20230101144353721

因为之前一直忙于其他事情没有记录,这里记录一下,其实解决办法很简单,就是在最后输出的位姿做一个坐标变换即可

数据集描述

最近需要使用到一个由清华大学一个团队构建的数据集 OpenLORIS-Scene Dataset 这个数据是一个做动态场景SLAM比较合适的数据集,里面包含很多行人干扰的场景。它的数据集采集平台是一个类似于服务机器人的平台:

image-20230101144100298

它上面传感器的坐标系如图所示:

image-20230101144149206

因为数据集中的真值是机器人base_linkgt_map坐标系的仿射变换,但是使用vinsfusion得到的位姿的载体是D435iIMU的,所以我们在最后输出位姿的时候需要转换到base_link坐标系下。

数据集中的各个传感器之间的静态TF变换在话题/tf_static中进行了发布,但是这里没有直接d400_imubase_link的TF变换。下面是echo这个话题的输出

transforms:
  -
    header:
      seq: 0
      stamp:
        secs: 0
        nsecs:         0
      frame_id: "base_link"
    child_frame_id: "laser"
    transform:
      translation:
        x: 0.35
        y: 0.0
        z: 1.28
      rotation:
        x: -0.009737
        y: 0.05002
        z: -0.004493
        w: 0.9986
  -
    header:
      seq: 0
      stamp:
        secs: 0
        nsecs:         0
      frame_id: "laser"
    child_frame_id: "d400_color"
    transform:
      translation:
        x: 0.0559649
        y: 0.0311189
        z: -0.0756753
      rotation:
        x: -0.52531
        y: 0.494111
        z: -0.469561
        w: 0.50933
  -
    header:
      seq: 0
      stamp:
        secs: 0
        nsecs:         0
      frame_id: "d400_color"
    child_frame_id: "d400_depth"
    transform:
      translation:
        x: 0.0147083755582571
        y: 3.83682090614457e-05
        z: 0.000288475974230096
      rotation:
        x: 0.000504782
        y: 0.00444093
        z: -0.00264019
        w: 0.999987
  -
    header:
      seq: 0
      stamp:
        secs: 0
        nsecs:         0
      frame_id: "d400_color"
    child_frame_id: "d400_imu"
    transform:
      translation:
        x: 0.0200968869030476
        y: -0.0050785536877811
        z: -0.0115051260218024
      rotation:
        x: -0.000504782
        y: 0.00444093
        z: -0.00264019
        w: 0.999987
  -
    header:
      seq: 0
      stamp:
        secs: 0
        nsecs:         0
      frame_id: "base_link"
    child_frame_id: "t265_fisheye1"
    transform:
      translation:
        x: 0.873
        y: 0.026
        z: 0.68
      rotation:
        x: -0.395
        y: 0.406
        z: -0.6
        w: 0.565
  -
    header:
      seq: 0
      stamp:
        secs: 0
        nsecs:         0
      frame_id: "t265_fisheye1"
    child_frame_id: "t265_fisheye2"
    transform:
      translation:
        x: 0.0640782490372658
        y: 0.000390329543733969
        z: -0.000322926469380036
      rotation:
        x: 0.00186088
        y: 0.0031785
        z: 0.000162728
        w: 0.999993
  -
    header:
      seq: 0
      stamp:
        secs: 0
        nsecs:         0
      frame_id: "t265_fisheye1"
    child_frame_id: "t265_imu"
    transform:
      translation:
        x: 0.0106999985873699
        y: 7.27595761418343e-12
        z: -2.91038304567337e-11
      rotation:
        x: 0.00554841
        y: 0.00136098
        z: 0.99998062
        w: -0.00245956
---

既然没有直接的结果,那我们通过 d400_imu ——> d400_color ——> laser ——> base_link 的变换关系来获得

使用TF工具包获取

使用ros里面的工具包,来监听两个坐标系之间的变换

rosrun tf tf_echo base_link d400_imu

播放数据集之后得到:

image-20230101114051393

直接从这个TF读出来的感觉还是有挺大误差的,因为那个欧拉角旋转应该理论上接近90°才比较正常。下面,我们通过手动计算出来看看有多大差别

使用Eigen库计算

#include <iostream>
#include <vector>
#include <algorithm>
#include <Eigen/Core>
#include <Eigen/Geometry>

int convert()
{
  Eigen::Quaterniond q_ci(0.999987, -0.000504782, 0.00444093, -0.00264019);
  Eigen::Vector3d t_ci(0.0200968869030476, -0.0050785536877811, -0.0115051260218024); 
  Isometry3d T_ci(q_ci);
  T_ci.pretranslate(t_ci);

  Eigen::Quaterniond q_lc(0.50933, -0.52531, 0.494111, -0.469561);
  Eigen::Vector3d t_lc(0.0559649, 0.0311189, -0.0756753); 
  Isometry3d T_lc(q_lc);
  T_lc.pretranslate(t_lc);

  Eigen::Quaterniond q_bl(0.9986, -0.009737, 0.05002, -0.004493);
  Eigen::Vector3d t_bl(0.35, 0.0, 1.28); 
  Isometry3d T_bl(q_bl);
  T_bl.pretranslate(t_bl);

  Isometry3d T_bi = T_bl * T_lc * T_ci;
  Eigen::Quaterniond q_bi(T_bi.rotation());
  cout <<"Rotation Matrix: \n" << T_bi.matrix() << endl;
  cout << "Quaternion    " << q_bi.coeffs().transpose() << endl;
  cout << "Translation   " << T_bi.translation().transpose() << endl;
  cout << "RPY (degree): " << T_bi.rotation().eulerAngles(2, 1, 0).transpose()*180/M_PI << endl;
  return 0;
};

输出如下:

image-20230101122330869

可以看到,这里我们手动计算得到的结果和直接从TF监听得到的结果还是有差别的,主要在于TF监听得到的结果的精度是比较低的,他舍去了小数点后一些位,导致在反复累乘过程中积累了一定的误差。后面我们还是直接使用我们手动计算出来的结果。

置换输出

在代码中添加一个变换函数

    static Eigen::Isometry3d transformBaselink(const Eigen::Quaterniond& q, const Eigen::Vector3d& t) {
        Eigen::Isometry3d Twi(q);
        Twi.pretranslate(t);

        Eigen::Isometry3d Tbi(Eigen::Quaterniond(0.550447, -0.51761, 0.453209, -0.472959));
        Tbi.pretranslate(Eigen::Vector3d(0.388943, 0.0084219, 1.20522));

        Eigen::Isometry3d Twb = Tbi * Twi * Tbi.inverse();
        return Twb;
    }

然后在保存位姿之前做一次转换即可

image-20230101154329158

误差对比

下面我们跑同一个数据集输出用输出的位姿和真值做评估,对比一下做了这个转换和没做这个转换看看有多大的差别

没做转换之前

image-20230101154604304

转换之后

image-20230101161633252

从上面结果来看,确实是会有一定的影响,平均误差降低了不少,在没做转换之后平均误差在1.3m左右,转换为真值参考坐标之后平均误差在1.1m左右,最大偏差也减少了不少。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/132754.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MATLAB读取tif格式图像

tif格式数据本质上就是带有地理信息的矩阵数据。 geotiffread函数 MATLAB帮助-geotiffread 语法Syntax&#xff1a; [A,R] geotiffread(filename) [X,cmap,R] geotiffread(filename) [A,refmat,bbox] geotiffread(filename) [X,cmap,refmat,bbox] geotiffread(filenam…

Symbol详解

Symbol Symbol是es6引入的一个新的原始数据类型&#xff0c;是一个独一无二的值。 目前为止&#xff0c;js的数据类型有以下几种&#xff1a; 数据类型说明undefinedundefinednullnullboolean布尔值string字符串number数字Bigint大整数Object对象SymbolSymbol Symbol通过Symb…

[go学习笔记.第十八章.数据结构] 2.约瑟夫问题,排序,栈,递归,哈希表,二叉树的三种遍历方式

一.约瑟夫问题 josephu 问题: 设编号为1, 2 &#xff0c;... n 的n个人围坐一圈, 约定编号为 k (1<k<n &#xff09;的人从 1 开始报数&#xff0c;数到m的那个人出列&#xff0c;它的下一位又从1开始报数&#xff0c;数到 m 的那个人又出列&#xff0c;依次类推&#xf…

ActivityManagerService

1 AMS 家族 ActivityManagerService&#xff08;AMS&#xff09;主要负责系统中四大组件的启动、切换、调度以及应用程序的管理和调度工作&#xff0c;其职责与操作系统中的进程管理和调度模块类似。ActivityManagerService 进行初始化的时机很明确&#xff0c;就是在 system_…

计算机组成原理“上分秘籍”——数据的表示和运算

前言 上分地图 目录 前言 上分地图 猜你想问 Q1&#xff1a;为何要研究数据表示问题&#xff1f; Q2&#xff1a;什么叫数据表示&#xff1f;计算机中又有哪些方法&#xff1f; 正文 上分突破口1&#xff1a;进位计数法 例&#xff1a;二进制转为十进制 例&#xff…

路由综合实验

目录需求分析解决方法1&#xff0c;环回配置2&#xff0c;路由接口ip配置3&#xff0c;配置DHCP服务4&#xff0c;配置缺省5&#xff0c;静态路由配置6.浮动路由配置7&#xff0c;nat的配置8&#xff0c;远程服务及端口进行映射需求分析 一&#xff0c;原始需求如图&#xff1…

基于React Native开发的非法App破解记录

目标app YUhSMGNITTZMeTloWm1ZdWJIVnNkWE5wY2k1dFpTOD0 使用jadx反编译&#xff0c;找了一圈没有找到相应代码&#xff0c;看AndroidManifest.xml也不像有加壳的样子。。。 在lib目录下找到libreactnativejni.so文件&#xff0c;看似和react相关&#xff0c;莫非这app是大前端…

C++ Primer Plus 第六版(中文版)第五、六章(重置版)编程练习答案

//本博主所写的代码仅为阅读者提供参考&#xff1b; //若有不足之处请提出&#xff0c;博主会尽所能修改&#xff1b; //附上课后编程练习题目&#xff1b; //若是对您有用的话请点赞或分享提供给它人&#xff1b; //-----------------------------------------------------…

JavaScript奇淫技巧:反调试

JavaScript奇淫技巧&#xff1a;反调试 本文&#xff0c;将分享几种JS代码反调试技巧&#xff0c;目标是&#xff1a;实现防止他人调试、动态分析自己的代码。 检测调试&#xff0c;方法一&#xff1a;用console.log检测 代码&#xff1a; var c new RegExp ("1"…

Cesium 定位到图层(ImageryLayer)报错 DeveloperError: normalized result is not a number

Cesium 定位到图层&#xff08;ImageryLayer&#xff09;报错 DeveloperError: normalized result is not a number错误原因调试定位问题过程问题解决总结在使用 Cesium 封装代码的时候&#xff0c;遇到个奇怪的问题。 使用 viewer.flyTo(ImageryLayer) 报错&#xff1a;Devel…

【2022年度悲报】-回望2022,展望2023

文章目录一、前言-想对大家说的话二、有感而谈2022年-新年开端&#xff08;同销万古愁&#xff09;2022年-前中期&#xff08;再进再困&#xff0c;再熬再奋&#xff09;2022年-年后半段&#xff08;玉骨那愁瘴雾&#xff0c;冰姿自有仙风&#xff09;2022年-年末尾声&#xff…

简单总结:Flink和Kafka是如何做到精准一致性的

Flink CheckPoint机制 CheckPoint本质上就是检查点&#xff0c;类似于玩游戏的时候&#xff0c;需要偶尔存档&#xff0c;怕家里断电导致自己白玩。 Flink也是一样的&#xff0c;机器也是可能宕机&#xff0c;那么Flink如何保证自身不受宕机影响呢&#xff1f; 一般来说&am…

python小案例——采集财经数据

前言 大家早好、午好、晚好吖 ❤ ~ 另我给大家准备了一些资料&#xff0c;包括: 2022最新Python视频教程、Python电子书10个G &#xff08;涵盖基础、爬虫、数据分析、web开发、机器学习、人工智能、面试题&#xff09;、Python学习路线图等等 全部可在文末名片获取哦&…

MATLAB算法实战应用案例精讲-【人工智能】语义分割(补充篇)(附实战应用案例及代码)

前言 语义分割作为计算机视觉领域的关键任务,是实现完整场景理解的必经之路。为了让机器拥有视觉,要经过图像分类、物体检测再到图像分割的过程。其中,图像分割的技术难度最高。 越来越多的应用得益于图像分类分割技术,全场景理解在计算机视觉领域也至关重要。其中一些应…

强大的ANTLR4(3)--算术表达式

下面要构建一个简单的计算器&#xff0c;规则如下&#xff1a; 1&#xff09;可以由一系列语句构成&#xff0c;每条语句由换行符终止 2&#xff09;一条语句可以是表达式、赋值语句或空行 3&#xff09;可以有加减乘除、小括号以及变量出现 例如&#xff0c;文件名t.expr的内…

【Java】PriorityQueue梳理

【Java】PriorityQueue梳理 简介 PriorityQueue是优先队列的意思。优先队列的作用是能保证每次取出的元素都是队列中权值最小的。这里牵涉到了大小关系&#xff0c;元素大小的评判可以通过元素本身的自然顺序&#xff08;natural ordering&#xff09;&#xff0c;也可以通过…

linux的例行性工作

一&#xff0c;单一执行的例行性工作 定时任务&#xff0c;将来的某个时间点执行 使用单一理性工作的命令&#xff1a;at -> atd 命令 服务名 查看atd状态&#xff0c;看有没有这个服务&#xff0c;查看结果为有 我们使用 at 命令来生成所要运行的工作&#xff0c;并将…

Taro+nutui h5使用nut-signature 签名组件的采坑记录

近期在使用Taro&#xff08;“tarojs/taro”: “3.4.0-beta.0”&#xff09; Nutui &#xff08;3.1.16&#xff09;开发H5时,需要一个签名功能结果在小程序上运行正常的 nut-signature组件,在h5上出问题了 首先问题是 : Nutui的 签名组件&#xff08;nut-signature&#xff…

加解密与HTTPS(3)

您好&#xff0c;我是湘王&#xff0c;这是我的CSDN博客&#xff0c;欢迎您来&#xff0c;欢迎您再来&#xff5e; 除了对称加密算法和非对称加密算法&#xff0c;再就是最后的一种加密算法了&#xff1a;不可逆加密算法。 对称加密算法和非对称加密算法在处理明文的过程中需要…

线程池ThreadPoolExecutor的源码中是如何解决并发问题的?

ThreadPoolExecutor面临哪些线程安全问题 ThreadPoolExecutor俗称线程池&#xff0c;作为java.util.concurrent包对外提供基础实现&#xff0c;以内部线程池的形式对外提供管理任务执行&#xff0c;线程调度&#xff0c;线程池管理等等服务。 然而为高效并发而生ThreadPoolExe…