代码编织梦想

Ceres-solver 曲线拟合及参数优化实例

1.ceres库的安装

  • 本人用的是ubuntu20.04系统,关于ceres-solver库的安装教程网上有许多,大家可以去其他人博客进行搜索,我只说几个注意事项。
  • 首先,装ceres之前必须安装eigen3,但是部分版本的ceres(比如高翔的github里提供的安装包)会与eigen 3.3.7冲突,所以我安装的是3.2.92(貌似是这个版本)
  • 另外,安装前需要安装它的依赖项,以ubuntu为例
  • sudo apt-get install liblapack-dev libsuitesparse-dev libcxsparse3 libgflags-dev libgoogle-glog-dev libgtest-dev
  • 不同的ubuntu版本略有区别,不再赘述

2.实例介绍

我们建立的优化模型为:
优化模型
真实的训练集为150对(任意设置),优化的参数为两个1维参数,当然也可以设置为1个2维参数。
首先,我们拟定参数a,b的真实值,假如a=2.0,b=6.0,把它们代入方程,并对计算结果加一定的高斯白噪合。就得到了我们的训练集,设置初始估计参数值(比如a_guji=1.0,b_guji=8.0)基于带噪声的训练集进行最小二乘曲线拟合(或者说是回归),可以迭代得到较佳的参数。

3.代码讲解

  • ceres_wb.cpp
#include "ceres/ceres.h"
#include "glog/logging.h"
#include <iostream>
#include <opencv2/core/core.hpp>
#include <ceres/ceres.h>
#include <chrono>
#include <vector>


using namespace std;
using ceres::AutoDiffCostFunction;
using ceres::CostFunction;
using ceres::Problem;
using ceres::Solve;
using ceres::Solver;




struct CostFunction_wb
{
    //CostFunction_wb类的构造函数
    CostFunction_wb(double x,double y):_x(x),_y(y)
    {
        //cout<<"------------gouzao function -------------------------";
        
    }
    
    //函数模板、函数调用重载、计算损失函数
    template<typename T>
    bool operator()(const T* const a,const T* const b,T* const residual) const
    {
    //避免报错,用T进行强制类型转换
        residual[0] = T(_y)-(ceres::exp(a[0]*T(_x))+ceres::exp(b[0]*T(_x)));
        return true;
        
    }
    
    //成员:训练集(训练数据对)
    const double _x,_y;
};

//主函数
int main()
{
	//设置的真实参数
    double a_real = 2.0,b_real=6.0;
    //初始估计参数
    double a_guji = 1.0,b_guji=8.0;
    
    //数据的对数
    int N = 150;
    
    //噪声参数
    double w_sigma = 1.0;
    double inv_sigma = 1.0/w_sigma;
    cv::RNG rng;
    
    //double ab[2] = {a_guji,b_guji};  
	// 如果当作一个2维参数的话可以这么设置,但同时需要改动一些其它内容
    double a = a_guji;
    double b = b_guji;
    
    //定义double 类型容器
    vector<double> x_train,y_train;
	//通过循环,设置x_train、y_train
    for (int i = 0 ;i <  N;i++)
    {
        double x = double(i)/150.0;

        x_train.push_back(x);
        
        double y = (exp(a_real*x)+exp(b_real*x)+rng.gaussian(inv_sigma));
        y_train.push_back(y);
    }
    //通过迭代器访问容器中的数据
    cout<<"---------------------------"<<endl;
    for (vector<double>::iterator it=x_train.begin();  it != x_train.end() ;it++) 
    {
        cout<<*it<<endl;
    }
    
    cout<<"---------------------------"<<endl;
    
    for (vector<double>::iterator it =y_train.begin();  it != y_train.end() ;it++) 
    {
        cout<<*it<<endl;
    }
    cout<<"---------------------------"<<endl;
    
 
 //定义最小二乘问题的一种形式   
/*
    ceres::Problem problem;
    for (int i = 0;i<N;i++)
    {
        problem.AddResidualBlock(
            new ceres::AutoDiffCostFunction<CostFunction_wb,1,1,1>(
                new CostFunction_wb(x_train[i],y_train[i]
                    )
        ),
        nullptr,
        &a,
        &b
    );
            
    }
 */
//我习惯于采用下面这种形式
ceres::Problem problem;
for (int i=0;i<N;i++)
{
//这是一个模板类,<CostFunction_wb, 1, 1, 1>分别为<损失函数计算模板、误差维度、第一个优化参数维度、第二个优化参数维度,......>
CostFunction* cost_function= new AutoDiffCostFunction<CostFunction_wb, 1, 1, 1>(
            new CostFunction_wb(x_train[i],y_train[i])); 
//CostFunction_wb(x_train[i],y_train[i])); 调用重载的(),计算误差、

//nullptr表示核函数为空,&a,&b为引用形式,为被优化的参数
problem.AddResidualBlock(cost_function, nullptr, &a,&b);
    
} 

//查看源码,Options中有很多配置项
ceres::Solver::Options options;
//增量方程的求解方式
options.linear_solver_type = ceres::DENSE_NORMAL_CHOLESKY;
//输出
options.minimizer_progress_to_stdout = true;
//优化信息
ceres::Solver::Summary summary;
//都设置好了,开始优化
ceres::Solve(options,&problem,&summary);
//输出所有迭代的优化信息
cout<<summary.BriefReport()<<endl;

//输出最终结果
cout<< a_guji<<"->"<<a<<endl;
cout<< b_guji<<"->"<<b<<endl;

return 0;
    
    
}

  • 最后的结果显示为:
