使用Sophus和pangolin实现轨迹误差

注:SLAM十四将的实例

绝对轨迹误差(Absolute Trahextiry,ATE)

姿态的真实值与姿态的理想值之间的差,实际上是李代数的均方根误差(Root-Mean-Aquared,RMSE)
A T E a l l = 1 N ∑ i = 1 N ∣ ∣ l o g ( T g t , i − 1 T e s t i , i ⋁ ) ∣ ∣ 2 2 ATE_{all}=\sqrt{\frac{1}{N}\sum_{i=1}^{N}||log(T^{-1}_{gt,i}T_{esti,i}^{\bigvee})||_2^2} ATEall=N1i=1Nlog(Tgt,i1Testi,i)22

绝对平移误差(Average Translational Error)

A T E t r a n s = 1 N ∑ i = 1 N ∣ ∣ t r a n s ( T g t , i − 1 T e s t i , i ⋁ ) ∣ ∣ 2 2 ATE_{trans}=\sqrt{\frac{1}{N}\sum_{i=1}^{N}||trans(T^{-1}_{gt,i}T_{esti,i}^{\bigvee})||_2^2} ATEtrans=N1i=1Ntrans(Tgt,i1Testi,i)22

相对位姿误差(Average Translational Error)

A T E t r a n s = 1 N − Δ t ∑ i = 1 N ∣ ∣ l o g ( T g t , i − 1 T g t , i + Δ t ⋁ ) − 1 ( T e s t i , i − 1 T e s t i , i + Δ t ⋁ ) ∣ ∣ 2 2 ATE_{trans}=\sqrt{\frac{1}{N-\Delta t}\sum_{i=1}^{N}||log(T^{-1}_{gt,i}T_{gt,i+\Delta t}^{\bigvee})^{-1}(T^{-1}_{esti,i}T_{esti,i+\Delta t}^{\bigvee})^{}||_2^2} ATEtrans=NΔt1i=1Nlog(Tgt,i1Tgt,i+Δt)1(Testi,i1Testi,i+Δt)22
平移部分真实值与姿态的理想值之间的差
实现:


#include <Eigen/Core>
#include <Eigen/Dense>
#include <Eigen/Geometry>
#include <sophus/geometry.hpp>
#include <sophus/se3.hpp>
#include <sophus/so3.hpp>
#include <iostream>
#include <fstream>
#include <cmath>

#include <pangolin/pangolin.h>
using namespace std;
using namespace Eigen;
using namespace Sophus;
typedef vector<Sophus::SE3d,Eigen::aligned_allocator<Sophus::SE3d >> TrajectoryType;

TrajectoryType read_data(string path, vector<double> &Time);
void plot_jectory( TrajectoryType true_pose,const TrajectoryType pose);
int main(int argc,char **argv)
{
  TrajectoryType data,real_data;
  vector<double> Time_data,Time_real_data;
  // Sophus::SE3d p1,p2;
  data=read_data("/home/n1/notes/Sophus/trajectroyError/estimated.txt",Time_data);
  real_data=read_data("/home/n1/notes/Sophus/trajectroyError/groundtruth.txt",Time_real_data);
  cout<<Time_data[0]<<endl;
  cout<<real_data[0].matrix()<<endl;

  assert(!real_data.empty() && !data.empty());//如果数据为空终止程序执行
  assert(real_data.size() == data.size());//如果数据长度不相同终止程序执行
  double error[3]={0,0,0};
  double error_sum[3]={0,0,0};
  double rmse=0;//绝对轨迹误差
  double ATE=0;//绝对平移误差
  double RPE=0;//相对时间误差 10s内
  double Delta=0;//变化时间
  double Delta_length=0;//固定时间内数据长度
  for(size_t t=0;t<real_data.size();t++)//计算误差
  {
    Sophus::SE3d p2=real_data[t];
    Sophus::SE3d p1=data[t];
    error[0]=(p2.inverse()*p1).log().norm();//norm() 范数
    error[1]=(p2.inverse()*p1).translation().norm();//平移部分
   
    error_sum[0]+=error[0]*error[0];
    error_sum[1]+=error[1]*error[1];
    Delta=double(Time_data[t]-Time_data[0]);
    
    if(Delta<10)//10s内的相对位姿误差
    {
      p2=real_data[t].inverse()*real_data[t+1];
      p1=data[t].inverse()*data[t+1];
      error[2]+=(p2.inverse()*p1).log().norm();
      error_sum[2]+=error[2]*error[2];
      cout<<"error[2]:"<<error[2]<<endl;
      Delta_length++;
    }
  }
  
  rmse=double(sqrt(error_sum[0]/real_data.size()));
  ATE=double(sqrt(error_sum[1]/real_data.size()));
  RPE=double(sqrt(error_sum[2]/Delta_length));
  cout<<"RMSE:"<<rmse<<endl;
  cout<<"ATE:"<<ATE<<endl;
  cout<<"RPE:"<<RPE<<endl;
  plot_jectory(real_data,data);

  return 0;
}





