首页 > 编程语言 >c++(0) sophus矩阵转换

c++(0) sophus矩阵转换

时间:2024-07-22 21:18:39浏览次数:9  
标签:p2 p1 pangolin 矩阵 c++ estimated sophus translation include

 

1安装sophus

2 使用代码

2-1 R,t矩阵 q四元数转换so3和se3

 CMakeLists.txt

cmake_minimum_required(VERSION 3.0)
project(useSophus)

# 为使用 sophus,需要使用find_package命令找到它
find_package(Sophus REQUIRED)

# Eigen
include_directories("/usr/include/eigen3")
add_executable(useSophus useSophus.cpp)
target_link_libraries(useSophus Sophus::Sophus)

add_subdirectory(example)

  useSophus.cpp

#include <iostream>
#include <cmath>
#include <Eigen/Core>
#include <Eigen/Geometry>
#include "sophus/se3.hpp"

using namespace std;
using namespace Eigen;

/// 本程序演示sophus的基本用法

int main(int argc, char **argv) {

  // 沿Z轴转90度的旋转矩阵
  Matrix3d R = AngleAxisd(M_PI / 2, Vector3d(0, 0, 1)).toRotationMatrix();
  // 或者四元数
  Quaterniond q(R);
  Sophus::SO3d SO3_R(R);              // Sophus::SO3d可以直接从旋转矩阵构造
  Sophus::SO3d SO3_q(q);              // 也可以通过四元数构造
  // 二者是等价的
  cout << "SO(3) from matrix:\n" << SO3_R.matrix() << endl;
  cout << "SO(3) from quaternion:\n" << SO3_q.matrix() << endl;
  cout << "they are equal" << endl;

  // 使用对数映射获得它的李代数
  Vector3d so3 = SO3_R.log();
  cout << "so3 = " << so3.transpose() << endl;
  // hat 为向量到反对称矩阵
  cout << "so3 hat=\n" << Sophus::SO3d::hat(so3) << endl;
  // 相对的,vee为反对称到向量
  cout << "so3 hat vee= " << Sophus::SO3d::vee(Sophus::SO3d::hat(so3)).transpose() << endl;

  // 增量扰动模型的更新
  Vector3d update_so3(1e-4, 0, 0); //假设更新量为这么多
  Sophus::SO3d SO3_updated = Sophus::SO3d::exp(update_so3) * SO3_R;
  cout << "SO3 updated = \n" << SO3_updated.matrix() << endl;

  cout << "*******************************" << endl;
  // 对SE(3)操作大同小异
  Vector3d t(1, 0, 0);           // 沿X轴平移1
  Sophus::SE3d SE3_Rt(R, t);           // 从R,t构造SE(3)
  Sophus::SE3d SE3_qt(q, t);            // 从q,t构造SE(3)
  cout << "SE3 from R,t= \n" << SE3_Rt.matrix() << endl;
  cout << "SE3 from q,t= \n" << SE3_qt.matrix() << endl;
  // 李代数se(3) 是一个六维向量,方便起见先typedef一下
  typedef Eigen::Matrix<double, 6, 1> Vector6d;
  Vector6d se3 = SE3_Rt.log();
  cout << "se3 = " << se3.transpose() << endl;
  // 观察输出,会发现在Sophus中,se(3)的平移在前,旋转在后.
  // 同样的,有hat和vee两个算符
  cout << "se3 hat = \n" << Sophus::SE3d::hat(se3) << endl;
  cout << "se3 hat vee = " << Sophus::SE3d::vee(Sophus::SE3d::hat(se3)).transpose() << endl;

  // 最后,演示一下更新
  Vector6d update_se3; //更新量
  update_se3.setZero();
  update_se3(0, 0) = 1e-4;
  Sophus::SE3d SE3_updated = Sophus::SE3d::exp(update_se3) * SE3_Rt;
  cout << "SE3 updated = " << endl << SE3_updated.matrix() << endl;

  return 0;
}

  

例子2  真值和测量值计算平均方误差

 

 

 CMakeLists.txt

option(USE_UBUNTU_20 "Set to ON if you are using Ubuntu 20.04" OFF)
find_package(Pangolin REQUIRED)
if(USE_UBUNTU_20)
    message("You are using Ubuntu 20.04, fmt::fmt will be linked")
    find_package(fmt REQUIRED)
    set(FMT_LIBRARIES fmt::fmt)
endif()
include_directories(${Pangolin_INCLUDE_DIRS})
add_executable(trajectoryError trajectoryError.cpp)
target_link_libraries(trajectoryError ${Pangolin_LIBRARIES} ${FMT_LIBRARIES})

  trajectoryError.cpp

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

using namespace Sophus;
using namespace std;

string groundtruth_file = "./example/groundtruth.txt";
string estimated_file = "./example/estimated.txt";

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

void DrawTrajectory(const TrajectoryType &gt, const TrajectoryType &esti);

TrajectoryType ReadTrajectory(const string &path);

int main(int argc, char **argv) {
  TrajectoryType groundtruth = ReadTrajectory(groundtruth_file);
  TrajectoryType estimated = ReadTrajectory(estimated_file);
  assert(!groundtruth.empty() && !estimated.empty());
  assert(groundtruth.size() == estimated.size());

  // compute rmse
  double rmse = 0;
  for (size_t i = 0; i < estimated.size(); i++) {
    Sophus::SE3d p1 = estimated[i], p2 = groundtruth[i];
    double error = (p2.inverse() * p1).log().norm();
    rmse += error * error;
  }
  rmse = rmse / double(estimated.size());
  rmse = sqrt(rmse);
  cout << "RMSE = " << rmse << endl;

  DrawTrajectory(groundtruth, estimated);
  return 0;
}