---------------------------
0
0.00666667
0.0133333
0.02
0.0266667
0.0333333
0.04
0.0466667
0.0533333
0.06
0.0666667
0.0733333
0.08
0.0866667
0.0933333
0.1
0.106667
0.113333
0.12
0.126667
0.133333
0.14
0.146667
0.153333
0.16
0.166667
0.173333
0.18
0.186667
0.193333
0.2
0.206667
0.213333
0.22
0.226667
0.233333
0.24
0.246667
0.253333
0.26
0.266667
0.273333
0.28
0.286667
0.293333
0.3
0.306667
0.313333
0.32
0.326667
0.333333
0.34
0.346667
0.353333
0.36
0.366667
0.373333
0.38
0.386667
0.393333
0.4
0.406667
0.413333
0.42
0.426667
0.433333
0.44
0.446667
0.453333
0.46
0.466667
0.473333
0.48
0.486667
0.493333
0.5
0.506667
0.513333
0.52
0.526667
0.533333
0.54
0.546667
0.553333
0.56
0.566667
0.573333
0.58
0.586667
0.593333
0.6
0.606667
0.613333
0.62
0.626667
0.633333
0.64
0.646667
0.653333
0.66
0.666667
0.673333
0.68
0.686667
0.693333
0.7
0.706667
0.713333
0.72
0.726667
0.733333
0.74
0.746667
0.753333
0.76
0.766667
0.773333
0.78
0.786667
0.793333
0.8
0.806667
0.813333
0.82
0.826667
0.833333
0.84
0.846667
0.853333
0.86
0.866667
0.873333
0.88
0.886667
0.893333
0.9
0.906667
0.913333
0.92
0.926667
0.933333
0.94
0.946667
0.953333
0.96
0.966667
0.973333
0.98
0.986667
0.993333
---------------------------
2
2.21237
1.40938
1.73971
3.46703
2.01233
1.70614
2.72612
3.00471
1.41578
3.4043
2.66424
4.09549
0.911606
1.05668
2.50628
2.38599
5.12478
3.59973
2.04638
5.0677
2.85314
1.27693
2.32025
2.6228
4.05065
5.59522
5.17712
4.25452
4.14099
6.64492
5.334
6.42081
4.65459
4.60844
6.72447
5.88495
5.75299
6.07754
6.07208
7.70722
7.35717
7.0064
8.3867
6.86308
7.26311
7.93042
9.58624
6.7459
9.7192
9.1203
9.7625
10.2675
9.52092
11.3746
10.9377
13.1682
11.6283
11.541
13.4967
13.8428
14.4147
13.7406
14.1649
15.4079
14.8843
15.466
18.1992
18.3024
18.6754
17.8166
21.0222
21.7035
22.6213
21.4761
21.7317
24.7696
25.0446
24.5768
25.8985
27.3228
27.5297
30.0829
30.7993
31.8886
32.0986
35.1974
36.9065
36.2552
38.996
42.2008
44.0429
44.7269
44.6216
47.6321
46.2683
51.3162
52.1944
55.5224
54.764
58.4422
61.602
62.3484
63.9592
66.69
69.4857
72.4012
76.4786
79.7633
82.162
85.6288
89.5031
93.1653
96.5886
100.529
104.232
109.251
112.609
114.756
120.254
125.198
131.215
137.367
142.319
146.965
153.895
160.111
164.774
173.111
179.063
188.2
194.314
202.727
210.303
218.943
228.02
234.843
246.859
255.857
264.576
274.662
288.402
300.037
312.987
324.582
336.913
348.422
364.827
378.361
396.668
---------------------------
iter      cost      cost_change  |gradient|   |step|    tr_ratio  tr_radius  ls_iter  iter_time  total_time
   0  2.800582e+07    0.00e+00    6.22e+07   0.00e+00   0.00e+00  1.00e+04        0    1.39e-04    3.89e-04
   1  3.336077e+06    2.47e+07    9.62e+06   2.88e+01   8.81e-01  1.80e+04        1    2.53e-04    6.82e-04
   2  1.137862e+44   -1.14e+44    0.00e+00   7.88e+01  -3.41e+37  8.98e+03        1    1.40e-05    7.03e-04
   3  1.126377e+44   -1.13e+44    0.00e+00   7.88e+01  -3.38e+37  2.25e+03        1    1.23e-05    7.22e-04
   4  1.059894e+44   -1.06e+44    0.00e+00   7.88e+01  -3.18e+37  2.81e+02        1    1.16e-05    7.38e-04
   5  6.020607e+43   -6.02e+43    0.00e+00   7.85e+01  -1.81e+37  1.75e+01        1    1.17e-05    7.54e-04
   6  6.722646e+39   -6.72e+39    0.00e+00   7.39e+01  -2.02e+33  5.48e-01        1    1.16e-05    7.70e-04
   7  1.560786e+06    1.78e+06    5.23e+06   2.48e+01   9.14e-01  1.26e+00        1    4.73e-05    8.21e-04
   8  4.431107e+05    1.12e+06    2.06e+06   1.35e+02   8.85e-01  2.32e+00        1    3.29e-05    8.61e-04
   9  6.783076e+04    3.75e+05    6.08e+05   3.95e+01   9.32e-01  6.53e+00        1    3.18e-05    8.97e-04
  10  5.832397e+30   -5.83e+30    0.00e+00   1.34e+02  -8.80e+25  3.26e+00        1    1.18e-05    9.13e-04
  11  6.100081e+03    6.17e+04    1.51e+05   8.85e+01   9.68e-01  9.79e+00        1    3.14e-05    9.49e-04
  12  2.812897e+27   -2.81e+27    0.00e+00   4.17e+01  -4.92e+23  4.90e+00        1    1.18e-05    9.64e-04
  13  1.081967e+24   -1.08e+24    0.00e+00   3.77e+01  -1.93e+20  1.22e+00        1    1.17e-05    9.80e-04
  14  2.173602e+12   -2.17e+12    0.00e+00   2.39e+01  -4.73e+08  1.53e-01        1    1.17e-05    9.95e-04
  15  4.676127e+03    1.42e+03    1.30e+05   5.34e+00   9.98e-01  4.59e-01        1    3.15e-05    1.03e-03
  16  2.425519e+03    2.25e+03    8.98e+04   3.12e+00   9.75e-01  1.38e+00        1    3.16e-05    1.07e-03
  17  6.794241e+02    1.75e+03    3.76e+04   1.46e-01   9.92e-01  4.13e+00        1    3.25e-05    1.11e-03
  18  1.338226e+04   -1.27e+04    0.00e+00   5.14e+00  -2.45e+01  2.07e+00        1    1.19e-05    1.12e-03
  19  6.759603e+02    3.46e+00    4.55e+04   3.27e+00   7.81e-03  1.06e+00        1    3.17e-05    1.16e-03
  20  1.918510e+02    4.84e+02    1.80e+04   3.23e-01   9.72e-01  3.17e+00        1    3.17e-05    1.19e-03
  21  1.035504e+02    8.83e+01    4.24e+03   1.56e-02   9.98e-01  9.52e+00        1    3.16e-05    1.23e-03
  22  8.403323e+01    1.95e+01    2.45e+03   3.14e-01   9.74e-01  2.85e+01        1    3.15e-05    1.26e-03
  23  7.762016e+01    6.41e+00    9.52e+02   1.97e-01   9.77e-01  8.56e+01        1    3.16e-05    1.30e-03
  24  7.693629e+01    6.84e-01    1.15e+02   6.21e-02   9.93e-01  2.57e+02        1    3.15e-05    1.33e-03
  25  7.692457e+01    1.17e-02    3.63e+00   9.11e-03   9.95e-01  7.71e+02        1    3.15e-05    1.37e-03
