利用平面进行位姿约束优化

cpp 复制代码
/**
 * 设位姿pose存在误差,利用观测到的平面进行位姿pose优化,只优化位姿pose的z轴平移和roll,pitch,yaw四个变量,要求优化后的pose,z轴与平面的z一致。请修改代码实现这个功能
 * 
 * 
 */
#include <gtsam/slam/PriorFactor.h>
#include <gtsam/nonlinear/NonlinearFactorGraph.h>
#include <gtsam/nonlinear/Values.h>
#include <gtsam/nonlinear/GaussNewtonOptimizer.h>
#include <gtsam/geometry/OrientedPlane3.h>
#include <gtsam/geometry/Pose3.h>
#include <gtsam/inference/Symbol.h>
#include <boost/optional.hpp>
#include <iostream>

using namespace gtsam;

// 自定义因子类
class CustomOrientedPlane3Factor : public NoiseModelFactor1<Pose3> {
    OrientedPlane3 measured_;

public:
    CustomOrientedPlane3Factor(const OrientedPlane3& measured, const SharedNoiseModel& model, Key poseKey)
        : NoiseModelFactor1<Pose3>(model, poseKey), measured_(measured) {}

    // 误差评估函数
    Vector evaluateError(const Pose3& pose, boost::optional<Matrix&> H = boost::none) const override {
        OrientedPlane3 transformedPlane = measured_.transform(pose, H); // 变换平面
        
        // 单独定义误差据向量
        double zError = pose.translation().z() - transformedPlane.planeCoefficients()(3);
        Vector3 normalError = transformedPlane.planeCoefficients().head<3>() - measured_.planeCoefficients().head<3>();

        Vector error(4); // 定义为4维向量
        error << normalError, zError; // 确保合并的正确顺序

        if (H) {
            *H = Matrix::Zero(4, 6); // 初始化 4x6 矩阵
            (*H)(3, 5) = 1.0; // 对z方向的偏导数
            // 这里需要自行计算剩余的angular部分根据误差函数的特定定义


        }

        return error; // 返回误差
    }
};

int main() {
    NonlinearFactorGraph graph;

    // 初始位姿,只允许z的平移以及旋转freedom
    Pose3 initialPose(Rot3::Ypr(0.1, 0.1, 0.1), Point3(10.5, 20.4, 1.2));
    Vector6 poseConstraint;
    poseConstraint << 0.0, 0.0, 1.0, 1.0, 1.0, 1.0; // 仅允许调整z, roll, pitch, yaw
    auto poseNoise = noiseModel::Diagonal::Sigmas(poseConstraint * 0.1);
    graph.add(PriorFactor<Pose3>(Symbol('x', 0), initialPose, poseNoise));
    // 输出初始位姿
    std::cout << "Initial Pose:\n" << initialPose << std::endl;

    // 观测到的平面
    // OrientedPlane3 observedPlane1(0, 0, 1, -1.0); // 假设z是我们的目标
    // 添加多个观测平面
    std::vector<OrientedPlane3> observedPlanes = {
        OrientedPlane3(0, 0, 1, -1.5),  // 平面 1
        OrientedPlane3(0, 0, 1, -2.0),  // 平面 2
        OrientedPlane3(0, 0, 1, -1.0),  // 平面 3
        OrientedPlane3(0, 0, 1, -0.5)   // 平面 4
        // 其他平面可根据需求添加
    };

    auto planeNoise = noiseModel::Isotropic::Sigma(4, 1e-3);

    // 添加因子
    // graph.add(boost::make_shared<CustomOrientedPlane3Factor>(observedPlane1, planeNoise, Symbol('x', 0)));
    // 为所有平面添加因子
    for (size_t i = 0; i < observedPlanes.size(); ++i) {
        graph.add(boost::make_shared<CustomOrientedPlane3Factor>(observedPlanes[i], planeNoise, Symbol('x', 0)));
    }

    Values initialEstimate;
    initialEstimate.insert(Symbol('x', 0), initialPose);

    GaussNewtonParams params;
    params.setMaxIterations(10);
    params.setRelativeErrorTol(1e-5);
    GaussNewtonOptimizer optimizer(graph, initialEstimate, params);
    Values result = optimizer.optimize();

    // 输出优化结果
    std::cout << "Optimized Pose:\n" << result.at<Pose3>(Symbol('x', 0)) << std::endl;

    return 0;
}
相关推荐
澄岚明雪13 分钟前
力扣经典题目之55.跳跃游戏
算法·leetcode·职场和发展
柠石榴1 小时前
【练习】力扣热题100 有效的括号
c++·算法·leetcode·职场和发展
迪小莫学AI2 小时前
高效解决 LeetCode 2270: 分割数组的方案数
算法·leetcode·职场和发展
egoist20232 小时前
数据结构之顺序结构二叉树(超详解)
c语言·开发语言·数据结构·学习·算法·二叉树·向上/下调整算法
pzx_0013 小时前
【论文阅读】基于空间相关性与Stacking集成学习的风电功率预测方法
论文阅读·人工智能·算法·机器学习·bootstrap·集成学习
梅茜Mercy3 小时前
蓝桥杯备赛:顺序表和单链表相关算法题详解(上)
算法·职场和发展·蓝桥杯
廖显东-ShirDon 讲编程4 小时前
《零基础Go语言算法实战》【题目 4-3】请用 Go 语言编写一个验证栈序列是否为空的算法
算法·程序员·go语言·web编程·go web
圆圆滚滚小企鹅。4 小时前
刷题记录 回溯算法-10:93. 复原 IP 地址
数据结构·python·算法·leetcode
多多*5 小时前
初识JVM HotSopt 的发展历程
java·开发语言·jvm·c++·学习·算法
axecute5 小时前
矩阵Strassen 算法
线性代数·算法·机器学习·矩阵