首页 > 其他分享 >优化原理 (1)高斯牛顿 线性

优化原理 (1)高斯牛顿 线性

时间:2024-07-18 13:08:26浏览次数:8  
标签:SE3 高斯 牛顿 Sophus dx 线性 estimate block Eigen

 

 

 

 

 

 增量方程

 

 

 

#include <iostream>

#include <Eigen/Core>
#include <Eigen/Dense>
#include <Eigen/Geometry>

#include "sophus/se3.hpp"
#include "sophus/so3.hpp"

int main(void){
    // 优化变量为李代数se(3)的平移向量
    typedef Eigen::Matrix<double, 6, 1> Vector6d;
    // 数据点
    std::vector<Eigen::Vector3d> pts1, pts2;
    // 随机数生成器
    std::default_random_engine generator;
    std::normal_distribution<double> noise(0., 1.);
    // 构造相机位姿,作为参考位姿
    Eigen::Matrix3d R = Eigen::AngleAxisd(M_PI/2, Eigen::Vector3d(0,0,1)).toRotationMatrix();
    Eigen::Vector3d t(1,0,0);
    Sophus::SE3d SE3_Rt(R, t);
    // 观测数据
    for (int i = 0; i < 100; ++i) {
        double x = noise(generator), y = noise(generator), z = noise(generator);
        pts1.push_back(Eigen::Vector3d(x, y, z)); // 相机坐标系下的点
        pts2.push_back(SE3_Rt * pts1[i]); // 世界坐标系下的点
    }
    // 开始Gauss-Newton迭代,初始位姿为参考位姿+扰动
    Sophus::SE3d SE3_estimate(R*Eigen::AngleAxisd(0.1, Eigen::Vector3d::UnitZ()).toRotationMatrix(), 
                            t+Eigen::Vector3d(0.1, 0.0, 0.0));
    enum {
        DLEFT = 0, // 左扰动
        DRIGHT = 1, // 右扰动
    };
    int disturb = DRIGHT;
    for (int iter = 0; iter < 100; ++iter) {
        Eigen::Matrix<double, 6, 6> H = Eigen::Matrix<double, 6, 6>::Zero();
        Eigen::Matrix<double, 6, 1> b = Eigen::Matrix<double, 6, 1>::Zero();
        double cost = 0;
        for (int i = 0; i < pts1.size(); ++i) {
            // compute cost for pts1[i] and pts2[i]
            Eigen::Vector3d p = pts1[i], pc = pts2[i]; // p为相机坐标系下的点,pc为世界坐标系下的点
            Eigen::Vector3d pc_est = SE3_estimate * p; // 估计的世界坐标系下的点
            Eigen::Vector3d e = pc_est - pc; // 残差
            cost += e.squaredNorm() / 2;
            // compute jacobian
            Eigen::Matrix<double, 3, 6> J = Eigen::Matrix<double, 3, 6>::Zero();
            if(disturb == DRIGHT){
                // 右扰动
                J.block<3,3>(0,0) = Eigen::Matrix3d::Identity();
                J.block<3,3>(0,3) = -SE3_estimate.rotationMatrix() * Sophus::SO3d::hat(p);
            } else{
                // 左扰动
                J.block<3,3>(0,0) = Eigen::Matrix3d::Identity();
                J.block<3,3>(0,3) = -Sophus::SO3d::hat(SE3_estimate.rotationMatrix() * p);
            }
            // compute H and b
            H += J.transpose() * J;
            b += -J.transpose() * e;
        }
        // solve dx 
        Vector6d dx = H.ldlt().solve(b);
        if (dx.norm() < 1e-6) {
            break;
        }
        // update estimation
        if(disturb == DRIGHT){
            // 右乘更新
            SE3_estimate.so3() = SE3_estimate.so3() * Sophus::SO3d::exp(dx.block<3,1>(3,0));
            SE3_estimate.translation() += dx.block<3,1>(0,0);
        } else{
            // 左乘更新
            SE3_estimate.so3() = Sophus::SO3d::exp(dx.block<3,1>(3,0)) * SE3_estimate.so3();
            SE3_estimate.translation() += dx.block<3,1>(0,0);
        }

        std::cout << "iteration " << iter << " cost=" << cost << std::endl;
    }
    std::cout << "estimated pose: \n" << SE3_estimate.matrix() << std::endl;
    std::cout << "ground truth pose: \n" << SE3_Rt.matrix() << std::endl;
}

  

bug记录

右乘se3的exp映射时,结果有问题,而左乘没问题

初步定位到问题,在求导时,不是对SE3求导,而是对平移向量和旋转向量分别求导,然后再组合起来,这和SE3求导结果不同.

暂时不管了,SE3右乘雅可比有点复杂,高翔书中也是分开求导和更新的,就这样吧。

