Sophus库的安装和使用教程

2023-11-04

本系列文章为原创,转载请注明出处。
作者:Dongdong Bai
邮箱: baidongdong@nudt.edu

若您觉得本博文对您有帮助,请您为我点赞并关注我,以鼓励我写出更优秀的博文。谢谢!


一、Sophus库简介:

Eigen库是一个开源的C++线性代数库,它提供了快速的有关矩阵的线性代数运算,还包括解方程等功能。但是Eigen库提供了集合模块,但没有提供李代数的支持。一个较好的李群和李代数的库是Sophus库,它很好的支持了SO(3),so(3),SE(3)和se(3)。Sophus库是基于Eigen基础上开发的,继承了Eigen库中的定义的各个类。因此在使用Eigen库中的类时,既可以使用Eigen命名空间,也可以使用Sophus命名空间。比如

Eigen::Matrix3d和Sophus::Matrix3d
Eigen::Vector3d和Sophus::Vector3d

此外,为了方便说明SE(4)和se(4),Sophus库还typedef了Vector4d、Matrix4d、Vector6d和Matrix6d等,即:

Sophus::Vector4d
Sophus::Matrix4d
Sophus::Vector6d
Sophus::Matrix6d

二、Sophus安装方式:

git clone https://github.com/strasdat/Sophus.git
cd Sophus
git checkout a621ff
mkdir build 
cd build
cmake ..
make

三、Sophus的使用教程:

写在前面,这里有几个需要注意的地方:

1. Sophus库的各种形式的表示如下:

李代数so(3):Sophus::Vector3d //因为so(3)仅仅只是一个普通的3维向量

李代数se(3):Sophus::Vector6d //因为se(3)仅仅只是一个普通的6维向量

2. SO3的构造函数为:

SO3 ();
SO3 (const SO3 & other);
explicit SO3 (const Matrix3d & _R);
explicit SO3 (const Quaterniond & unit_quaternion);
SO3 (double rot_x, double rot_y, double rot_z);

3. SE3的构造函数为:

SE3 ();
SE3 (const SO3 & so3,const Vector3d & translation);
SE3 (const Matrix3d & rotation_matrix,const Vector3d & translation);
SE3 (const Quaterniond & unit_quaternion,const Vector3d & translation_);
SE3 (const SE3 & other);

4.SO3,SE3和se3的输出说明:

  • 尽管SO3对应于矩阵群,但是SO3在使用cout时是以so3形式输出的,输出的是一个3维向量

  • SE3在使用cout输出时输出的是一个6维向量,其中前3维为对应的so3的值,后3维为实际的平移向量t

  • se3在使用cout输出时输出的也是一个6维向量,但是其前3维为平移值 ρ (注意此时的 ρ 与SE3输出的t是不同的,t=J ρ ,其中J是雅克比矩阵),后3维为其对应的so3.

四、SO3,so3,SE3和se3初始化以及相互转换关系

1.转换关系图:SO3,so3,SE3和se3的相互转换关系

关于旋转矩阵,旋转向量和四元数的初始化和相互转换关系可以参考我的另一篇博文:http://blog.csdn.net/u011092188/article/details/77430988

2.代码示意:

下面是SO3,so3,SE3和se3初始化以及相互转换的示意代码useSophusc.cpp:

#include <iostream>
#include <Eigen/Core>
#include <sophus/so3.h>
#include <sophus/se3.h>

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