Ceres Solver Report: Iterations: 26, Initial cost: 2.800582e+07, Final cost: 7.692457e+01, Termination: CONVERGENCE
1->2.0209
8->5.99873
  • a=2.0209,b=5.99873,非常接近真实值+
  • 除此之外,ceres库中注释详细介绍了ceres库的用法,我复制一段供大家查看,在IDE中可以ctrl+鼠标左键进行查看。
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2015 Google Inc. All rights reserved.
// http://ceres-solver.org/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
//   used to endorse or promote products derived from this software without
//   specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Create CostFunctions as needed by the least squares framework, with
// Jacobians computed via automatic differentiation. For more
// information on automatic differentation, see the wikipedia article
// at http://en.wikipedia.org/wiki/Automatic_differentiation
//
// To get an auto differentiated cost function, you must define a class with a
// templated operator() (a functor) that computes the cost function in terms of
// the template parameter T. The autodiff framework substitutes appropriate
// "jet" objects for T in order to compute the derivative when necessary, but
// this is hidden, and you should write the function as if T were a scalar type
// (e.g. a double-precision floating point number).
//
// The function must write the computed value in the last argument
// (the only non-const one) and return true to indicate
// success. Please see cost_function.h for details on how the return
// value maybe used to impose simple constraints on the parameter
// block.
//
// For example, consider a scalar error e = k - x'y, where both x and y are
// two-dimensional column vector parameters, the prime sign indicates
// transposition, and k is a constant. The form of this error, which is the
// difference between a constant and an expression, is a common pattern in least
// squares problems. For example, the value x'y might be the model expectation
// for a series of measurements, where there is an instance of the cost function
// for each measurement k.
//
// The actual cost added to the total problem is e^2, or (k - x'k)^2; however,
// the squaring is implicitly done by the optimization framework.
//
// To write an auto-differentiable cost function for the above model, first
// define the object
//
//   class MyScalarCostFunctor {
//     MyScalarCostFunctor(double k): k_(k) {}
//
//     template <typename T>
//     bool operator()(const T* const x , const T* const y, T* e) const {
//       e[0] = T(k_) - x[0] * y[0] + x[1] * y[1];
//       return true;
//     }
//
//    private:
//     double k_;
//   };
//
// Note that in the declaration of operator() the input parameters x and y come
// first, and are passed as const pointers to arrays of T. If there were three
// input parameters, then the third input parameter would come after y. The
// output is always the last parameter, and is also a pointer to an array. In
// the example above, e is a scalar, so only e[0] is set.
//
// Then given this class definition, the auto differentiated cost function for
// it can be constructed as follows.
//
//   CostFunction* cost_function
//       = new AutoDiffCostFunction<MyScalarCostFunctor, 1, 2, 2>(
//            new MyScalarCostFunctor(1.0));             ^  ^  ^
//                                                       |  |  |
//                            Dimension of residual -----+  |  |
//                            Dimension of x ---------------+  |
//                            Dimension of y ------------------+
//
// In this example, there is usually an instance for each measumerent of k.
//
// In the instantiation above, the template parameters following
// "MyScalarCostFunctor", "1, 2, 2", describe the functor as computing a
// 1-dimensional output from two arguments, both 2-dimensional.
//
// AutoDiffCostFunction also supports cost functions with a
// runtime-determined number of residuals. For example:
//
//   CostFunction* cost_function
//       = new AutoDiffCostFunction<MyScalarCostFunctor, DYNAMIC, 2, 2>(
//           new CostFunctorWithDynamicNumResiduals(1.0),   ^     ^  ^
//           runtime_number_of_residuals); <----+           |     |  |
//                                              |           |     |  |
//                                              |           |     |  |
//             Actual number of residuals ------+           |     |  |
//             Indicate dynamic number of residuals --------+     |  |
//             Dimension of x ------------------------------------+  |
//             Dimension of y ---------------------------------------+
//
// The framework can currently accommodate cost functions of up to 10
// independent variables, and there is no limit on the dimensionality
// of each of them.
//
// WARNING #1: Since the functor will get instantiated with different types for
// T, you must to convert from other numeric types to T before mixing
// computations with other variables of type T. In the example above, this is
// seen where instead of using k_ directly, k_ is wrapped with T(k_).
//
// WARNING #2: A common beginner's error when first using autodiff cost
// functions is to get the sizing wrong. In particular, there is a tendency to
// set the template parameters to (dimension of residual, number of parameters)
// instead of passing a dimension parameter for *every parameter*. In the
// example above, that would be <MyScalarCostFunctor, 1, 2>, which is missing
// the last '2' argument. Please be careful when setting the size parameters.

