【SLAM】评估轨迹误差,手写ATE、RPE对比EVO

目录

1.绝对轨迹误差(Absolute Trajectory Error, ATE)

 1.1旋转+平移的均方根误差

1.2 仅计算平移的均方根误差

2.相对轨迹误差(Relative Pose Error, RPE)

 2.1旋转+平移的均方根误差

 2.2平移的均方根误差 

3.代码部分

4.evo工具

4.1 evo工具安装以及使用说明

4.2 evo中计算ATE(APE)

4.2 evo中计算RPE


常用评估轨迹误差的方式有两种:绝对轨迹误差(ATE)与相对轨迹误差(RPE)

1.绝对轨迹误差(Absolute Trajectory Error, ATE)

绝对轨迹误差即为求每个位姿李代数的均方根

如图,有两条轨迹,一条为真实轨迹esti,一条为slam算法估算的轨迹gt, 将两条轨迹分为无数个点,并在上面分别取两个点Pesti,i和Pg,i,其相对于原点P的计算公式如下,其中T为欧式变化(属于李群

P_{esti,i} = T_{esti,i}*P

 P_{g,i} = T_{g,i}*P

计算第i个点的误差error的李群形式,写成相除的形式比较好理解:

error = P_{esti,i} / P_{g,i} = T_{esti,i} * T_{g,i}^{-1}

 1.1旋转+平移的均方根误差

由于我们最终求的是李代数的均方根,所以先求error对应的李代数,提出一个负号(可在代码中验证)

E_{g,i} =log_e(T_{g,i+\Delta } * T_{g.i}^{-1})^V = - log_e(T_{g.i}^{-1} *T_{g,i+\Delta })^V

取范数后,取均方根得到ATEall,取范数后正负号不影响

ATE_{all} =\sqrt{\frac{1}{N}\sum_{i=1}^N||log_e(T_{g,i} ^{-1} *T_{esti,i})^V||_{2}^{2}}

1.2 仅计算平移的均方根误差

在获取平移的均方根时,不需要转换到李代数,在欧式变换(李群)中取出其平移量计算均方根。

ATE_{all} =\sqrt{\frac{1}{N}\sum_{i=1}^N||trans(T_{g,i} ^{-1} *T_{esti,i})||_{2}^{2}}

2.相对轨迹误差(Relative Pose Error, RPE)

 2.1旋转+平移的均方根误差

相对轨迹误差是计算相隔\Delta t时间的两帧之间位姿之差的精度。(有点绕)

 (\Delta t时间对应可能不止1帧,但是是帧数的整数比如1,2,3...帧)

还是一样,两条轨迹分别为真实轨迹gi,算法估计轨迹esti,这次需要在上面取两个点,对于任意的i点有相应后的i+\Delta点,两条轨迹上的四个点分别记为P_{g,i} ,P_{g,i+\Delta}, P_{esti,i}, P_{esti,i+\Delta }

 与ATE不同的是,RPE是分别计算每条轨迹上两个时刻(也就是两个点)的变化,再求这两个变化的误差。

分别求真实轨迹gi和算法估计轨迹esti的变化,还是用李代数表示:

真实轨迹上两帧之间的变化的李代数:

E_{g,i} =log_e(T_{g,i+\Delta } / T_{g.i})^V = log_e(T_{g,i+\Delta } * T_{g.i}^{-1})^V = - log_e(T_{g.i}^{-1} *T_{g,i+\Delta })^V

算法估计轨迹上两帧之间的变化的李代数:

E_{esti,i} =log_e(T_{esti,i+\Delta } * T_{esti.i}^{-1})^V = - log_e(T_{esti.i}^{-1} *T_{esti,i+\Delta })^V

最后在计算两帧之间变化的误差:

E_i = log_e(E_{esti,i} / E_{g,i}) = log_e(E_{esti,i}*E_{g,i}^{-1}) = -log_e(E_{g,i}^{-1}*E_{esti,i})

 最后取均方根得到RPEall,注意是之前说的\Delta t对应的是整数帧数,取均方根的时候取到N-\Delta t

RPE_{all}=\sqrt{\frac{1}{N-\Delta t}\sum _{i=1}^{N-\Delta t}||log_e((T_{gi.i}^{-1} *T_{gi,i+\Delta })^{-1}(T_{esti.i}^{-1} *T_{esti,i+\Delta })^V||_{2}^2}

 2.2平移的均方根误差 

在获取平移的均方根时,不需要转换到李代数,在欧式变换(李群)中取出其平移量计算均方根。

RPE_{trans}=\sqrt{\frac{1}{N-\Delta t}\sum _{i=1}^{N-\Delta t}||trans((T_{gi.i}^{-1} *T_{gi,i+\Delta })^{-1}(T_{esti.i}^{-1} *T_{esti,i+\Delta })||_{2}^2}

3.代码部分

这部分引用高博《视觉slam14讲》ch4/example中的数据groundtruth.txt和estimated.txt(https://github.com/gaoxiang12/slambook2

#include<pangolin/pangolin.h>
#include <iostream>
#include <sophus/se3.hpp>
#include <fstream>
#include <unistd.h>
#include <Eigen/Core>
#include <Eigen/Dense>

using namespace std;
using namespace Sophus;
using namespace Eigen;

string groundtruth_file = "/home/liao/workspace/slambook2/ch4/example/groundtruth.txt";
string estimated_file = "/home/liao/workspace/slambook2/ch4/example/estimated.txt";

typedef vector<Sophus::SE3d, Eigen::aligned_allocator<Sophus::SE3d>> TrajectoryType;

TrajectoryType ReadTrajectory(const string& file_name);
void DrawTrajectory(const TrajectoryType& gt, const TrajectoryType& esti);
vector<double> calculateATE(const TrajectoryType& gt, const TrajectoryType& esti);
vector<double> calculateRPE(const TrajectoryType& gt, const TrajectoryType& esti);

int main(int argc, char **argv)
{
    //读取高博slam14讲中的groundtruth.txt和estimated.txt的数据
    auto gi = ReadTrajectory(groundtruth_file);
    cout << "gi read total " << gi.size() << endl;
    auto esti = ReadTrajectory(estimated_file);
    cout << "esti read total " << esti.size() << endl;

    vector<double> ATE, RPE;
    ATE = calculateATE(gi, esti); //计算ATE
    RPE = calculateRPE(gi, esti); //计算RPE
//    DrawTrajectory(gi, esti);
    return 0;
}
vector<double> calculateATE(const TrajectoryType& gt, const TrajectoryType& esti)
{
    double rmse_all, rmse_trans;
    for(size_t i = 0; i < gt.size(); i++)
    {
        //ATE旋转+平移
        double error_all = (gt[i].inverse()*esti[i]).log().norm();
        rmse_all += error_all * error_all;
        //ATE平移
        double error_trans = (gt[i].inverse()*esti[i]).translation().norm();
        rmse_trans += error_trans * error_trans;
    }
    rmse_all = sqrt(rmse_all / double(gt.size()));
    rmse_trans = sqrt(rmse_trans / double(gt.size()));
    vector<double> ATE;
    ATE.push_back(rmse_all);
    ATE.push_back(rmse_trans);
    cout << "ATE_all = " << rmse_all << " ATE_trans = " << rmse_trans << endl;
}
vector<double> calculateRPE(const TrajectoryType& gt, const TrajectoryType& esti)
{
    double rmse_all, rmse_trans;
    double delta = 1;               //delta = 2, 间隔两帧
    for(size_t i = 0; i < gt.size() - delta; i++)
    {
        //RPE旋转+平移
        double error_all = ((gt[i].inverse()*gt[i + delta]).inverse()*(esti[i].inverse()*esti[i + delta])).log().norm();
        rmse_all += error_all * error_all;
        //RPE平移
        double error_trans = ((gt[i].inverse()*gt[i + delta]).inverse()*(esti[i].inverse()*esti[i + delta])).translation().norm();
        rmse_trans += error_trans * error_trans;
    }
    rmse_all = sqrt(rmse_all / double(gt.size()));
    rmse_trans = sqrt(rmse_trans / double(gt.size()));
    vector<double> RPE;
    RPE.push_back(rmse_all);
    RPE.push_back(rmse_trans);
    cout << "RPE_all = " << rmse_all << " RPE_trans = " << rmse_trans << endl;
}
TrajectoryType ReadTrajectory(const string& file_name)
{
    ifstream fin(file_name);
    TrajectoryType trajectory;
    if(!fin)
    {
        cerr << "trajectory " << file_name << "not found" << endl;
        return trajectory;
    }
    while(!fin.eof())
    {
        double time, tx, ty, tz, qx, qy, qz, qw;
        fin >> time >> tx >> ty >> tz >> qx >> qy >> qz >> qw;
        Sophus::SE3d p1(Eigen::Quaterniond(qw, qx, qy, qz), Eigen::Vector3d(tx, ty, tz));
        trajectory.push_back(p1);
    }
    return trajectory;
}
//结果如下:

gi read total 612
esti read total 612
ATE_all = 2.20728 ATE_trans = 0.0231005
RPE_all = 0.0593723 RPE_trans = 0.0310044

轨迹如图,绿色的为真实轨迹,蓝色为估算轨迹。

4.evo工具

4.1 evo工具安装以及使用说明

安装参考这个帖子:https://www.guyuehome.com/18717

evo使用看这个帖子:https://blog.csdn.net/dcq1609931832/article/details/102465071

4.2 evo中计算ATE(APE)

evo中把ATE称为APE。

高博书中的格式是数据集TUM格式,即time, tx, ty, tz, qx, qy, qz, qw

evo中默认计算平移部分,需要通过输入-r full来改为计算平移+旋转。

 分别输入以下命令:

计算旋转+平移:rmse = 2.397755, 自己写的是ATE_all = 2.20728

evo_ape tum -r full groundtruth.txt estimated.txt 

#############output################

       max	2.828949
      mean	2.353747
    median	2.527603
       min	0.993047
      rmse	2.397755
       sse	3507.030550
       std	0.457280

计算平移:rmse = 0.023082,自己写的是ATE_trans = 0.0231005

evo_ape tum groundtruth.txt estimated.txt 

#########output###########

       max	0.063891
      mean	0.019498
    median	0.016376
       min	0.001271
      rmse	0.023082
       sse	0.325000
       std	0.012354

4.2 evo中计算RPE

默认为delta = 1的情况,如需更改为delta = 2,则: -r --delta 2,如下:

evo_rpe tum -r full --delta 2 groundtruth.txt estimated.txt

当delta = 1时,分别输入以下命令:

计算旋转+平移:rmse = 0.078218,RPE_all = 0.0593723

evo_rpe tum -r full groundtruth.txt estimated.txt 

#############output################

for delta = 1 (frames) using consecutive pairs
(not aligned)

       max	0.314840
      mean	0.067958
    median	0.063364
       min	0.005507
      rmse	0.078218
       sse	3.725902
       std	0.038726

计算平移:rmse = 0.031082, 自己写的是:RPE_trans = 0.0310044

evo_rpe tum groundtruth.txt estimated.txt

##############output###############

for delta = 1 (frames) using consecutive pairs
(not aligned)

       max	0.115223
      mean	0.025923
    median	0.022008
       min	0.000927
      rmse	0.031082
       sse	0.588337
       std	0.017148

最后,对比自己写的和evo算得还是有一点点差别。算旋转的时候会差0.1-0.2,算平移的时候比较准一点。

SLAM精度评估中的EVO是指使用EVO工具来评估SLAM系统的轨迹误差EVO是一个开源的工具,用于评估SLAM系统的性能。它提供了一系列命令和功能,可以计算和可视化SLAM系统的轨迹误差。 在EVO中,有几个常用的命令可以用来评估SLAM系统的轨迹误差。其中,evo_traj命令用于评估轨迹误差,可以使用手写ATE绝对位姿误差)和RPE(相对位姿误差)来比较SLAM系统的性能。\[1\] 相对位姿误差主要用于比较运动(姿态增量),而不是进行绝对位姿的比较。相对位姿误差可以给出局部精度,例如SLAM系统每米的平移或旋转漂移量。可以使用evo_rpe命令来计算相对位姿误差,并通过设置参数来进行可视化和保存结果。\[2\] 另外,evo_ape命令可以用于计算ATE绝对位姿误差),并提供了可视化和保存结果的功能。可以使用该命令来评估SLAM系统在KITTI数据集上的性能。\[3\] 总之,EVO是一个用于评估SLAM系统性能的工具,可以通过计算和可视化轨迹误差评估SLAM系统的精度。可以使用evo_traj、evo_rpeevo_ape等命令来进行评估和分析。 #### 引用[.reference_title] - *1* *2* [SLAM精度测评——EVO进阶](https://blog.csdn.net/Darlingqiang/article/details/123534388)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [ros中SLAMEVO、APE测评——SLAM精度测评(一)](https://blog.csdn.net/Yangy_Jiaojiao/article/details/124419966)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值