int main(int argc, char **argv) {
    //沿着Z轴旋转90度的旋转矩阵
    Eigen::AngleAxisd A1(M_PI / 2, Eigen::Vector3d(0, 0, 1));//以(0,0,1)为旋转轴,旋转180度
    Eigen::Matrix3d R1 = A1.matrix();
    Eigen::Quaterniond Q1(A1);


    //一、初始化的李群(SO3)的几种方式

    //1.使用旋转矩阵初始化李群
    Sophus::SO3 SO3_R(R1);
    //注意:尽管SO(3)是对应一个矩阵,但是输出SO(3)时,实际上是以so(3)形式输出,从输出的结果可以看到,其输出的值与旋转角对应的值相同,这也证证实了SO(3)对应的李代数so(3)就是旋转角。
    cout << "SO(3) SO3_R from Matrix" << SO3_R << endl << endl;

    //2.使用四元数初始化李群
    Sophus::SO3 SO3_Q(Q1);
    cout << "SO(3) SO3_Q from Quaterion" << SO3_Q << endl << endl;

    /****************************************************************************
     3.1 使用旋转角(轴角)的各个元素对应的代数值来初始化李群

     注意:直接使用旋转角AngleAxis或是旋转角度对应的向量(Vector3d=AngleAxis.axis()*AngleAxis.angle())对李群进行初始化是不行的,因为SO3李群没有对应的构造函数。
    也即是使用下列方法是错误的:

     Sophus::SO3 SO3_A(A1);//直接使用旋转角对李群初始化
     Sophus::SO3 SO3_A(A1.axis()*A1.angle());//直接使用旋转角度对应的向量(Vector3d=AngleAxis.axis()*AngleAxis.angle())对李群进行初始化

     只能使用旋转角对应的向量的每一个维度进行赋值,对应于SO3的这样一个构造函数SO3(double rot_x, double rot_y, double rot_z);

    *******************************************************************************/

    //3.1.1 使用旋转角度对应的向量(Vector3d=AngleAxis.axis()*AngleAxis.angle())中的各个元素对李群进行初始化
    Sophus::SO3 SO3_A1((A1.axis() * A1.angle())(0), (A1.axis() * A1.angle())(1), (A1.axis() * A1.angle())(2));
    cout << "SO(3) SO3_A1 from AngelAxis1" << SO3_A1 << endl << endl;

    //3.1.2 使用旋转角度对应的向量(Vector3d=AngleAxis.axis()*AngleAxis.angle())中的各个元素对李群进行初始化
    Sophus::SO3 SO3_A2(M_PI / 2 * 0, M_PI / 2 * 0, M_PI / 2 * 1);
    cout << "SO(3) SO3_A2 from AngleAixs2" << SO3_A2 << endl << endl;

    //3.2 由于旋转角(轴角)与李代数so(3)对应,所以直接使用旋转角的值获得se(3),进而再通过Sophus::SO3::exp()获得对应的SO(3)
    Eigen::Vector3d V1(0, 0, M_PI / 2);//so3在Eigen中用Vector3d表示
    Sophus::SO3 SO3_V1 = Sophus::SO3::exp(V1);
    cout << "SO(3) SO3_V1 from SO3::exp()" << SO3_V1 << endl << endl;


    //二、SO(3)与so(3)的相互转换,以及so3对应的hat和vee操作

    Eigen::Vector3d so3_V1 = SO3_V1.log();//so(3)在Sophus(Eigen)中用vector3d表示,使用对数映射获得李群对应的李代数
    cout << "so(3) so3_V1 from SO3_V1" << so3_V1.transpose() << endl << endl;


    Sophus::SO3 SO3_V2 = Sophus::SO3::exp(so3_V1);//使用指数映射将李代数转化为李群
    cout << "SO(3) so3_V2 from so3_V1" <<SO3_V2 << endl << endl;


    Eigen::Matrix3d M_so3_V1 = Sophus::SO3::hat(so3_V1);//hat为向量到其对应的反对称矩阵
    cout << "so3 hat=\n" << M_so3_V1 << endl << endl;

    Eigen::Vector3d V_M = Sophus::SO3::vee(M_so3_V1);//vee为反对称矩阵对应的向量
    cout << "so3 vee=\n" << V_M << endl << endl;

    //三、增量扰动模型
    Eigen::Vector3d update_so3(1e-4,0,0);//假设更新量为这么多
    Eigen::Matrix3d update_matrix=Sophus::SO3::exp(update_so3).matrix();//将李群转换为旋转矩阵
    cout<<"SO3 update Matrix=\n"<<update_matrix<<endl<<endl;

    Sophus::SO3 SO3_updated=Sophus::SO3::exp(update_so3)*SO3_R;
    cout<<"SO3 updated = \n"<<SO3_updated<<endl;

    Eigen::Matrix3d SO3_updated_matrix=SO3_updated.matrix();//将李群转换为旋转矩阵
    cout<<"SO3 updated Matrix = \n"<<SO3_updated_matrix<<endl<<endl;


//******************************************************************分割线***********************************************************************************
    cout<<"************************************分割线*************************************************"<<endl<<endl;

    Eigen::AngleAxisd A2(M_PI/2,Eigen::Vector3d(0,0,1));
    Eigen::Matrix3d R2=A2.matrix();
    Eigen::Quaterniond Q2(A2);
    Sophus::SO3 SO3_2(R2);

    //一、初始化李代数的几种方式
    Eigen::Vector3d t(1,0,0);

    //1. 使用旋转矩阵和平移向量来初始化SE3
    Sophus::SE3 SE_Rt(R2,t);
    cout<<"SE3 SE_Rt from  Rotation_Matrix and Transform=\n"<<SE_Rt<<endl<<endl;//注意尽管SE(3)是对应一个4*4的矩阵,但是输出SE(3)时是以一个六维向量输出的,其中前前三位为对应的so3,后3维度为实际的平移量t,而不是se3中的平移分量
    //2. 使用四元数和平移向量来初始化SE3
    Sophus::SE3 SE_Qt(Q2,t);
    cout<<"SE3 SE_Qt from  Quaterion and Transform=\n"<<SE_Qt<<endl<<endl;
    //3. 使用SO3和平移向量来初始化SE3
    Sophus::SE3 SE_St(SO3_2,t);
    cout<<"SE3 SE_St from  SO3 and Transform=\n"<<SE_St<<endl<<endl;

    //二、SE(3)与se(3)的相互转换,以及se3对应的hat和vee操作
    Sophus::Vector6d se3_Rt=SE_Rt.log();//se(3)在Sophus中用Vector6d表示,使用对数映射获得李群对应的李代数
    cout<<"se(3) se3_Rt from SE3_Rt\n"<<se3_Rt<<endl<<endl;//se3输出的是一个六维度向量,其中前3维是平移分量,后3维度是旋转分量

    Sophus::SE3 SE3_Rt2=Sophus::SE3::exp(se3_Rt);//使用指数映射将李代数转化为李群
    cout<<"SE(3) SO3_Rt2 from se3_Rt"<<SE3_Rt2<<endl<<endl;

    Sophus::Matrix4d M_se3_Rt=Sophus::SE3::hat(se3_Rt);
    cout<<"se(3) hat=\n"<<M_se3_Rt<<endl<<endl;

    Sophus::Vector6d V_M_se3=Sophus::SE3::vee(M_se3_Rt);
    cout<<"se(3) vee=\n"<<V_M_se3<<endl<<endl;




    //三、增量扰动模型

    Sophus::Vector6d update_se3=Sophus::Vector6d::Zero();
    update_se3(0)=1e-4d;

    cout<<"update_se3\n"<<update_se3.transpose()<<endl<<endl;

    Eigen::Matrix4d update_matrix2=Sophus::SE3::exp(update_se3).matrix();//将李群转换为旋转矩阵
    cout<<"update matrix=\n"<<update_matrix2<<endl<<endl;

    Sophus::SE3 SE3_updated=Sophus::SE3::exp(update_se3)*SE3_Rt2;
    cout<<"SE3 updated=\n"<<SE3_updated<<endl<<endl;

    Eigen::Matrix4d SE3_updated_matrix=SE3_updated.matrix();//将李群转换为旋转矩阵
    cout<<"SE3 updated Matrix=\n"<<SE3_updated_matrix<<endl<<endl;

    return 0;

}

