ceres库,g2o库做BA问题,效果对比

有关优化库的一点点对比思考(g2o / ceres solver / gtsam / TORO and iSAM) gtsam:gtsam是一个基于因子图的库,提供了丰富的功能和工具来解决SLAM和机器人导航等问题。它具有清晰的接口和易用性,适合于相对较小的优化问题和需要高级特性的应用场景。TORO和iSAM:TORO和iSAM是针对特定应用领域的库,它们提供了一些特定的算法和数据结构,适用于大规模图优化和增量式优化。g2o:g2o是一个高度灵活和可扩展的库,提供了对稀疏矩阵和图优化的支持。它在初步图优化领域的应用中非常流行。除了上述的官方文档和代码库,还可以参考相关的学术论文和书籍来深入了解图优化算法和应用。 阅读详情

BA是Bundle Adjustment,Bundle指bundles of light rays。
也就是说,通过调整(adjustment) 各相机姿态和各特征点的空间位置,使这些光线最终收束到相机的光心。

相机坐标系到归一化坐标,畸变模型这些就不说了。

BA求解本质上是用最小二乘法优化一个误差,这个误差是观测点与实际的路标通过相机外参映射到像素坐标系的点的误差。
e = z − h ( T , p ) e = z - h(T, p) e=z−h(T,p)
而需要调整的变量是相机位姿和路标(两个同时调整)。

以高斯牛顿法为例,还是要求雅可比矩阵J,然后H = JJT, b=-Je, H Δ x = b H\Delta x = b HΔx=b,
求更新量 Δ x \Delta x Δx, 不断迭代更新。

这里面临的问题是直接求H-1运算量随着特征点增加会非常大。
所以利用了H矩阵的稀疏性质,通过消元可以把路标点的那部分给整成对角矩阵。

理论依据就是消元后固定路标点的更新量,先求相机位姿的更新量,
求完了以后代回去,再求路标点的更新量。

当然这个更新,消元都可以用Ceres, g2o库来解决。

下面就是Ceres, g2o库求解BA的代码。

BA数据集用的是华盛顿大学给出的一个,参考链接
数据格式,相机坐标系到像素坐标系的转换方法也在链接中,它的只有归一化相机坐标,原点在光心,而不是以往的原点在左上角。
有畸变模型在里面。

Ceres实现主要注意的就是要重载()运算符,定义残差。
然后用ceres::Solve函数求解。
包含了下面的include的头文件,当然里面还有自带的其他头文件,就不写了,完整代码参考代码链接

#include <iostream>
#include "ceres/ceres.h"
#include "rotation.h"

class SnavelyReprojectionError {
public:
    SnavelyReprojectionError(double observation_x, double observation_y) : observed_x(observation_x), observed_y(observation_y) {}

    template<typename T>
    //const T *const camera: camera是指针常量,指针不能修改,同时camera指向的是常量,也不能修改,函数后const:不能修改类的成员,只读函数
    bool operator() (const T *const camera, const T *const point, T *residuals) const {
        // camera[0,1,2] are the angle-axis rotation
        T predictions[2];
        CamProjectionWithDistortion(camera, point, predictions);  //预测点的位置
        residuals[0] = predictions[0] - T(observed_x);  //x误差
        residuals[1] = predictions[1] - T(observed_y);  //y误差

        return true;
    }

    // camera : 9 dims array
    // [0-2] : angle-axis rotation
    // [3-5] : translateion
    // [6-8] : camera parameter, [6] focal length, [7-8] second and forth order radial distortion
    // point : 3D location.
    // predictions : 2D predictions with center of the image plane.
    template<typename T>
    static inline bool CamProjectionWithDistortion(const T *camera, const T* point, T* predictions) {
        // Rodrigues' formula
        T p[3]; //保存旋转后的结果
        AngleAxisRotatePoint(camera, point, p);
        // camera[3,4,5] are the translation
        p[0] += camera[3];
        p[1] += camera[4];
        p[2] += camera[5];

        // Compute the center fo distortion, 归一化相机坐标, (x,y)原点在光心,不在左上角
        //计算方法参照https://grail.cs.washington.edu/projects/bal/
        T xp = -p[0] / p[2];  //x/z
        T yp = -p[1] / p[2];  //y/z

        const T &l1 = camera[7];  //取得地址
        const T &l2 = camera[8];

        T r2 = xp * xp + yp * yp;  //相当于||p||^2
        T distortion = T(1.0) + r2 * (l1 + l2 * r2);  //1 + k1||p||^2 + k2||p||^4

        const T &focal = camera[6];
        predictions[0] = focal * distortion * xp;
        predictions[1] = focal * distortion * yp;

        return true;
    }