//读取数据函数
TrajectoryType read_data(string path, vector<double> &Time)
{
  ifstream fin(path);
  TrajectoryType ject;
  if(!fin)
  {
    cout<<"error"<<endl;return ject;
  }
  double time,tx,ty,tz,qx,qy,qz,qw;
  while (!fin.eof())//处理读取到的数据
  {
    fin>>time>>tx>>ty>>tz>>qx>>qy>>qz>>qw;//重定向数据到
    //cout<<"time"<<time<<endl;

    Sophus::SE3d p1(Eigen::Quaterniond(qx,qy,qz,qw),Vector3d(tx,ty,tz));//组成一个SE 欧氏旋转群
    Time.push_back(time);
    ject.push_back(p1);//保存数据点
  }
  cout<<"time"<<Time[0]<<endl;
  return ject;
}

//绘制点函数
void plot_jectory(TrajectoryType true_pose, TrajectoryType pose)
{
  int w=1024,h=768;
  pangolin::CreateWindowAndBind("Display",w,h);//创建名称,大小
  
  glEnable(GL_DEPTH_TEST);//景深
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);//开启颜色混合
  pangolin::OpenGlRenderState s_cam(//相机参数初始化
      pangolin::ProjectionMatrix(w, h, w/2, h/2, w/2, h/2, 0.1, 1000),
      pangolin::ModelViewLookAt(0, -0.1, -1.8, 0, 0, 0, 0.0, -1.0, 0.0)
  );

 
  pangolin::View &d_cam = pangolin::CreateDisplay()
      .SetBounds(0.0, 1.0, pangolin::Attach::Pix(175), 1.0, -float(w/h))
      .SetHandler(new pangolin::Handler3D(s_cam));//创建显示界面
  while (!pangolin::ShouldQuit())
  {
    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    d_cam.Activate(s_cam);
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    
    for(int i=0;i<true_pose.size()-1;i++)//读取点数据,画直线
    {
      glColor3f(0,0,1);
      
      glBegin(GL_LINES);
      auto p1 = true_pose[i], p2 = true_pose[i + 1];

      glVertex3d(p1.translation()[0], p1.translation()[1], p1.translation()[2]);
      glVertex3d(p2.translation()[0], p2.translation()[1], p2.translation()[2]);
      glEnd();
    }
        for(size_t i=0;i<pose.size()-1;i++)//读取点数据,画直线
    {
      glColor3f(0,1,0);
      glBegin(GL_LINES);
      glVertex3f(pose[i].translation()[0],pose[i].translation()[1],pose[i].translation()[2]);
      glVertex3f(pose[i+1].translation()[0],pose[i+1].translation()[1],pose[i+1].translation()[2]);
      glEnd();
    }
    pangolin::FinishFrame();
    
  }
  
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值