Eigen 的简单使用 与 轨迹拟合代码的理解

工作中遇到一个问题,发到hmi的车辆引导线为斜的,有一说一,仔细看下这段代码,发现用到了Eigen库用来多项式曲线拟合,线性回归,矩阵向量计算等。

#include <iostream>
#include <vector>
#include <eigen3/Eigen/Dense>

int main()
{
  Eigen::MatrixXd matrix_a;
  matrix_a.resize(2,2);
  Eigen::IOFormat fmt;
  fmt.rowPrefix='[';
  fmt.rowSuffix=']';
  fmt.coeffSeparator=',';
  matrix_a(0,0)=1;
  matrix_a(0,1)=2;
  matrix_a(1,0)=3;
  matrix_a(1,1)=4;
  std::cout<<matrix_a.format(fmt)<<std::endl;
  std::cout<<"矩阵转置"<<std::endl;
  std::cout<<matrix_a.transpose().format(fmt)<<std::endl;
  std::cout<<"逆矩阵"<<std::endl;
  std::cout<<matrix_a.inverse().format(fmt)<<std::endl;

  return 0;
}

/*输出
[1,2]
[3,4]
矩阵转置
[1,3]
[2,4]
逆矩阵
[  -2,   1]
[ 1.5,-0.5]

如下图,通过一系列点拟合一元三次方程,表示轨迹线:

 

 利用 Eigen库完成计算,开始想着直接调用 inverse 接口不就行了?试着改了下代码,直接报错了,看提示是 Assertion `rows() == cols()' failed.

哦,忘记方阵才有逆矩阵了,既然拟合的点数量与方程阶数不一定对应,所以不能直接求 X 的逆矩阵,借用转置矩阵来计算。

(设拟合点数量为n)

下面的函数用于求得 Y=XC中Y(n阶向量)与X(n行3列矩阵)调用的时候 order 给3。

void XYTrajectoryPoly(const std::vector<Point>& traj, unsigned int order, Eigen::MatrixXd& Xs,Eigen::VectorXd& Ys) {

  Xs.resize(traj.size(), order + 1);
  Ys.resize(traj.size());
  for (uint32_t i = 0; i < traj.size(); ++i) {
    for (uint32_t j = 0; j < order + 1; ++j) {
      Xs(i, j) = std::pow(traj[i].x, j);
    }
    Ys(i) = traj[i].y;
  }
}

下面的函数,接收Y与X,返回由方程的系数组成的向量,transpose返回转置矩阵,inverse返回逆矩阵 

void LinearRegression(const Eigen::MatrixXd& Xs,const Eigen::VectorXd& Ys, 
Eigen::VectorXd& Ck) {
  Eigen::MatrixXd Pk;
  Pk = (Xs.transpose() * Xs).inverse();
  Ck = Pk * Xs.transpose() * Ys;
}

Eigen::VectorXd 的读取,下列代码输出-15

  Eigen::VectorXd Ck;
  Ck.resize(3);
  Ck(0)=10;
  Ck(1)=15;
  Ck(2)=3;
  std::cout<<-Ck(1)<<std::endl; 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
QT是一个跨平台的C++图形用户界面应用程序开发框架,而Eigen是一个C++模板,用于线性代数计算,其中包含了许多矩阵和向量的运算。因此,使用QT和Eigen实现曲线拟合是一种非常方便和高效的方法。 下面是一段使用QT和Eigen进行曲线拟合代码: ```cpp #include <QtGui> #include <QtCore> #include <Eigen/Dense> QVector<double> xData, yData; // 读取数据 void readData(const QString &fileName) { QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return; xData.clear(); yData.clear(); QTextStream in(&file); while (!in.atEnd()) { QString line = in.readLine(); QStringList fields = line.split(","); if (fields.size() != 2) continue; xData.append(fields.toDouble()); yData.append(fields.toDouble()); } } // 曲线拟合 void fitCurve() { int n = xData.size(); Eigen::MatrixXd A(n, 3); Eigen::VectorXd b(n); for (int i = 0; i < n; ++i) { A(i, 0) = xData[i] * xData[i]; A(i, 1) = xData[i]; A(i, 2) = 1; b(i) = yData[i]; } Eigen::VectorXd x = A.colPivHouseholderQr().solve(b); double a = x(0), b = x(1), c = x(2); qDebug() << "f(x) = " << a << "x^2 + " << b << "x + " << c; } int main(int argc, char *argv[]) { QApplication app(argc, argv); readData("data.txt"); fitCurve(); return app.exec(); } ``` 这段代码实现了从文件中读取数据,并使用Eigen对数据进行曲线拟合,最后输出拟合函数的系数。具体来说,这里使用了二次函数对数据进行拟合,可以根据具体情况选择其他的函数形式。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值