    static ceres::CostFunction *Create(const double observed_x, const double observed_y) {
        return (new ceres::AutoDiffCostFunction<SnavelyReprojectionError, 2, 9, 3> ( //residual dim:2, x dim:9, y dim:3
                new SnavelyReprojectionError(observed_x, observed_y)));
    }
private:
    double observed_x;
    double observed_y;

};

还有一个主函数

void SolveBA(BALProblem &bal_problem) {
    const int point_block_size = bal_problem.point_block_size();
    const int camera_block_size = bal_problem.camera_block_size();
    double *points = bal_problem.mutable_points();
    double *cameras = bal_problem.mutable_cameras();

    // Observations is 2 * num_observations long array observations
    // [u_1, u_2, ... u_n], where each u_i is two dimensional, the x
    // and y position of the observation.
    const double *observations = bal_problem.observations();
    ceres::Problem problem;

    for (int i = 0; i < bal_problem.num_observations(); ++i) {
        ceres::CostFunction *cost_function;

        // Each Residual block takes a point and a camera as input
        // and outputs a 2 dimensional Residual
        cost_function = SnavelyReprojectionError::Create(observations[2 * i + 0], observations[2 * i + 1]);

        // If enabled use Huber's loss function.
        ceres::LossFunction *loss_function = new ceres::HuberLoss(1.0);

        // Each observation corresponds to a pair of a camera and a point
        // which are identified by camera_index()[i] and point_index()[i]
        // respectively.
        double *camera = cameras + camera_block_size * bal_problem.camera_index()[i];
        double *point = points + point_block_size * bal_problem.point_index()[i];

        problem.AddResidualBlock(cost_function, loss_function, camera, point);
    }

    // show some information here ...
    std::cout << "bal problem file loaded..." << std::endl;
    std::cout << "bal problem have " << bal_problem.num_cameras() << " cameras and "
              << bal_problem.num_points() << " points. " << std::endl;
    std::cout << "Forming " << bal_problem.num_observations() << " observations. " << std::endl;

    std::cout << "Solving ceres BA ... " << endl;
    ceres::Solver::Options options;
    options.linear_solver_type = ceres::LinearSolverType::SPARSE_SCHUR;
    options.minimizer_progress_to_stdout = true;
    ceres::Solver::Summary summary;
    ceres::Solve(options, &problem, &summary);
    std::cout << summary.FullReport() << "\n";
}

(2)g2o库解BA
g2o是一个图优化库,主要需要注意的是添加顶点和边,第一个顶点要固定住。
g2o如果是自己定义顶点,要继承BaseVertex类,自己定义边的话继承BaseBinaryEdge类,
继承后要实现基类中的一些virtual函数,
主要有以下要覆盖的:
1.设置原点:setToOriginImpl()
2.读写函数,读入数据,写出数据,不需要的时候就直接返回一个boolean,
virtual bool read(istream &in), virtual bool write(ostream &out)
3.update时的更新函数:virtual void oplusImpl(const double *update)
4.计算误差函数,用在边继承里面:virtual void computeError()

g2o库还有几个函数解释一下:
setEstimate函数:
g2o库自带的有_estimate变量,通过setEstimate函数来设置这个_estimate, 当要读取更新后的_estimate时,
用顶点的estimate()函数。
setMeasurement也是一样的原理。

