g2o曲线拟合参数y = a sin( b * t + c) + d

g2o_fit.cpp

#include <iostream>
#include <fstream>
#include <Eigen/Core>
#include <g2o/core/base_vertex.h>
#include <g2o/core/base_unary_edge.h>
#include <g2o/core/block_solver.h>
#include <g2o/core/optimization_algorithm_levenberg.h>
#include <g2o/solvers/dense/linear_solver_dense.h>
#include <g2o/types/slam3d/types_slam3d.h>
#include <g2o/types/sba/types_six_dof_expmap.h>
#include <g2o/core/sparse_optimizer.h>
#include <g2o/core/optimization_algorithm_levenberg.h>
#include <g2o/core/optimization_algorithm_factory.h>

// 自定义顶点
class VertexParameters : public g2o::BaseVertex<4, Eigen::Vector4d> {
public:
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW

    void setToOriginImpl() override {
        _estimate << 1.0, 1.0, 0.0, 0.0;
    }

    void oplusImpl(const double* update) override {
        _estimate += Eigen::Map<const Eigen::Vector4d>(update);
    }

    bool read(std::istream& is) override { return false; }

    bool write(std::ostream& os) const override { return false; }
};

// 自定义边
class EdgeResidual : public g2o::BaseUnaryEdge<1, double, VertexParameters> {
public:
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW

    EdgeResidual(double t, double y)
        : t_(t), y_(y) {}

    void computeError() override {
        // TODO: 完成这个函数(提示:需要对 _error[0] 进行赋值)
        const VertexParameters* v =static_cast<const VertexParameters*>(_vertices[0]);
        const Eigen::Vector4d abcd =  v->estimate();
        double a = abcd[0], b = abcd[1], c = abcd[2], d = abcd[3];
        _error(0,0) = y_ - (a * sin( b * t_ + c ) + d) ;
    }

    void linearizeOplus() override {
        // TODO: 完成这个函数(提示:需要对 _jacobianOplusXi 进行赋值)=
        VertexParameters* vi = static_cast<VertexParameters*>(_vertices[0]);
        Eigen::Vector4d abcd = vi -> estimate();
        double a = abcd[0], b = abcd[1], c = abcd[2], d = abcd[3];
        _jacobianOplusXi(0,0) = -sin( b * t_ + c );
        _jacobianOplusXi(0,1) = -a*t_*cos( b * t_ + c );
        _jacobianOplusXi(0,2) = -a*cos( b * t_ + c );
        _jacobianOplusXi(0,3) = -1;
    }

    bool read(std::istream& is) override { return false; }

    bool write(std::ostream& os) const override { return false; }

    double t_;
    double y_;
};

