ORB-SLAM3源码学习:G2oTypes.cc: void EdgeInertial::linearizeOplus计算残差对状态增量的雅克比矩阵

server/2024/12/20 7:39:21/

前言

这个函数和计算残差函数一样需要学习g2o和IMU相关的公式。

1.函数声明

void EdgeInertial::linearizeOplus()

2.函数定义 

可以用下面这样的表格来表示这些雅可比矩阵的关系

涉及到的IMU公式: 

 未提及的雅可比矩阵则在表格对应处为0矩阵

// 计算残差对状态增量的雅克比矩阵
void EdgeInertial::linearizeOplus()
{// 获取因子图的顶点与计算残差函数的顶点对应const VertexPose* VP1 = static_cast<const VertexPose*>(_vertices[0]);const VertexVelocity* VV1= static_cast<const VertexVelocity*>(_vertices[1]);const VertexGyroBias* VG1= static_cast<const VertexGyroBias*>(_vertices[2]);const VertexAccBias* VA1= static_cast<const VertexAccBias*>(_vertices[3]);const VertexPose* VP2 = static_cast<const VertexPose*>(_vertices[4]);const VertexVelocity* VV2= static_cast<const VertexVelocity*>(_vertices[5]);const IMU::Bias b1(VA1->estimate()[0],VA1->estimate()[1],VA1->estimate()[2],VG1->estimate()[0],VG1->estimate()[1],VG1->estimate()[2]);const IMU::Bias db = mpInt->GetDeltaBias(b1);Eigen::Vector3d dbg;dbg << db.bwx, db.bwy, db.bwz;const Eigen::Matrix3d Rwb1 = VP1->estimate().Rwb;  // Riconst Eigen::Matrix3d Rbw1 = Rwb1.transpose();     // Ri.t()const Eigen::Matrix3d Rwb2 = VP2->estimate().Rwb;  // Rjconst Eigen::Matrix3d dR = mpInt->GetDeltaRotation(b1).cast<double>();const Eigen::Matrix3d eR = dR.transpose()*Rbw1*Rwb2;        // r△Rijconst Eigen::Vector3d er = LogSO3(eR);                      // r△φijconst Eigen::Matrix3d invJr = InverseRightJacobianSO3(er);  // Jr^-1(log(△Rij))// _jacobianOplus个数等于边的个数,里面的大小等于观测值维度(也就是残差)× 每个节点待优化值的维度// Jacobians wrt Pose 1// _jacobianOplus[0] 9*6矩阵 总体来说就是三个残差分别对pose1的旋转与平移(p)求导_jacobianOplus[0].setZero();// rotation// (0,0)起点的3*3块表示旋转残差对pose1的旋转求导_jacobianOplus[0].block<3,3>(0,0) = -invJr*Rwb2.transpose()*Rwb1;// (3,0)起点的3*3块表示速度残差对pose1的旋转求导_jacobianOplus[0].block<3,3>(3,0) = Sophus::SO3d::hat(Rbw1*(VV2->estimate() - VV1->estimate() - g*dt));// (6,0)起点的3*3块表示位置残差对pose1的旋转求导_jacobianOplus[0].block<3,3>(6,0) = Sophus::SO3d::hat(Rbw1*(VP2->estimate().twb - VP1->estimate().twb- VV1->estimate()*dt - 0.5*g*dt*dt));// translation// (6,3)起点的3*3块表示位置残差对pose1的位置求导_jacobianOplus[0].block<3,3>(6,3) = -Eigen::Matrix3d::Identity();// Jacobians wrt Velocity 1// _jacobianOplus[1] 9*3矩阵 总体来说就是三个残差分别对pose1的速度求导_jacobianOplus[1].setZero();_jacobianOplus[1].block<3,3>(3,0) = -Rbw1;_jacobianOplus[1].block<3,3>(6,0) = -Rbw1*dt;// Jacobians wrt Gyro 1// _jacobianOplus[2] 9*3矩阵 总体来说就是三个残差分别对陀螺仪偏置的速度求导_jacobianOplus[2].setZero();_jacobianOplus[2].block<3,3>(0,0) = -invJr*eR.transpose()*RightJacobianSO3(JRg*dbg)*JRg;_jacobianOplus[2].block<3,3>(3,0) = -JVg;_jacobianOplus[2].block<3,3>(6,0) = -JPg;// Jacobians wrt Accelerometer 1// _jacobianOplus[3] 9*3矩阵 总体来说就是三个残差分别对加速度计偏置的速度求导_jacobianOplus[3].setZero();_jacobianOplus[3].block<3,3>(3,0) = -JVa;_jacobianOplus[3].block<3,3>(6,0) = -JPa;// Jacobians wrt Pose 2// _jacobianOplus[4] 9*6矩阵 总体来说就是三个残差分别对pose2的旋转与平移(p)求导_jacobianOplus[4].setZero();// rotation_jacobianOplus[4].block<3,3>(0,0) = invJr;// translation_jacobianOplus[4].block<3,3>(6,3) = Rbw1*Rwb2;// Jacobians wrt Velocity 2// _jacobianOplus[5] 9*3矩阵 总体来说就是三个残差分别对pose2的速度求导_jacobianOplus[5].setZero();_jacobianOplus[5].block<3,3>(3,0) = Rbw1;
}