// se3右乘更新, 有问题
SE3_estimate = SE3_estimate * Sophus::SE3d::exp(dx); 
// 分开更新,没问题
SE3_estimate.so3() = SE3_estimate.so3() * Sophus::SO3d::exp(dx.block<3,1>(3,0));
SE3_estimate.translation() += dx.block<3,1>(0,0);

  

标签:SE3,高斯,牛顿,Sophus,dx,线性,estimate,block,Eigen
From: https://www.cnblogs.com/gooutlook/p/18309306

相关文章

  • 高等代数 第三章 线性空间
    知识复习向量的线性关系我们先从方程入手把它写成向量的形式,分别用\(\alpha_i,\beta\)表示上面的列向量,那么方程等价于\(\sumx_i\alpha_i=\beta\)如果考虑齐次方程,那么$\sumx_i\alpha_i=0$,\(0\)肯定是一个解,但是我们想知道的是有没有非平凡的解,也就是说有没有一组不......
  • Halcon的学习笔记(一)——非线性字符识别
    Halcon非线性模式的字符识别(ocr_cd_print_polar_trans.hdev例程分析)Halcon的学习笔记(一)——非线性字符识别项目上需要对非线性模式的字符进行识别,halcon中包含的例程,我搜了一下,网上对于该例程的解析比较少,因此自己便记录了一下自己的学习例程,也算自己的学习笔记。1.什......
  • 【数学】高斯消元
    1.算法简介高斯消元法(Gauss–Jordanelimination)是求解线性方程组的经典算法。例如求解下列方程组:\(\begin{cases}2x+9y-5z=10\\4x+20y+z=24\\x-2y+3z=8\end{cases}\)形式化的,高斯消元可用于求解类似于\(\begin{cases}a_{1,1}x_1+a_{1,2}x_2+\dots+a_{1,n}x_n=b......
  • 基于FPGA的MSK调制解调系统verilog开发,包含testbench,同步模块,高斯信道模拟模块,误
    1.算法仿真效果本程序系统是《m基于FPGA的MSK调制解调系统verilog开发,并带FPGA误码检测模块和matlab仿真程序》的的升级。 升级前原文链接 增加了完整的AWGN信道模型的FPGA实现,可以在testbench里面设置SNR,分析不同SNR对应的FPGA误码率情况。 vivado2019.2仿真结果如下(......
  • R语言贝叶斯MCMC:用rstan建立线性回归模型分析汽车数据和可视化诊断|附代码数据
    全文链接 http://tecdat.cn/?p=23255最近我们被客户要求撰写关于rstan的研究报告,包括一些图形和统计输出。本文将谈论Stan以及如何在R中使用rstan创建Stan模型尽管Stan提供了使用其编程语言的文档和带有例子的用户指南,但对于初学者来说,这可能是很难理解的。StanStan是一种用......
  • 电工电子实验——集成运算放大器的非线性应用
    正弦波形产生电路实验目的加深理解RC桥式正弦振荡器的工作原理。学习并掌握RC桥式正弦振荡器的设计方法和步骤。掌握RC桥式正弦振荡器的调试方法。主要仪器设备及软件硬件:硬件:双踪示波器、函数信号发生器、直流稳压电源、交流毫伏表、实验箱、万用表、阻容元件及导线......
  • 机器学习实战笔记4线性回归
    线性回归首先看一下线性回归方程,就是用代码来编写方程1.numpy正规方程线性回归importnumpyasnpimportpandasaspddf=pd.DataFrame({'years':[1,2,3,4,5,6],'salary':[4000,4250,4500,4750,5000,5250]})df生成dfm=len(df)m输出:6x1=df......
  • 华为高斯数据库openGauss_5.0.2 企业版部署学习
    系统环境欧拉系统官方下载链接openEuler-22.03-LTS-SP4-x86_64-dvd.iso https://mirrors.tuna.tsinghua.edu.cn/openeuler/openEuler-22.03-LTS-SP4/ISO/x86_64/openEuler-22.03-LTS-SP4-x86_64-dvd.iso openEuler下载|openEulerISO镜像|openEuler社区官网 数据库安......
  • 数据分享|R语言逻辑回归、线性判别分析LDA、GAM、MARS、KNN、QDA、决策树、随机森林、
    全文链接:http://tecdat.cn/?p=27384最近我们被客户要求撰写关于葡萄酒的研究报告,包括一些图形和统计输出。在本文中,数据包含有关葡萄牙“VinhoVerde”葡萄酒的信息介绍该数据集(查看文末了解数据获取方式)有1599个观测值和12个变量,分别是固定酸度、挥发性酸度、柠檬酸、残糖、......
  • 王道数据结构课后习题详细分析 第二章线性表 2.1线性表的定义和基本操作
    单项选择题————————————————————————————————————————解析:正确答案:C————————————————————————————————————————解析:A:集合中的元素没有前后驱关系,错误;C:序列中整数不是有限个,错......