int main() {
    double w_sigma = 2.0;
    // 从文件中读取数据
    std::vector<double> t_values;
    std::vector<double> y_values;

    std::ifstream file("../data.txt");  // 注意修改为自己的文件路径
    if (!file) {
        std::cerr << "Error opening file." << std::endl;
        return 1;
    }

    // 读取数据到程序中
    double t, y;
    while (file >> t >> y) {
        t_values.push_back(t);
        y_values.push_back(y);
    }

    // 构建g2o优化器
    g2o::SparseOptimizer optimizer;
    typedef g2o::BlockSolver< g2o::BlockSolverTraits<4, 1>>  Block;
    std::unique_ptr<Block::LinearSolverType> linearSolver (new g2o::LinearSolverDense<Block::PoseMatrixType> ());
    std::unique_ptr<Block > blockSolver (new Block (std::move(linearSolver)));
    g2o::OptimizationAlgorithmLevenberg* algorithm = new g2o::OptimizationAlgorithmLevenberg(std::move(blockSolver));

    optimizer.setAlgorithm(algorithm);

    // 添加顶点
    VertexParameters* parameters = new VertexParameters();
    /***    开始(添加顶点)    ***/ 
    parameters -> setEstimate ( Eigen::Vector4d (1,1,0,0));
    parameters -> setId(0);
    optimizer.addVertex (parameters);
    /***    结束(添加顶点)    ***/ 


    // 添加边
    for (size_t i = 0; i < t_values.size(); ++i) {
        /***    开始(添加边)    ***/ 
        EdgeResidual* edge = new EdgeResidual(t_values[i],y_values[i]);
        edge -> setId(i);
        edge -> setVertex( 0 , parameters );
        edge -> setMeasurement ( y_values[i] );
        edge -> setInformation (Eigen::Matrix<double,1,1>::Identity()*1/(w_sigma*w_sigma));
        edge -> t_ = t_values[i]; 
        optimizer.addEdge(edge);
        /***    结束(添加边)    ***/ 
    }

    // 开始优化
    optimizer.initializeOptimization();
    optimizer.optimize(10);

    // 打印优化结果
    std::cout << "Optimization results:" << std::endl;
    std::cout << "Estimated parameters: " << parameters->estimate().transpose() << std::endl;

    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(g2oFit)

set(CMAKE_CXX_STANDARD 17)

find_package(Eigen3 REQUIRED)
find_package(g2o REQUIRED)

include_directories(${EIGEN3_INCLUDE_DIRS})
include_directories(${G2O_INCLUDE_DIRS})

add_executable(g2o_fit g2o_fit.cpp)
target_link_libraries(g2o_fit g2o_core g2o_stuff)

data.txt 数据

0	0.76757
0.10101	0.93524
0.20202	1.1466
0.30303	1.1455
0.40404	1.154
0.50505	1.3246
0.60606	1.5646
0.70707	1.4691
0.80808	1.7375
0.90909	1.6842
1.0101	1.6719
1.1111	1.7399
1.2121	1.9719
1.3131	1.9569
1.4141	1.9843
1.5152	1.8329
1.6162	2.1149
1.7172	1.9869
1.8182	2.0363
1.9192	2.114
2.0202	1.8387
2.1212	1.9638
2.2222	1.7445
2.3232	1.6328
2.4242	1.893
2.5253	1.7023
2.6263	1.6607
2.7273	1.4326
2.8283	1.4774
2.9293	1.2658
3.0303	1.2903
3.1313	1.0478
3.2323	1.0599
3.3333	1.1794
3.4343	0.87257
3.5354	0.6227
3.6364	0.52524
3.7374	0.27585
3.8384	0.3178
3.9394	0.2932
4.0404	0.18571
4.1414	-0.10813
4.2424	-0.11886
4.3434	-0.23174
4.4444	-0.35856
4.5455	-0.53086
4.6465	-0.6226
4.7475	-0.63279
4.8485	-0.75072
4.9495	-0.81937
5.0505	-0.7828
5.1515	-0.81525
5.2525	-0.93389
5.3535	-0.92959
5.4545	-0.85862
5.5556	-1.055
5.6566	-0.96281
5.7576	-0.94334
5.8586	-1.0017
5.9596	-0.97491
6.0606	-0.91803
6.1616	-0.94708
6.2626	-0.67075
6.3636	-0.75539
6.4646	-0.76205
6.5657	-0.63985
6.6667	-0.37652
6.7677	-0.60884
6.8687	-0.28017
6.9697	-0.14374
7.0707	-0.046163
7.1717	-0.14572
7.2727	0.28633
7.3737	0.19477
7.4747	0.37418
7.5758	0.40421
7.6768	0.58243
7.7778	0.57071
7.8788	0.79059
7.9798	0.86386
8.0808	1.0311
8.1818	1.203
8.2828	1.2812
8.3838	1.4714
8.4848	1.4824
8.5859	1.2881
8.6869	1.5937
8.7879	1.8294
8.8889	1.8893
8.9899	2.0411
9.0909	1.8181
9.1919	2.0668
9.2929	1.981
9.3939	2.0563
9.4949	2.0291
9.596	2.0428
9.697	2.0146
9.798	1.9306
9.899	1.7098
10	1.7872

结果

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值