/// 位姿加相机内参的顶点,9维,前三维为so3,接下去为t, f, k1, k2
//继承BaseVertex类,<9,T>, 9表示图顶点的最小维度,g2o是图优化库, T表示内部使用的表示估计的类
class VertexPoseAndIntrinsics : public g2o::BaseVertex<9, PoseAndIntrinsics> {
public:
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW; //new一个对象时会返回一个对齐的指针,指针内存位数对齐,因为Eigen为了加速使用了128位的指针,默认构造函数x86指针是32位

    VertexPoseAndIntrinsics() {}

    //加override, 强制在派生类中重写该函数,为了满足继承的所有条件,加override可以在派生类中写错时报错
    //设置原点操作
    virtual void setToOriginImpl() override {
        _estimate = PoseAndIntrinsics();
    }

    //实现相加运算符
    virtual void oplusImpl(const double *update) override {
        _estimate.rotation = SO3d::exp(Vector3d(update[0], update[1], update[2])) * _estimate.rotation; //更新rotation
        _estimate.translation += Vector3d(update[3], update[4], update[5]);
        _estimate.focal += update[6];
        _estimate.k1 += update[7];
        _estimate.k2 += update[8];
    }

    ///根据估计值投影一个点
    Vector2d project(const Vector3d &point) {
        Vector3d pc = _estimate.rotation * point + _estimate.translation; //旋转+平移
        //还是按https://grail.cs.washington.edu/projects/bal/的计算方法
        pc = -pc / pc[2];  //归一化相机坐标
        double r2 = pc.squaredNorm(); //长度的平方
        double distortion = 1.0 + r2 * (_estimate.k1 + _estimate.k2 * r2);
        return Vector2d(_estimate.focal * distortion * pc[0], _estimate.focal * distortion * pc[1]);
    }

    virtual bool read(istream &in) {return true;}

    virtual bool write(ostream &out) const {return true;}
};

class VertexPoint : public g2o::BaseVertex<3, Eigen::Vector3d> {
public:
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW;

    VertexPoint() {}

    //设置原点操作
    virtual void setToOriginImpl() override {
        _estimate = Vector3d(0, 0, 0);
    }

    //实现相加运算符
    virtual void oplusImpl(const double *update) override{
        _estimate += Vector3d(update[0], update[1], update[2]);
    }

    virtual bool read(istream &in) {return true;}

    virtual bool write(ostream &out) const {return true;}
};

//图的边映射
//4个参数:2:测量值(x,y), Vector2d:测量值的类型, 后面两个是不同顶点的类型
class EdgeProjection : public g2o::BaseBinaryEdge<2, Vector2d, VertexPoseAndIntrinsics, VertexPoint> {
public:
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW;

    virtual void computeError() override {
        auto v0 = (VertexPoseAndIntrinsics *) _vertices[0];  //相机参数,位姿
        auto v1 = (VertexPoint *) _vertices[1];  //观测点位置
        auto proj = v0->project(v1->estimate()); //映射到像素坐标,后面计算像素上的误差
        _error = proj - _measurement;  //推测值和测量值的误差
    }

    virtual bool read(istream &in) {}

    virtual bool write(ostream &out) const {}
};