上述代码对应的CMakeLists.txt为:

CMAKE_MINIMUM_REQUIRED( VERSION 2.8)
PROJECT(useSophus)
FIND_PACKAGE(Sophus REQUIRED)
INCLUDE_DIRECTORIES(${Sophus_INCLUDE_DIRS})
add_executable(useSophus useSophus.cpp)
TARGET_LINK_LIBRARIES(useSophus ${Sophus_LIBRARIES})

本系列文章为原创,转载请注明出处。
作者:Dongdong Bai
邮箱: baidongdong@nudt.edu

若您觉得本博文对您有帮助,请您为我点赞并关注我,以鼓励我写出更优秀的博文。谢谢!

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

Sophus库的安装和使用教程 的相关文章

随机推荐

  • shell单双引号嵌套+变量

    metadata annotations volume kubernetes io selected node TARGET NODE
  • 云计算中微服务是什么Java之命名、标示符、变量

    微服务架构是一种架构模式 它提倡将单一应用程序划分成一组小的服务 服务之间相互协调 互相配合 为用户提供最终价值 每个服务运行在其独立的进程中 服务和服务之间采用轻量级的通信机制相互沟通 每个服务都围绕着具体的业务进行构建 并且能够被独立的
  • 【笔试强训选择题】Day34.习题(错题)解析

    作者简介 大家好 我是未央 博客首页 未央 303 系列专栏 笔试强训选择题 每日一句 人的一生 可以有所作为的时机只有一次 那就是现在 文章目录 前言 一 Day34习题 错题 解析1 总结 前言 一 Day34习题 错题 解析 1 解析
  • 升级 Linux 系统中的 Python 版本

    升级 Linux 系统中的 Python 版本 Python 是一种非常流行的编程语言 广泛应用于各种领域 包括 Web 开发 数据分析等 而对于 Linux 系统来说 Python 更是一个必须的组件 在系统运行和管理中都扮演了重要的角色
  • 大模型Founation Model

    一 背景 自从chatgpt gpt4以特别好的效果冲入人们的视野中 也使得AI产业发生了巨大变革 从17年以来的bert 将AI的各种领域都引入bert类的fine tune方法 来解决单个领域单个任务的一一个预训练模型 在学术界和工业界
  • 谈谈Linux epoll惊群问题的原因和解决方案

    近期排查了一个问题 epoll惊群的问题 起初我并不认为这是惊群导致 因为从现象上看 只是体现了CPU不均衡 一共fork了20个Server进程 在请求负载中等的时候 有三四个Server进程呈现出比较高的CPU利用率 其余的Server
  • 如何区分成员函数和构造函数?

    在面向对象编程中 成员函数和构造函数是类中定义的两种不同类型的函数 构造函数是一个特殊的成员函数 用于创建并初始化类的对象 构造函数的名称必须与类的名称相同 它没有返回值 并且在对象创建时自动调用 构造函数可以有参数 这些参数用于初始化类的
  • 字符串查找之 KMP 算法思路讲解和代码实现

    算法介绍 KMP 算法是一种改进的字符串匹配算法 由 D E Knuth J H Morris 和 V R Pratt 提出的 KMP 算法的核心是利用匹配失败后的信息 尽量减少模式串与主串的匹配次数以达到快速匹配的目的 KMP 算法的时间
  • lab值意义_色差仪lab值如何分析

    色差仪在涂料 建材 油漆 涂料 纺织印染 油墨 塑料 染料颜料制造等表面色料工业的配色方面有着广泛的应用 也称为CIELAB均匀色空间 本文深圳京联泰科技给大家就色差仪LAB值如何分析作说明 L 亮度 轴表示黑白 0为黑 100为白 a 红
  • 树莓派常用命令

    刷系统 格式化 这样就ok了 开启ssh 刷完系统在boot盘跟目录创建文件ssh就可以了小写不需要后缀 汉化 sudo raspi config 选4 再选1 然后把 4个前面是 zh cn的 用 空格选中 然后 ok 选zh CN ut
  • 科研无人机平台P600进阶版,突破科研难题!

    随着无人机技术日益成熟 无人机的应用领域不断扩大 对无人机研发的需求也在不断增加 然而 许多开发人员面临着无法从零开始构建无人机的时间和精力压力 同时也缺乏适合的软件平台来支持他们的开发工作 为了解决这个问题 我们特别开发了科研无人机平台P
  • 访问私有变量或方法

    本文主要介绍一下如何访问类的私有成员变量以及类的私有方法 这里以下面这个类来举例 interface HomeController UIViewController NSString name2 property nonatomic cop
  • 分页插件(jquery.pagination.js)简单案例

    分页插件 jquery pagination js 前言 开发中需要展示数据操作记录 但数量是未知的 使用该插件 实现分页切换页码的功能 1 使用 引入文件 先引入jQuery 再引入pagination组件 2 具体效果 3 html代码
  • ubuntu挂载Windows共享文件夹

    1 windows下设置shared文件夹为共享文件夹 2 linux下执行命令 sudo apt get install cifs utils samba client sudo mount t cifs o username dhc p
  • linux下搭建测试环境

    linux应用服务器 腾讯云服务器 centos7 传送文件上传到 linux服务器 winscp 文件传输工具 jdk及tomcat安装 本服务器安装的是jkd1 8 tomcat8 mysql 5 7 下载jkd1 8 https ww
  • Mysql在大型网站的应用架构演变

    摘要 本文主要描述在网站的不同的并发访问量级下Mysql架构的演变历程 架构的可扩展性往往和并发是息息相关 没有并发的增长 也就没有必要做高可扩展性的架构 常用的扩展手段主要有Scale up和Scale out两种 前者为纵向扩展 主要通
  • Java八大基本数据类型

    Java八大基本数据类型 开发工具与关键技术 MyEclipse 10 java 作者 刘东标 撰写时间 2019 04 04 Java语言提供了八种基本类型 六种数字类型 四个整数型 两个浮点型 一种字符类型 还有一种布尔型 1 数据类型
  • Windows下创建进程简介

    正在执行的应用程序称为进程 进程不仅仅是指令和数据 它还有状态 状态是保存在处理器寄存器中的一组值 如当前执行指令的地址 保存在内存中的值 以及唯一定义进程在任一时刻任务的所有其他值 进程与应用程序的一个重要的区别在于 进程运行时 进程的状
  • Linux笔记:文本编辑器vi基础使用

    文章目录 目的 工作模式 命令行模式 默认模式 光标移动 屏模滚动 选择复制黏贴与删除 搜索与替换 撤销与重复 插入模式 总结 目的 vi是几乎所有Unix Linux系统下都自带的文本编辑器 有点类似于window上的记事本 如果用惯了现
  • Sophus库的安装和使用教程

    本系列文章为原创 转载请注明出处 作者 Dongdong Bai 邮箱 baidongdong nudt edu 若您觉得本博文对您有帮助 请您为我点赞并关注我 以鼓励我写出更优秀的博文 谢谢 一 Sophus库简介 Eigen库是一个开源