结束语 

以上就是我学习到的内容,如果对您有帮助请多多支持我,如果哪里有问题欢迎大家在评论区积极讨论,我看到会及时回复。


http://www.ppmy.cn/server/151648.html

相关文章

C语言-稀疏数组转置

1.题目要求 2.代码实现 #include <stdio.h> #define MAX_TERM 80// 定义稀疏矩阵结构体 typedef struct juzhen {int row;int col;int value; } Juzhen;// 显示稀疏矩阵 void show(Juzhen a[], int count_a) {printf(" i row col val\n");for (int i 1; i &…

DePIN潜力项目Spheron解读:激活闲置硬件,赋能Web3与AI

DePIN赛道作为今年加密资本关注的热点之一&#xff0c;不仅吸引了大量资金涌入&#xff0c;还凭借其灵活的资源调配、高效的运作方式和可靠的安全性能&#xff0c;逐渐渗透到多个领域和项目中。例如&#xff0c;Helium的无线网络协议、IoTeX的去中心化物联网、IO NET的去中心化…

Spring Boot 声明式事务

Spring Boot中的声明式事务管理主要通过Transactional注解来实现。以下是Transactional注解的一些关键用法和特性&#xff1a; 1. 启用事务管理 在Spring Boot应用中使用Transactional注解之前&#xff0c;需要在启动类或者配置类上添加EnableTransactionManagement注解来启用事…

SQL或ORM获取随机一行数据

MySQL 使用ORDER BY RAND()结合LIMIT来实现。例如,有一个名为employees的表,要从中随机获取一行数据,可以使用以下语句: SELECT * FROM employees ORDER BY RAND() LIMIT 1; 使用order_by(?) 在 Django 中,可以使用order_by(?)来对查询集进行随机排序,然后取第一条数…

Python构造方法:对象的“开机启动程序”

在Python中&#xff0c;构造方法&#xff08;__init__&#xff09;是一个类的“生命之初”&#xff0c;定义了每个对象从“出生”到“投入使用”的整个初始化过程。那既然类里可以直接写属性&#xff0c;为什么还需要构造方法呢&#xff1f; 构造方法的核心作用&#xff1a;创…

搭建MongoDB

title: 搭建MongoDB date: 2024-11-30 23:30:00 categories: - 服务器 tags: - MongoDB - 大数据搭建MongoDB 环境&#xff1a;Centos 7-2009 1. 创建MongoDB的国内yum源 # 下载Centos7对应最新版7.0.15的安装包 cat >> /etc/yum.repos.d/mongodb.repo << &quo…

生态学研究中,森林生态系统的结构、功能与稳定性是核心研究

在生态学研究中&#xff0c;森林生态系统的结构、功能与稳定性是核心研究内容之一。这些方面不仅关系到森林动态变化和物种多样性&#xff0c;还直接影响森林提供的生态服务功能及其应对环境变化的能力。森林生态系统的结构主要包括物种组成、树种多样性、树木的空间分布与密度…

Docker 部署 新版 Nacos、Seata

Docker 部署 新版 Nacos、Seata 版本说明 名称版本号Nacos2.4.3Seata2.0.0 Nacos 启动容器 # MODEstandalone 系统启动方式: 单机 # NWEzYzdkNmMtZjQ5Ny00ZDY4LWE3MWEtMmU1ZTMzNDBiM2Nh 为 5a3c7d6c-f497-4d68-a71a-2e5e3340b3ca 的Base64 编码表示,可以修改&#xff0c;…