void SolveBA(BALProblem &bal_problem) {
    const int point_block_size = bal_problem.point_block_size();
    const int camera_block_size = bal_problem.camera_block_size();
    double *points = bal_problem.mutable_points();
    double *cameras = bal_problem.mutable_cameras();

    //位姿维度为9, 观测点为3维
    typedef g2o::BlockSolver<g2o::BlockSolverTraits<9, 3>> BlockSolverType;
    typedef g2o::LinearSolverCSparse<BlockSolverType::PoseMatrixType> LinearSolverType;
    //use LM
    auto solver = new g2o::OptimizationAlgorithmLevenberg(
            g2o::make_unique<BlockSolverType>(g2o::make_unique<LinearSolverType>()) //std::unique_ptr<Solver>可以使用 make_uniqueunique_ptr 数组创建 ,但不能make_unique使用初始化数组元素
            ); //向 C unique_ptr ++ 标准库容器添加实例非常高效,因为移动 unique_ptr 构造函数无需复制操作。
    g2o::SparseOptimizer optimizer;
    optimizer.setAlgorithm(solver);
    optimizer.setVerbose(true);

    //build g2o problem
    const double *observations = bal_problem.observations();
    //vertex
    vector<VertexPoseAndIntrinsics *> vertex_pose_intrinsics;
    vector<VertexPoint *> vertex_points;

    //存入每个相机的位姿内参
    for(int i = 0; i < bal_problem.num_cameras(); ++i) {
        VertexPoseAndIntrinsics *v = new VertexPoseAndIntrinsics();
        double *camera = cameras + camera_block_size * i;
        v->setId(i);
        v->setEstimate(PoseAndIntrinsics(camera)); //_estimate = camera, update cache
        optimizer.addVertex(v);
        vertex_pose_intrinsics.push_back(v);
    }

    //存入观测点,3维
    for(int i = 0; i < bal_problem.num_points(); ++i) {
        VertexPoint *v = new VertexPoint();
        double *point = points + point_block_size * i;
        v->setId(i + bal_problem.num_cameras()); //data format中,camera存完了后面才是point
        v->setEstimate(Vector3d(point[0], point[1], point[2])); //设置_estimate变量
        //g2o需要在BA中手动设置待Marg的点
        v->setMarginalized(true); //边缘概率估计的是xp
        optimizer.addVertex(v);
        vertex_points.push_back(v);
    }

    //edge
    for(int i = 0; i < bal_problem.num_observations(); ++i) {
        EdgeProjection *edge = new EdgeProjection;
        edge->setVertex(0, vertex_pose_intrinsics[bal_problem.camera_index()[i]]);
        edge->setVertex(1, vertex_points[bal_problem.point_index()[i]]);
        edge->setMeasurement(Vector2d(observations[2 * i + 0], observations[2 * i + 1]));
        edge->setInformation(Matrix2d::Identity());  //g2o内部的_information矩阵
        edge->setRobustKernel(new g2o::RobustKernelHuber());
        optimizer.addEdge(edge);
    }

    optimizer.initializeOptimization();
    optimizer.optimize(40); //迭代次数

    //set to bal problem//更新数据
    for(int i = 0; i < bal_problem.num_cameras(); ++i) {
        double *camera = cameras + camera_block_size * i;
        auto vertex = vertex_pose_intrinsics[i];
        auto estimate = vertex->estimate();
        estimate.set_to(camera);
    }
    for(int i = 0; i < bal_problem.num_points(); i++) {
        double *point = points + point_block_size * i;
        auto vertex = vertex_points[i];
        for(int k = 0; k < 3; k++) point[k] = vertex->estimate()[k];
    }

}

ply文件的显示用meshlab
效果图:
没有优化之前的:
在这里插入图片描述ceres优化之后的
在这里插入图片描述g2o优化后的
在这里插入图片描述看下初始状态和优化后的对比,可看到初始状态噪声比较大,而优化后较聚集
在这里插入图片描述

看下ceres和g2o的对比吧,都会收敛一些,但是位置会有一些错开
在这里插入图片描述

(3分钟了解)SLAM后端优化的四大金刚!g2o ceres gtsam SE-Sync 总结:这篇博客中了解了SE-Sync的后端优化库,并且对后端优化的框架又有了一个新的认识和总结。就是说对偶问题的解是原问题的下确界,然后这两之间的差值被称为对偶间隙,并且当对偶间隙为0的时候,对偶问题的最优解即是原问题的最优解。添加图片注释,不超过 140 字(可选)添加图片注释,不超过 140 字(可选)添加图片注释,不超过 140 字(可选)添加图片注释,不超过 140 字(可选)添加图片注释,不超过 140 字(可选)添加图片注释,不超过 140 字(可选)添加图片注释,不超过 140 字(可选) 阅读详情

相关推荐

光束平差法(BA)在SLAM中的应用:从原理到落地,手把手教你优化相机位姿