#ifndef CERES_PUBLIC_AUTODIFF_COST_FUNCTION_H_
#define CERES_PUBLIC_AUTODIFF_COST_FUNCTION_H_

#include "ceres/internal/autodiff.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/sized_cost_function.h"
#include "ceres/types.h"
#include "glog/logging.h"

namespace ceres {

// A cost function which computes the derivative of the cost with respect to
// the parameters (a.k.a. the jacobian) using an autodifferentiation framework.
// The first template argument is the functor object, described in the header
// comment. The second argument is the dimension of the residual (or
// ceres::DYNAMIC to indicate it will be set at runtime), and subsequent
// arguments describe the size of the Nth parameter, one per parameter.
//
// The constructors take ownership of the cost functor.
//
// If the number of residuals (argument kNumResiduals below) is
// ceres::DYNAMIC, then the two-argument constructor must be used. The
// second constructor takes a number of residuals (in addition to the
// templated number of residuals). This allows for varying the number
// of residuals for a single autodiff cost function at runtime.
template <typename CostFunctor,
          int kNumResiduals,  // Number of residuals, or ceres::DYNAMIC.
          int N0,       // Number of parameters in block 0.
          int N1 = 0,   // Number of parameters in block 1.
          int N2 = 0,   // Number of parameters in block 2.
          int N3 = 0,   // Number of parameters in block 3.
          int N4 = 0,   // Number of parameters in block 4.
          int N5 = 0,   // Number of parameters in block 5.
          int N6 = 0,   // Number of parameters in block 6.
          int N7 = 0,   // Number of parameters in block 7.
          int N8 = 0,   // Number of parameters in block 8.
          int N9 = 0>   // Number of parameters in block 9.
class AutoDiffCostFunction : public SizedCostFunction<kNumResiduals,
                                                      N0, N1, N2, N3, N4,
                                                      N5, N6, N7, N8, N9> {
 public:
  // Takes ownership of functor. Uses the template-provided value for the
  // number of residuals ("kNumResiduals").
  explicit AutoDiffCostFunction(CostFunctor* functor)
      : functor_(functor) {
    CHECK_NE(kNumResiduals, DYNAMIC)
        << "Can't run the fixed-size constructor if the "
        << "number of residuals is set to ceres::DYNAMIC.";
  }

  // Takes ownership of functor. Ignores the template-provided
  // kNumResiduals in favor of the "num_residuals" argument provided.
  //
  // This allows for having autodiff cost functions which return varying
  // numbers of residuals at runtime.
  AutoDiffCostFunction(CostFunctor* functor, int num_residuals)
      : functor_(functor) {
    CHECK_EQ(kNumResiduals, DYNAMIC)
        << "Can't run the dynamic-size constructor if the "
        << "number of residuals is not ceres::DYNAMIC.";
    SizedCostFunction<kNumResiduals,
                      N0, N1, N2, N3, N4,
                      N5, N6, N7, N8, N9>
        ::set_num_residuals(num_residuals);
  }

  virtual ~AutoDiffCostFunction() {}

  // Implementation details follow; clients of the autodiff cost function should
  // not have to examine below here.
  //
  // To handle varardic cost functions, some template magic is needed. It's
  // mostly hidden inside autodiff.h.
  virtual bool Evaluate(double const* const* parameters,
                        double* residuals,
                        double** jacobians) const {
    if (!jacobians) {
      return internal::VariadicEvaluate<
          CostFunctor, double, N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>
          ::Call(*functor_, parameters, residuals);
    }
    return internal::AutoDiff<CostFunctor, double,
           N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>::Differentiate(
               *functor_,
               parameters,
               SizedCostFunction<kNumResiduals,
                                 N0, N1, N2, N3, N4,
                                 N5, N6, N7, N8, N9>::num_residuals(),
               residuals,
               jacobians);
  }

 private:
  internal::scoped_ptr<CostFunctor> functor_;
};

}  // namespace ceres