TrajectoryType ReadTrajectory(const string &path) {
  ifstream fin(path);
  TrajectoryType trajectory;
  if (!fin) {
    cerr << "trajectory " << path << " 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;
}

void DrawTrajectory(const TrajectoryType &gt, const TrajectoryType &esti) {
  // create pangolin window and plot the trajectory
  pangolin::CreateWindowAndBind("Trajectory Viewer", 1024, 768);
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  pangolin::OpenGlRenderState s_cam(
      pangolin::ProjectionMatrix(1024, 768, 500, 500, 512, 389, 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, -1024.0f / 768.0f)
      .SetHandler(new pangolin::Handler3D(s_cam));


  while (pangolin::ShouldQuit() == false) {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    d_cam.Activate(s_cam);
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

    glLineWidth(2);
    for (size_t i = 0; i < gt.size() - 1; i++) {
      glColor3f(0.0f, 0.0f, 1.0f);  // blue for ground truth
      glBegin(GL_LINES);
      auto p1 = gt[i], p2 = gt[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 < esti.size() - 1; i++) {
      glColor3f(1.0f, 0.0f, 0.0f);  // red for estimated
      glBegin(GL_LINES);
      auto p1 = esti[i], p2 = esti[i + 1];
      glVertex3d(p1.translation()[0], p1.translation()[1], p1.translation()[2]);
      glVertex3d(p2.translation()[0], p2.translation()[1], p2.translation()[2]);
      glEnd();
    }
    pangolin::FinishFrame();
    usleep(5000);   // sleep 5 ms
  }

}

  

标签:p2,p1,pangolin,矩阵,c++,estimated,sophus,translation,include
From: https://www.cnblogs.com/gooutlook/p/18316934

相关文章

  • c++零基础知识要点整理(7)
    *请搭配c++零基础知识要点整理(5)使用位或运算符的应用: | (有1即1)1.设置标记位(使某一个位置的值变为1)inta=0b101101;//(以使第五位变为1举例,即使a变为:0b11101)cout<<(a|0b10000)<<endl;//要使第五个位置的值变为1,则将这个数和0b10000进行位或//以此类推:需要使第四个......
  • C++树的介绍
    目录树的基本概念和术语树的种类实现树的例子遍历树在C++中,树(Tree)是一种非常重要的数据结构,用于模拟具有层级关系的数据。树结构是递归定义的,一个树由零个或多个节点(node)组成,其中一个节点被称为根节点(rootnode),其余节点分为若干个不相交的子树(subtree),每个子树也是一棵树......
  • 聊聊C++string
    原文链接聊聊c++string  相信大家对string都不陌生,但不知道大家有没有这样的疑问:两个string之间赋值,是指向同一个字符串还是不同的字符串?  如果是深拷贝,按理说要指向不同的字符串,那么内部数据的地址要不同;如果是浅拷贝,怎么避免指针doublefree的问题?  先看个简单......
  • zig vs c++:控制x11鼠标移动
    zigDebug输出大小:2.3MBReleaseSmall输出大小:11.3kBconststd=@import("std");constx11=@cImport({@cInclude("X11/Xlib.h");});//Convertsbetweennumerictypes:.Enum,.Intand.Float.pubinlinefnas(comptimeT:type,from:anyty......
  • C++ 学习笔记十一 封装
    封装4.1.1封装的意义封装是C++面向对象三大特性之一封装的意义:将属性和行为作为一个整体,表现生活中的事物将属性和行为加以权限控制封装意义一:​在设计类的时候,属性和行为写在一起,表现事物语法:class类名{访问权限:属性/行为};**示例1:**设计一个圆类,求圆的周......
  • 手写Kd树(C++模板非递归实现)
    手写Kd树(C++模板非递归实现)1.Kd树1.1Kd树简介1.2Kd树的建立1.3Kd树的查找2.C++完整代码实现3.测试代码3.1代码实现3.2测试结果4.与PCL中的Kd树做对比本文实现的Kd树实现参考了高翔博士的书《自动驾驶与机器人中的slam技术从理论到实践》;高博士原书中是递归......
  • 在 python 中表示矩阵等价类的好方法是什么?
    我正在尝试编写一个程序来对井字棋进行强化学习。我希望引擎认识到,如果您反射棋盘或旋转它,您会得到完全相同的游戏,因此这些棋盘应该被视为彼此相同。目前我有一本字典,代表我当前对每个棋盘的估计估值游戏中的棋盘,每次游戏结束时,该游戏期间发生的所有棋盘位置的估值都会根据它......
  • C++:istream、ostream和fstream类
    1、基类istream和ostream(1)istreamA.What输入流的抽象类,是所有输入流类的基类B.Why(输入流的作用)用于从数据源(如文件、标准输入设备等外部设备)读取数据到内存中(2)ostreamA.What输出流的抽象类,是所有输出流类的基类B.Why(输出流的作用)输出流用于将数据从......
  • GPy 回归中的输出 Gram 矩阵(高斯过程)
    因为我需要在大量点上训练我的GP,所以我不仅想保存优化的超参数ker=GPy.kern.Matern32(nc,ARD=True)m=GPy.models.GPRegression(xTrain,np.reshape(yTrain,(-1,1)),ker,noise_var=1e-8)m.Mat32.lengthscale.constrain_bounded(0.01,5e0)m.Mat32.variance.constr......
  • c++中字符串之string和char
    c++string初始化的几种方式相对于C#来说,c++中string的初始化方式真的非常多,比如以下都可以用来初始化string:usingnamespacestd;intmain(){ stringstr1="test01";//直接赋值 stringstr2(5,'c');//结果:str2='ccccc',以length为长度的ch的拷贝(即length个ch) ......