本文深入解析了光束平差法(Bundle Adjustment)在SLAM系统中的核心作用与实现。作为优化相机位姿和三维地图点的关键算法,BA通过最小化重投影误差,有效解决视觉里程计的累积漂移问题。文章从数学原理出发,结合g2o和Ceres库的实战代码,详细讲解了BA的工程落地、性能调优技巧及与IMU的紧耦合优化,是提升SLAM系统精度的必备指南。

desk3的博客 1062

Ceres BA优化细解(一)

ceresBA算法学习与思考

balabala923的博客 1236

VINS 实战解析 - 从BA理论到Ceres实现的关键步骤拆解

本文深入解析了VINS中光束法平差(BA)的核心原理与Ceres实现。从重投影误差和LM算法的理论基石出发,详细拆解了如何将BA优化问题转化为C++代码,包括定义CostFunction、构建Problem以及配置求解器。文章重点阐述了如何利用Ceres库高效处理BA的稀疏性,并提供了使用四元数参数化、鲁棒核函数等关键工程实践与调试技巧,帮助开发者打通VINS从理论到实战的关键环节。

weixin_29266749的博客 111

位姿图优化(Ceres&G2O&GTSAM)

作为SLAM中常用的方法,其原因是因为SLAM观测不只考虑到当前帧的情况,而需要加入之前状态量的观测。就比如一个在二维平面上移动的机器人,机器人可以使用一组传感器,例如车轮里程计或激光测距仪。从这些原始测量值中,我们想要估计机器人的。为了降低问题的计算复杂度,。具体来说,。边缘是源自原始传感器测量值的虚拟测量值,例如通过集成原始车轮里程计或对齐从机器人获取的激光范围扫描。对上图的具体描述如下。

lovely_yoshino的博客 1万+

视觉SLAM笔记(53) g2o 操作后端优化

g2o 求解 BA

氢键H-H 1万+

SfM三维重建:BA优化【VS2015+OpenCV3.4+PCL1.8+Ceres Solver】

使用BA优化对SfM三维重建的结果进行非线性优化,环境:VS2015+OpenCV3.4+PCL1.8+Ceres Solver,包含两张图、多张图BA优化代码及images文件。

SLAM非线性优化终极指南:Ceres与g2o库的深度对比与实战选择

SLAM(同步定位与地图构建)技术中,非线性优化是核心环节,而Ceres Solver与g2o作为两大主流优化库,在精度、效率和易用性上各有千秋。本文将深入对比两者的技术特性,帮助开发者快速掌握选型策略与实战技巧,轻松应对SLAM项目中的优化难题。 ## 📊 核心功能对比:Ceres与g2o的技术特性 ### Ceres Solver:谷歌开源的通用优化引擎 Ceres Solver由谷歌开

gitblog_00737的博客 801

ceres非线性求解代码

ceres非线性问题求解器,解决SLAM,及方程求解,fitting等等问题

ceres-solver和g2o性能比较

ceres-solver 和 g2o 是slam领域常见的优化器,其中ceres-solver被vins-mono使用,而g2o被orb-slam3使用,因此到底哪个优化器更适合于在slam算法开发中使用?分别基于这两种优化器实现BA过程,然后针对同一个仿真数据集进行测试,测试程序链接: https://github.com/chennuo0125-HIT/test/tree/main/ceres_g2o_comparer,按readme进行编译运行可得如下结果: 说明 测试程序中的仿真数据来源于 g2o

chennuo0125的博客 2412

SpringBoot3 + Vben5.0实战:从零搭建企业级管理后台(附完整代码)

本文详细介绍了如何从零开始,使用SpringBoot3与Vben5.0技术栈搭建现代化企业级管理后台。通过对比分析,阐述了该组合在开发效率、性能(如虚拟线程)和权限模型(RBAC)方面的优势,并提供了从项目初始化、核心功能开发到部署运维的完整实战指南,帮助开发者快速构建高性能、易维护的后台系统。

weixin_29306317的博客 171

人大金仓集群部署(主备)