#endif  // CERES_PUBLIC_AUTODIFF_COST_FUNCTION_H_

4.结果展示

  • 下面我通过matlab画图来进行结果分析:
    ceres最小二乘曲线拟合图

画图的源代码附在下面:

x_train=[0
0.00666667
0.0133333
0.02
0.0266667
0.0333333
0.04
0.0466667
0.0533333
0.06
0.0666667
0.0733333
0.08
0.0866667
0.0933333
0.1
0.106667
0.113333
0.12
0.126667
0.133333
0.14
0.146667
0.153333
0.16
0.166667
0.173333
0.18
0.186667
0.193333
0.2
0.206667
0.213333
0.22
0.226667
0.233333
0.24
0.246667
0.253333
0.26
0.266667
0.273333
0.28
0.286667
0.293333
0.3
0.306667
0.313333
0.32
0.326667
0.333333
0.34
0.346667
0.353333
0.36
0.366667
0.373333
0.38
0.386667
0.393333
0.4
0.406667
0.413333
0.42
0.426667
0.433333
0.44
0.446667
0.453333
0.46
0.466667
0.473333
0.48
0.486667
0.493333
0.5
0.506667
0.513333
0.52
0.526667
0.533333
0.54
0.546667
0.553333
0.56
0.566667
0.573333
0.58
0.586667
0.593333
0.6
0.606667
0.613333
0.62
0.626667
0.633333
0.64
0.646667
0.653333
0.66
0.666667
0.673333
0.68
0.686667
0.693333
0.7
0.706667
0.713333
0.72
0.726667
0.733333
0.74
0.746667
0.753333
0.76
0.766667
0.773333
0.78
0.786667
0.793333
0.8
0.806667
0.813333
0.82
0.826667
0.833333
0.84
0.846667
0.853333
0.86
0.866667
0.873333
0.88
0.886667
0.893333
0.9
0.906667
0.913333
0.92
0.926667
0.933333
0.94
0.946667
0.953333
0.96
0.966667
0.973333
0.98
0.986667
0.993333];
y_train = [2
2.21237
1.40938
1.73971
3.46703
2.01233
1.70614
2.72612
3.00471
1.41578
3.4043
2.66424
4.09549
0.911606
1.05668
2.50628
2.38599
5.12478
3.59973
2.04638
5.0677
2.85314
1.27693
2.32025
2.6228
4.05065
5.59522
5.17712
4.25452
4.14099
6.64492
5.334
6.42081
4.65459
4.60844
6.72447
5.88495
5.75299
6.07754
6.07208
7.70722
7.35717
7.0064
8.3867
6.86308
7.26311
7.93042
9.58624
6.7459
9.7192
9.1203
9.7625
10.2675
9.52092
11.3746
10.9377
13.1682
11.6283
11.541
13.4967
13.8428
14.4147
13.7406
14.1649
15.4079
14.8843
15.466
18.1992
18.3024
18.6754
17.8166
21.0222
21.7035
22.6213
21.4761
21.7317
24.7696
25.0446
24.5768
25.8985
27.3228
27.5297
30.0829
30.7993
31.8886
32.0986
35.1974
36.9065
36.2552
38.996
42.2008
44.0429
44.7269
44.6216
47.6321
46.2683
51.3162
52.1944
55.5224
54.764
58.4422
61.602
62.3484
63.9592
66.69
69.4857
72.4012
76.4786
79.7633
82.162
85.6288
89.5031
93.1653
96.5886
100.529
104.232
109.251
112.609
114.756
120.254
125.198
131.215
137.367
142.319
146.965
153.895
160.111
164.774
173.111
179.063
188.2
194.314
202.727
210.303
218.943
228.02
234.843
246.859
255.857
264.576
274.662
288.402
300.037
312.987
324.582
336.913
348.422
364.827
378.361
396.668];
plot (x_train,y_train ,"or")
hold on;
xlabel("x");
ylabel("y");
title("曲线拟合图");
x =[0:0.01:1];
y=exp(2.0209*x)+exp(5.99873*x);
plot(x,y,'-k','LineWidth',2);
%  hold on
%  xlim([0 1]);
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_52519143/article/details/126333774

既生瑜,何生亮?_茶话mcu的博客-爱代码爱编程

我们知道在STM32 MCU片内的常规定时器【基本定时器、通用定时器、高级定时器】里面,有个ARR寄存器,它负责配置定时器的计数时钟个数,进而决定每个计数周期的时长。【下图是计数器三种计数方式及溢出点的示意图,绿色圆圈表示溢出位置。】 对于基本定时器和通用定时器,每次溢出时都可以产生更新事件,该事件可以用来触发中断、触发DMA请求、触发其它

ceres-爱代码爱编程

安装(Linux) 安装方法:http://ceres-solver.org/installation.html 2.0版本要求使用C++14进行编译,如果使用C++11,则应该换用1.14版本 安装依赖项 # CM