4.2 上传安装包镜像和授权文件到install目录下并授权。1、复制系统脚本到/opt/kingbase目录下(主节点)4.2 修改cluster_install.sh。回车进行下一步,直到出现以下界面,回复Y键回车。三、安装kingbase客户端段(都要安装)install目录作为安装包具体存放目录。4.1 修改install.conf文件。2、复制授权文件到安装目录下(主节点)3、修改ssh参数(节点都要配置)5、安装kingbase客户端。二、基本环境配置(都要配置)6、数据库集群安装(主节点)

edutech_wang的博客 1995

《视觉 SLAM 十四讲》V2 第 9 讲 后端优化1 【扩展卡尔曼滤波器 EKF && BA+非线性优化(Ceres、g2o)】

发射出来的几束光线(bundles of light rays), 它们会在几个相机的成像平面上变成像素或是检测到的特征点,如果我们调整(adjustment) 各相机姿态和各自特征点的空间位置,使得这些光纤最终收束到 相机的光心,称为 BA。把卡尔曼滤波器 的结果 扩展到 非线性系统中, 扩展卡尔曼滤波器。时刻状态 与 之前所有状态 的关系。前端视觉里程计: 短时间内的轨迹和地图。卡尔曼滤波器构成了线性系统的最优无偏估计。后端优化: 长时间内的最优轨迹和地图。的信息更新自己的状态,也会用。

weixin_46034116的博客 1088

WPS专业版自带字体

WPS专业版其中一个好处就是自带了部分有版权的字体,就算你安装了没买授权,他也会给你在系统里面安装上这些字体,至于没授权继续用合不合规我不知道。但是带来的实实在在的好处就是有些子他支持的全啊。 /usr/share/fonts/wps-office/FZWBK.TTF: 方正魏碑_GBK,FZWeiBei\-S03:style=Regular /usr/share/fonts/wps-office/FZFSK.TTF: 方正仿宋_GBK,FZFangSong\-Z02:style=Regular /us

chenqioulin的博客 5696

如何用ceres进行两帧之间的BA优化

学习高博的书已有很长一段时间了,一直看理论,看代码,而没有自己亲自上手,最近在做BA优化,大部分SLAM是用g2o进行的,而对于ceres用的很少,由于博主根本看不懂g2o的代码风格,个人觉得很无语(其实是博主zz),那咋办?,于是就想干脆用ceres实现BA优化吧。而关于ceres,其实主要还是残差的定义了,然后求解过程都是大同小异,直接上我写的代码struct cost_function_de...

SLAM_masterFei的博客 7433

从零到一:用STM32 FOC算法驯服无刷电机的艺术

本文详细介绍了如何使用STM32和FOC算法实现无刷电机的高性能控制。从硬件搭建、参数识别到闭环调节,一步步解析FOC算法的核心原理与调优技巧,帮助开发者掌握电机控制的关键技术,实现从零到一的精准驯服。

kkk56的博客 916

YOLO26全网首发:CVPR2026 FAA| 解决YOLO Neck跨尺度方向冲突--- FAAFusion频域对齐融合模块 | 暴力涨点篇

本文改进:FAAFusion引入YOLO neck ,代替nn.Upsample和Concat

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 638

ba_demo_ceres 项目教程

ba_demo_ceres 项目教程 1、项目介绍 ba_demo_ceres 是一个使用 Ceres Solver 实现的简单 Bundle Adjustment(BA)问题解决方案。该项目通过自定义的成本函数和局部参数化方法,在 SE(3) 空间中进行优化。项目的主要特点包括: 自定义成本函数:定义了适用于 Bundle Adjustment 问题的成本函数。 局部参数化:实现了两种版本的 ...

gitblog_00704的博客 458

IP-Guard安全网关实例

企业相关情况: 1.OA系统,主要为日常工作使用,该系统IP为192.168.1.2,端口为8080; 2.文件共享服务器,用于存放日常工作资料和文档,该文件共享服务器的IP为192.168.1.1,其中\\192.168.1.1\private 目录中的存放着公司重要文档,不能随意外传; 3.安全网关已采用串联的方式联入网络,IP为192.168.2.6,所有机器访问OA系统和文件共享服务...

IP-Guard专栏 705

第9讲 后端1

目录1 Ceres BA的书写1.1 源文件和头文件1.2 CMakeLists.txt文件1.3 执行结果 1 Ceres BA的书写 1.1 源文件和头文件 待更新 1.2 CMakeLists.txt文件   内容如下, find_package(Ceres REQUIRED) include_directories(${CERES_DIRECTORIES}) include_directories("/usr/include/eigen3") add_library(bal_common com

YMWM_的博客 1623

55、Mac OS X 10.2 安装、设置、卸载及故障排除全攻略

本博客全面解析了 Mac OS X 10.2 的安装、设置、卸载及故障排除方法。内容涵盖四种安装方式的适用场景及操作步骤、设置助手的详细配置流程、卸载注意事项与恢复建议,以及常见问题和进阶故障的解决办法。通过图文并茂的形式,帮助用户快速掌握 Mac OS X 10.2 的基础与高级操作,是使用该操作系统的实用指南。

qsc90123456的博客 151

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SLAM++ 增量式BA优化库

incSLAM++是3DV 2017最佳论文,源文件网址 https://sourceforge.net/p/slam-plus-plus/wiki/Home/ incSLAM++有两个创新点: 一是增量式Schur补更新。 如果delta更新是稀疏的,则采用增量式Schur补来求解非线性最小二乘问题,即增量式BA问题,会缩短计算时间。 求解不同关键帧之间的位姿和每帧上的点即求解增量式BA(解不是全局的),就是求解如下非线性最小二乘问题 在每次迭代时,在初始点附近利用泰勒展开进行线性化,得到如下最小二乘问

格物致知 756

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

slam十四讲-ch9(后端1)-卡尔曼滤波器公式推导及BA优化代码实现【注释】(应该是ch13前面最难的部分了)

一、KF以及EKF公式推导(卡尔曼滤波和线性近似卡尔曼滤波) 前提:概率论相关知识

joun772的博客 2161

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Ceres计算Bundle Adjustment

Bundle Adjustment,中文名称是光束法平差,经典的BA目的是优化相机的pose和landmark,其在SfM和SLAM 领域中扮演者重要角色。开发Ceres的主要原因之一是需要解决大规模的Bundle Adjustment. 目前bundle adjustment 优化框架最为代表的是ceres solver和g2o ,据说ceres的命名是天文学家Piazzi闲暇无事的时候观测一颗没有观测到的星星,最后用least squares算出了这个小行星的轨道,故将这个小行星命名为ceres。

nuc_baixu的博客 781

RTAB-Map相机位姿图优化:基于BA的全局一致性调整终极指南

RTAB-Map作为一款功能强大的开源视觉SLAM库,其相机位姿图优化技术是实现高精度地图构建的关键。本文将深入探讨RTAB-Map中基于束调整(Bundle Adjustment)的全局一致性调整方法,帮助您理解如何通过优化算法提升SLAM系统的精度和鲁棒性。RTAB-Map的位姿图优化模块通过多种优化策略,包括g2o、GTSAM、Ceres和CVSBA等,为不同应用场景提供灵活的优化解决方案。

gitblog_00446的博客 652

SLAM14讲之ch10: Ceres求解BA

说明 本文整理了几个对SLAM14讲ch10ceres求解BA的理解,由于原文格式看得很累,故转载在此。原文链接 1. 前言 g2o是根据边来保存每一个代价函数,它是在边类中构造误差函数,构造边的时候,会设置顶点、测量值、协方差矩阵等。 而在ceres中,用problem类型来构造最终的目标函数。 先是使用AddResidualBlock来添加代价函数,代价函数和核函数等构造成目标函数。 在cer...

GeneralShark 2278
上一篇: g2o_viewer安装及一些坑
下一篇: slam 单目稠密深度详解
蓝羽飞鸟
博客等级 码龄8年 1万+粉丝 727原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝羽飞鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值