MPC(模型预测控制)控制小车沿轨迹移动——C++实现

2023-05-16

任务说明

要求如下图所示,给定一条轨迹,要求控制小车沿这条轨迹移动,同时可以适用于系统带有延时的情况。注意,本篇文章只给出部分C++代码参考。

主要流程

首先用运动学自行车模型(Kinematic Bicycle Model)对小车建模,设计相应的成本函数(cost function)和约束,之后利用OSQP求解二次规划问题,实现线性时变模型预测控制(Linear Time-Varying MPC)器。

运动学自行车模型(Kinematic Bicycle Model)

首先我们来讲一下运动学自行车模型,如下图所示,小车的运动学模型可以当作是一个自行车,前轮控制拐的角度 \delta ,后轮控制加速度 a ,所以这两个量就是我们就控制量。系统的状态为惯性系中小车后轮的 x 和 y 的坐标, 惯性系速度 v 以及小车相对于惯性系的姿态角 \phi ,其微分的形式如下式所示:

线性时变模型预测控制(Linear Time-Varying MPC)

动力学系统模型

一个普通动力学系统的模型如下图所示,首先其状态量可以微分,其微分形式是关于系统状态和控制量的一个函数。其次系统的下一个状态也是相当于当前状态与当前状态采取的控制量相关的一个函数。

线性模型

如果一个动力学系统是线性的,那么就可以写成以下的形式,其中 A 和 B 是系数,如果不是时变模型的话,其值不会改变:

那么我们就可以将其推导成与初始状态 x_0 相关的形式:

那么其矩阵形式就是这样的:

线性时变模型

线性时变模型就是系统的系数 A 和 B会随时间 t 改变:

我们重看回运动学自行车模型,发现其系统模型并不是线性的(因为系统模型中存在三角函数),那么我们可以将其线性化,通过以下的形式,我们就可以将非线性模型转换成线性时变模型,其中上面带横线的变量是参考系统的状态和输出,也就是我们希望的状态量和输出量,比如说,我们希望系统的位置处于轨迹点上,并且速度为期望值。

我们会发现,相比于线性模型,会多出一个系数 g ,下面我们来通过线性化运动学自行车模型来看是不是会多出这一项。

线性化模型(Model linearization)

我们利用上面线性化的公式对运动学自行车模型进行线性化:

 那么就得到:

我们将其离散化,方便求解和控制:

其线性化模型的C++的代码如下, 其中 ll_就是公式中的 L,dt_ 就是时间 T_s

static constexpr int n = 4;  // state x y phi v
static constexpr int m = 2;  // input a delta
typedef Eigen::Matrix<double, n, n> MatrixA;
typedef Eigen::Matrix<double, n, m> MatrixB;
typedef Eigen::Vector4d VectorG;
typedef Eigen::Vector4d VectorX;
typedef Eigen::Vector2d VectorU;
void linearization(const double &phi, const double &v, const double &delta) {
    Ad_ <<  0, 0, -v*sin(phi), cos(phi),
            0, 0,  v*cos(phi), sin(phi),
            0, 0, 0, tan(delta) / ll_,
            0, 0, 0, 0;
    Bd_ <<  0, 0,
            0, 0,
            0, v/(ll_*pow(cos(delta),2)),
            1, 0;
    gd_ <<  v*phi*sin(phi), -v*phi*cos(phi), -v*delta/(ll_*pow(cos(delta),2)), 0;

    Ad_ = MatrixA::Identity() + dt_ * Ad_;
    Bd_ = dt_ * Bd_;
    gd_ = dt_ * gd_;
    return;
  }

设计成本函数(cost function)和约束

设计成本函数

我们要得到一个最优的控制量,那么就要有一个目标,这个目标要求整个系统从起始状态到终止状态的总成本最小,其可以分成两个部分,其中一个是表示系统状态转移时的成本,由当前状态和当前控制共同决定,另一个是系统到终止状态时花费的成本,两者相加就是总成本:

同时系统要满足系统状态转换的约束和一些等式约束和不等式约束:

在本次小车跟踪轨迹的任务中我们设计的成本函数是这样的,要求小车在当前位置与轨迹的位置误差和偏航角误差尽量小:

\large J=(x-x_{ref})^2+(y-y_{ref})^2+\rho (\phi-\phi_{ref})^2

那么我们就可以设计一个 Q 矩阵,其中每一个小方括号代表每一个系统状态,每一行对应 x 和 y 的坐标, 小车姿态角 \phi 以及速度 v ,如果我们设置预测步长为40个,那么就有40个小方括号,其中 \rho _N 表示最终状态的系数,由于系统的stage cost和terminal cost不一样所以设置得不一样,一般我们认为最终状态速度要为 0,所以最后一个元素就设置成 1:

那么系统的成本函数就可以写成如下形式,注意这里的 \large \textbf{x} 是一个向量,表示系统的状态:

\large J=(\textbf{x}-\textbf{x}_{ref})^T\textbf{Q}(\textbf{x}-\textbf{x}_{ref})

约束

这里我们设置的约束比较简单,就只是一些不等式约束:

\large -v_{max}\leqslant v\leqslant v_{max}

\large -a_{max}\leqslant a\leqslant a_{max}

\large -\delta_{max}\leqslant \delta\leqslant \delta _{max}

\large -\dot{\delta}_{max} * \Delta t\leqslant \dot{\delta}\leqslant \dot{\delta}_{max} * \Delta t

由于我们要输入到OSQP上,所以要对这些变量作一些处理,其C++代码如下,其中N_代表MPC的预测步长:

/* *
   *               /  x1  \
   *               |  x2  |
   *  lx_ <=  Cx_  |  x3  |  <= ux_
   *               | ...  |
   *               \  xN  /
   * */
  Eigen::SparseMatrix<double> Cx_, lx_, ux_;  // p, v constrains
  /* *
   *               /  u0  \
   *               |  u1  |
   *  lu_ <=  Cu_  |  u2  |  <= uu_
   *               | ...  |
   *               \ uN-1 /
   * */
  Eigen::SparseMatrix<double> Cu_, lu_, uu_;  // a delta vs constrains
  Eigen::SparseMatrix<double> Qx_;

// set size of sparse matrices
    P_.resize(m * N_, m * N_);
    q_.resize(m * N_, 1);
    Qx_.resize(n * N_, n * N_);
    // stage cost
    Qx_.setIdentity();
    for (int i = 1; i < N_; ++i) {
      Qx_.coeffRef(i * n - 2, i * n - 2) = rho_;
      Qx_.coeffRef(i * n - 1, i * n - 1) = 0;
    }
    Qx_.coeffRef(N_ * n - 4, N_ * n - 4) = rhoN_;
    Qx_.coeffRef(N_ * n - 3, N_ * n - 3) = rhoN_;
    Qx_.coeffRef(N_ * n - 2, N_ * n - 2) = rhoN_ * rho_;
    int n_cons = 4;  // v a delta ddelta
    A_.resize(n_cons * N_, m * N_);
    l_.resize(n_cons * N_, 1);
    u_.resize(n_cons * N_, 1);
    // v constrains
    Cx_.resize(1 * N_, n * N_);
    lx_.resize(1 * N_, 1);
    ux_.resize(1 * N_, 1);
    // a delta constrains
    Cu_.resize(3 * N_, m * N_);
    lu_.resize(3 * N_, 1);
    uu_.resize(3 * N_, 1);
    // set lower and upper boundaries
    for (int i = 0; i < N_; ++i) {
      // -a_max <= a <= a_max for instance:
      Cu_.coeffRef(i * 3 + 0, i * m + 0) = 1;
      lu_.coeffRef(i * 3 + 0, 0) = -a_max_;
      uu_.coeffRef(i * 3 + 0, 0) = a_max_;
      // ...
      Cu_.coeffRef(i * 3 + 1, i * m + 1) = 1;
      lu_.coeffRef(i * 3 + 1, 0) = -delta_max_;
      uu_.coeffRef(i * 3 + 1, 0) = delta_max_;

      Cu_.coeffRef(i * 3 + 2, i * m + 1) = 1;
      if (i > 0){
        Cu_.coeffRef(i * 3 + 2, (i - 1) * m + 1) = -1;
      }
      lu_.coeffRef(i * 3 + 2, 0) = -ddelta_max_ * dt_;
      uu_.coeffRef(i * 3 + 2, 0) = ddelta_max_ * dt_;

      // -v_max <= v <= v_max
      Cx_.coeffRef(i, i * n + 3) = 1;
      lx_.coeffRef(i, 0) = -v_max_;
      ux_.coeffRef(i, 0) = v_max_;
    }

求解二次规划问题

这样,我们就可以通过得到系统的当前状态 \textbf{x}_0,然后通过下式得到未来预测 N 步的状态,注意下式中的 A 和 B 此时已经不再是一样的,都是随时间而不同(也就是说其实是有下标的),因为现在是线性时变模型:

这个才是正确的,在下面的代码中就是AA BB gg矩阵的构建: 

之后我们就可以将我们要求解的问题根据OSQP的需要一步步处理完输进去。

具体怎么用OSQP求解可以参考下面这个链接,输入到OSQP的形式是什么样子的都可以看到:

使用OSQP解决二次凸优化(QP)问题

首先是cost function,我们先推导出其形式:

\large J=(\textbf{x}-\textbf{x}_{ref})^T\textbf{Q}(\textbf{x}-\textbf{x}_{ref})

这里为了表达方便,我们就作如下简化,分别用这几个变量代替: 

将下式代入到上式: 

\large \textbf{x}=\textbf{A}\textbf{x}_0 + \textbf{B}\textbf{u}+\textbf{g}=\bar{\textbf{T}}\textbf{x}_0 + \bar{\textbf{S}}\textbf{Z}+\textbf{g}

由于自变量是控制量 \textbf{Z} ,我们可以在推导的过程把没有 \textbf{Z} 的项直接去掉,推导的过程我就不一一写出来了,最后我们就可以得到:

\large J=\frac{1}{2}\textbf{Z}^T\bar{\textbf{S}}^T\textbf{Q}\bar{\textbf{S}}\textbf{Z}+[(\bar{\textbf{T}}\textbf{x}_0+\textbf{g})^T\textbf{Q}\bar{\textbf{S}}-{\textbf{x}_{ref}}^T\textbf{Q}\bar{\textbf{S}}]\textbf{Z}

那么输入到OSQP的前两个矩阵就是: 

\large H = \bar{\textbf{S}}^T\textbf{Q}\textbf{S} \ \ \ \ f= \textbf{S}\bar{\textbf{Q}}^T (\bar{\textbf{T}}\textbf{x}_0+\textbf{g})+\textbf{S}\textbf{q}_x

 其中:

\large \textbf{q}_x = -\textbf{Q}^T\textbf{x}_{ref}

之后我们把对应的上界约束和下界约束转换成与控制量有关的形式,输入进OSQP中,就能得出我们的最优控制量。下面就是相关的代码:

int solveQP(const VectorX& x0_observe) {
    x0_observe_ = x0_observe;
    historyInput_.pop_front();
    historyInput_.push_back(predictInput_.front());
    lu_.coeffRef(2, 0) = predictInput_.front()(1) - ddelta_max_ * dt_;
    uu_.coeffRef(2, 0) = predictInput_.front()(1) + ddelta_max_ * dt_;
    VectorX x0 = compensateDelay(x0_observe_);
    // set BB, AA, gg
    Eigen::MatrixXd BB, AA, gg;
    BB.setZero(n * N_, m * N_);
    AA.setZero(n * N_, n);
    gg.setZero(n * N_, 1);
    double s0 = s_.findS(x0.head(2));
    double phi, v, delta;
    double last_phi = x0(2);
    Eigen::SparseMatrix<double> qx;
    qx.resize(n * N_, 1);
    for (int i = 0; i < N_; ++i) {
      calLinPoint(s0, phi, v, delta);
      if (phi - last_phi > M_PI) {
          phi -= 2 * M_PI;
      } else if (phi - last_phi < -M_PI) {
          phi += 2 * M_PI;
      }
      last_phi = phi;
      linearization(phi, v, delta);
      // calculate big state-space matrices
      /* *                BB                AA
       * x1    /       B    0  ... 0 \    /   A \
       * x2    |      AB    B  ... 0 |    |  A2 |
       * x3  = |    A^2B   AB  ... 0 |u + | ... |x0 + gg
       * ...   |     ...  ...  ... 0 |    | ... |
       * xN    \A^(n-1)B  ...  ... B /    \ A^N /
       *
       *     X = BB * U + AA * x0 + gg
       * */
      if (i == 0) {
        BB.block(0, 0, n, m) = Bd_;
        AA.block(0, 0, n, n) = Ad_;
        gg.block(0, 0, n, 1) = gd_;
      } else {
        BB.block(i * n, i * m, n, m) = Bd_;
        for (int j = i - 1; j >= 0; --j){
          BB.block(i * n, j * m, n, m) = Ad_ * BB.block((i - 1) * n, j * m, n, m);
        }
        AA.block(i * n, 0, n, n) = Ad_ * AA.block((i - 1) * n, 0, n, n);
        gg.block(i * n, 0, n, 1) = Ad_ * gg.block((i - 1) * n, 0, n, 1) + gd_;
      }
      Eigen::Vector2d xy = s_(s0);  // reference (x_r, y_r)

      // cost function should be represented as follows:
      /* *
       *           /  x1  \T       /  x1  \         /  x1  \
       *           |  x2  |        |  x2  |         |  x2  |
       *  J =  0.5 |  x3  |   Qx_  |  x3  | + qx^T  |  x3  | + const.
       *           | ...  |        | ...  |         | ...  |
       *           \  xN  /        \  xN  /         \  xN  /
       * */

      qx.coeffRef(i * n + 0, 0) = -Qx_.coeffRef(i * n + 0, i * n + 0) * xy(0);
      qx.coeffRef(i * n + 1, 0) = -Qx_.coeffRef(i * n + 1, i * n + 1) * xy(1);
      qx.coeffRef(i * n + 2, 0) = -Qx_.coeffRef(i * n + 2, i * n + 2) * phi;
      qx.coeffRef(i * n + 3, 0) = -Qx_.coeffRef(i * n + 3, i * n + 3) * v;

      s0 += desired_v_ * dt_;
      s0 = s0 < s_.arcL() ? s0 : s_.arcL();
    }
    Eigen::SparseMatrix<double> BB_sparse = BB.sparseView();
    Eigen::SparseMatrix<double> AA_sparse = AA.sparseView();
    Eigen::SparseMatrix<double> gg_sparse = gg.sparseView();
    Eigen::SparseMatrix<double> x0_sparse = x0.sparseView();

    // state constrants propogate to input constraints using "X = BB * U + AA * x0 + gg"
    /* *
     *               /  x1  \                              /  u0  \
     *               |  x2  |                              |  u1  |
     *  lx_ <=  Cx_  |  x3  |  <= ux_    ==>    lx <=  Cx  |  u2  |  <= ux
     *               | ...  |                              | ...  |
     *               \  xN  /                              \ uN-1 /
     * */
    Eigen::SparseMatrix<double> Cx = Cx_ * BB_sparse;
    Eigen::SparseMatrix<double> lx = lx_ - Cx_ * AA_sparse * x0_sparse - Cx_ * gg_sparse;
    Eigen::SparseMatrix<double> ux = ux_ - Cx_ * AA_sparse * x0_sparse - Cx_ * gg_sparse;

    /* *      / Cx  \       / lx  \       / ux  \
     *   A_ = \ Cu_ /, l_ = \ lu_ /, u_ = \ uu_ /
     * */

    Eigen::SparseMatrix<double> A_T = A_.transpose();
    A_T.middleCols(0, Cx.rows()) = Cx.transpose();
    A_T.middleCols(Cx.rows(), Cu_.rows()) = Cu_.transpose();
    A_ = A_T.transpose();
    for (int i = 0; i < lx.rows(); ++i) {
      l_.coeffRef(i, 0) = lx.coeff(i, 0);
      u_.coeffRef(i, 0) = ux.coeff(i, 0);
    }
    for (int i = 0; i < lu_.rows(); ++i) {
      l_.coeffRef(i + lx.rows(), 0) = lu_.coeff(i, 0);
      u_.coeffRef(i + lx.rows(), 0) = uu_.coeff(i, 0);
    }
    Eigen::SparseMatrix<double> BBT_sparse = BB_sparse.transpose();
    P_ = BBT_sparse * Qx_ * BB_sparse;
    q_ = BBT_sparse * Qx_.transpose() * (AA_sparse * x0_sparse + gg_sparse) + BBT_sparse * qx;
    // osqp
    Eigen::VectorXd q_d = q_.toDense();
    Eigen::VectorXd l_d = l_.toDense();
    Eigen::VectorXd u_d = u_.toDense();
    qpSolver_.setMats(P_, q_d, A_, l_d, u_d);
    qpSolver_.solve();
    int ret = qpSolver_.getStatus();
    if (ret != 1) {
      ROS_ERROR("fail to solve QP!");
      return ret;
    }
    solve_flag = true;
    Eigen::VectorXd sol = qpSolver_.getPrimalSol();
    Eigen::MatrixXd solMat = Eigen::Map<const Eigen::MatrixXd>(sol.data(), m, N_);
    Eigen::VectorXd solState = BB * sol + AA * x0 + gg;
    Eigen::MatrixXd predictMat = Eigen::Map<const Eigen::MatrixXd>(solState.data(), n, N_);

    for (int i = 0; i < N_; ++i) {
      predictInput_[i] = solMat.col(i);
      predictState_[i] = predictMat.col(i);
    }
    return ret;
  }

延时模型

注意到上面的代码中有:

VectorX x0 = compensateDelay(x0_observe_);

这个函数就是要考虑延时的情况,当系统是无延时的时候状态就是它本身。 

延时模型的意思就是系统当前的控制量并不会马上作用于当前的系统,而是会经过一段时间 \tau 后才作用,也就是说系统的控制是有延时的,如下所示:

那么我们就可以把系统的初始状态  \textbf{x}_0 定义成当前时刻 \tau 之后的状态量,由于我们用的是MPC,可以预测当前时刻  \tau 之后的状态,那么我们就可以利用类似之前AA BB gg矩阵的形式来得到一个delay后的状态,然后我们就可以利用这个状态得到相应的延时控制量,如下所示:

其代码如下: 

  VectorX compensateDelay(const VectorX& x0) {
    VectorX x0_delay = x0;
    if (delay_ == 0)
    {
      return x0_delay;
    }
    Eigen::MatrixXd BB, AA, gg, x0_pred;
    int tau = std::ceil(delay_ / dt_);
    BB.setZero(n * tau, m * tau);
    AA.setZero(n * tau, n);
    gg.setZero(n * tau, 1);
    x0_pred.setZero(n * tau, 1);
    double s0 = s_.findS(x0.head(2));
    double phi, v, delta;
    double last_phi = x0(2);

    for (int i = 0; i < tau; ++i) {
      calLinPoint(s0, phi, v, delta);
      if (phi - last_phi > M_PI) {
        phi -= 2 * M_PI;
      } else if (phi - last_phi < -M_PI) {
        phi += 2 * M_PI;
      }
      last_phi = phi;
      linearization(phi, v, delta);
      if (i == 0) {
          BB.block(0, 0, n, m) = Bd_;
          AA.block(0, 0, n, n) = Ad_;
          gg.block(0, 0, n, 1) = gd_;
        } else {
          BB.block(i * n, i * m, n, m) = Bd_;
          for (int j = i - 1; j >= 0; --j){
            BB.block(i * n, j * m, n, m) = Ad_ * BB.block((i - 1) * n, j * m, n, m);
          }
          AA.block(i * n, 0, n, n) = Ad_ * AA.block((i - 1) * n, 0, n, n);
          gg.block(i * n, 0, n, 1) = Ad_ * gg.block((i - 1) * n, 0, n, 1) + gd_;
        }
      }
    Eigen::VectorXd uu(m * tau, 1);
    for (double t = delay_; t > 0; t -= dt_) {
      int i = std::ceil(t / dt_);
      uu.coeffRef((tau - i) * m + 0, 0) = historyInput_[i - 1][0];
      uu.coeffRef((tau - i) * m + 1, 0) = historyInput_[i - 1][1];
    }
    x0_pred = BB * uu + AA * x0 + gg;
    x0_delay = x0_pred.block((tau - 1) * n, 0, n, 1);
    return x0_delay;
  }

 效果图(注意看小车末尾的紫色线条表示延时):

至此,任务完成,小车可以跟踪给定的轨迹。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MPC(模型预测控制)控制小车沿轨迹移动——C++实现 的相关文章

  • mpc模型预测控制原理详解

    mpc模型预测控制原理详解 前言mpc算法步骤mpc算法推导 前言 本文是对mpc模型预测控制学习的记录 xff0c 主要参照了DR CAN老师的视频进行学习 视频专栏链接 xff1a DR CAN老师mpc视频专栏 在这篇博客中博主也针对
  • Apollo代码学习(七)—MPC与LQR比较 (百度Apollo中用到了PID、MPC和LQR三种控制器)

    摘自 xff1a https blog csdn net u013914471 article details 84324754 Apollo代码学习 七 MPC与LQR比较 follow轻尘 2018 11 29 17 32 56 179
  • 我已经多次看到说LQR和MPC相似

    https zhuanlan zhihu com p 139145957 https blog csdn net sinat 16643223 article details 109707776
  • 自动驾驶控制算法-模型预测MPC

    本文记录一下MPC控制算法的学习过程和自己的理解 xff0c 初步接触控制算法 xff0c 理解肯定不是很完善 xff0c 重在记录思考的过程 背景 随着自动驾驶技术以及机器人控制技术的不断发展及逐渐火热 xff0c 模型预测控制 MPC
  • PID/LQR/MPC自行总结使用

    PID LQR MPC自行总结使用 自学控制相关知识 xff0c 已经一年多了 xff0c 现在回头看看还是有很多模糊不明确的地方 xff0c 准备借此机会进行总结一下 xff0c 第一次写博客 xff0c 如果错误和不合理之处 xff0c
  • MPC控制笔记(一)

    转自 我的博客 笔记参考1 xff1a Understanding Model Predictive Control Youtube 带自动生成字幕 笔记参考2 xff1a Understanding Model Predictive Co
  • MPC控制笔记(一)

    转自 我的博客 笔记参考1 xff1a Understanding Model Predictive Control Youtube 带自动生成字幕 笔记参考2 xff1a Understanding Model Predictive Co
  • MPC控制

    基于状态空间模型的控制 模型预测控制 xff08 MPC xff09 简介 对基于状态空间模型的控制理解得很到位 在这里我重点讲解一下状态空间 模型 那么什么是状态 xff1f 输出是不是也是状态的一种 xff1f 对的 xff0c 输出也
  • LQR、LQR-MPC、GP-MPC控制倒立摆

    LQR控制倒立摆 xff1a 倒立摆状态方程 xff1a 目标任务 xff1a 模型参数 xff1a LQR for the cart pole system load 39 cp params mat 39 syms phi phid x
  • MPC(模型预测控制)控制小车沿轨迹移动——C++实现

    任务说明 要求如下图所示 xff0c 给定一条轨迹 xff0c 要求控制小车沿这条轨迹移动 xff0c 同时可以适用于系统带有延时的情况 注意 xff0c 本篇文章只给出部分C 43 43 代码参考 主要流程 首先用运动学自行车模型 xff
  • MPC与LQR的详细对比分析

    从以下几个方面进行阐述 xff1a 一 xff0c 研究对象 xff1a 是否线性 二 xff0c 状态方程 xff1a 离散化 三 xff0c 目标函数 xff1a 误差和控制量的极小值 四 xff0c 工作时域 xff1a 预测时域 x
  • MPC模型预测控制

    这篇主要讲一下模型预测控制 xff0c 如果对PID控制了解的同学 xff0c 那效果更好 如果不了解PID控制 xff0c 还是熟悉下比较好 模型预测控制 xff0c 顾名思义 xff0c 基于模型 xff0c 预测未来 xff0c 进行
  • MPC自学资料总结

    1 书籍 xff1a 无人驾驶车辆模型预测控制 2 视频 xff1a https ww2 mathworks cn videos understanding model predictive control part 1 why use m
  • Apollo代码学习(七)—MPC与LQR比较

    Apollo代码学习 MPC与LQR比较 前言研究对象状态方程工作时域目标函数求解方法 前言 Apollo中用到了PID MPC和LQR三种控制器 xff0c 其中 xff0c MPC和LQR控制器在状态方程的形式 状态变量的形式 目标函数
  • 基于模型预测控制(MPC)的悬架系统仿真分析

    目录 前言 1 悬架系统 2 基于MPC的悬架系统仿真分析 2 1 simulink模型 2 2仿真结果
  • 小巧玲珑:机器学习届快刀XGBoost的介绍和使用

    欢迎大家前往腾讯云技术社区 获取更多腾讯海量技术实践干货哦 作者 张萌 序言 XGBoost效率很高 在Kaggle等诸多比赛中使用广泛 并且取得了不少好成绩 为了让公司的算法工程师 可以更加方便的使用XGBoost 我们将XGBoost更
  • Apollo代码学习(六)—模型预测控制(MPC)

    Apollo代码学习 模型预测控制 前言 模型预测控制 预测模型 线性化 单车模型 滚动优化 反馈矫正 总结 前言 非专业选手 此篇博文内容基于书本和网络资源整理 可能理解的较为狭隘 起点较低 就事论事 如发现有纰漏 请指正 非常感谢 查看
  • 控制范围和预测范围

    我已经回顾了模型预测控制的参考书目和 Gekko 编程结构 尽管我了解它的编程方式及其目的 例如 我想了解 Gekko 如何根据 Seborg 中的相关内容来管理控制范围和预测范围之间的差异 我看不出代码有什么区别 下面是一个用于说明的 M
  • 在 GEKKO 中使用非线性模型预测控制实现横向控制器

    我正在尝试为由横向动态模型定义的自动驾驶车辆实现横向控制器 好吧 我的问题是 CV 没有达到 SP 设置的所需参考点或目标点 我正在使用以下运动方程和目标函数 我正在使用半经验公式 pacejka 来计算 Fyf Fyr 提供的轮胎力 这里
  • Linux配置Acado

    如果需要使用acado的matlab接口 请移步 Linux Matlab配置Acado 首先 安装必要的软件包 sudo apt get install gcc g cmake git gnuplot doxygen graphviz 在

随机推荐

  • Oracle VirtualBox虚拟机安装

    1 到官网下载虚拟机安装包 xff08 https www virtualbox org wiki Downloads xff09 2 下载后的样子 3 选择安装路径 4 选择要安装的功能 5 安装 6 安装完成
  • VirtualBox虚拟机安装Red Hat Enterprise Linux7.2

    1 首先安装好VirtualBox 2 下载好rhel server 7 2 xff0c 下载好长这样 3 点击新建 xff0c 在弹出窗口中输入名称 xff0c 选择类型和版本 xff0c 之后点击下一步 4 选择内存大小 xff0c 根
  • HTML 页面中的 target 用法

    值含义 blank在新窗口中打开链接 parent在父窗体中打开链接 self在当前窗体打开链接 此为默认值 top在当前窗体打开链接 xff0c 并替换当前的整个窗体 框架页 一个对应的框架页的名称在对应框架页中打开
  • VirtualBox挂载RedHat光盘

    1 使用root用户登录RedHat系统 xff0c 点击设备 gt 安装增强功能 2 安装增强功能后桌面会出现一个光盘标志 xff0c 弹出框点取消 3 为防止后续步骤出错 xff0c 此处重新分配光盘 点击设备 gt 分配光驱 xff0
  • RedHat系统使用yum安装软件

    使用yum命令安装软件 xff0c 此处以system config users为例 1 配置yum源配置文件 xff08 存放在 etc yum repos d文件夹下 xff09 xff1b 切换到 etc yum repos d文件夹
  • 初识HTML

    什么是HTML xff1f HTML 指的是超文本标记语言 HyperText Markup LanguageHTML 不是一种编程语言 xff0c 而是一种标记语言标记语言是一套标记标签 markup tag HTML 使用标记标签来描述
  • Window 安装MySQL8

    1 下载安装包 官网下载MySQL安装包 xff0c 下载地址 https dev mysql com downloads mysql 2 解压缩 将下载好的压缩包解压至你的安装目录 xff0c 我的路径为E tools MySQL ins
  • Windows 安装Navicat 连接MySQL

    1 下载Navicat Premium 进入官网https www navicat com cn download navicat premium下载Navicat Premium 2 安装 选择安装路径 然后一直点击下一步 xff0c 直
  • win10 安装Python3.8和pip

    下载安装包 1 进入Python官网https www python org xff0c 选择Windows 2 往下滑 xff0c 找到3 8 10 xff0c 选择Download Windows installer 64 bit xf
  • jeston TX1/TX2 系统迁移至SD卡的正确步骤

    如果是刚刚开始Nvidia jeston TX1 TX2 开发的初学者 xff0c 希望本文可以帮助节省时间 首先上张图 xff0c 完成配置后的 jeston TX1 载板使用的是作者自己设计的EdgeBox EHub tx1 tx2 E
  • win 10安装IPython

    什么是IPython Ipython是一种交互式解释器 Ipython的性能优于标准Python的shell IPython支持变量自动补全 xff0c 自动缩进 xff0c 支持 bash shell 命令 xff0c 内置了许多很有用的
  • Java连接MySQL数据库

    Java连接MySQL数据库 数据库帮助类DBHelper java 使用的JDBC驱动是 mysql connector java 8 0 25 jar span class token keyword import span java
  • ubuntu安装cmake

    参考 xff1a ubuntu安装cmake 陈 洪 伟的博客 CSDN博客 ubuntu安装cmake 注意 xff1a https cmake org download 下载cmake时 xff0c 要下载Source distribu
  • ADRC最速综合函数fhan实现

    ADRC最优综合函数fhan函数测试 fhan函数是ADRC的跟踪微分控制器的核心函数 xff0c 使得状态变量可以快速跟踪上系统输入 本例中 xff0c 设理想输入v 61 sin t 用状态变量x1跟踪输入 xff0c x2跟踪输入的导
  • 【日志】gazebo无法加载模型 & 黑屏 & ResourceNotFound &[gazebo-1] process has died [pid 11734, exit code 255]

    问题1 ResourceNotFound xacro 解决方法 sudo apt get install ros kinetic xacro 问题2 ERROR cannot launch node of type gazebo ros g
  • Robotics: Aerial Robotics(空中机器人)笔记(二):如何设计一架四旋翼无人机

    在这一章里 xff0c 我们将探索四旋翼如何飞行的 这章将会讲一些基本的力学原理以及如何设计无人机 上一章链接 xff1a Robotics Aerial Robotics xff08 空中机器人 xff09 笔记 xff08 一 xff0
  • Robotics: Aerial Robotics(空中机器人)笔记(三):无人机运动学建模

    在这一章里 xff0c 我们将探索四旋翼无人机的运动学原理 这章将会讲机器人学中的坐标转换 xff08 Transformation xff09 旋转 xff08 Rotation xff09 欧拉角 xff08 Euler Angles
  • Robotics: Aerial Robotics(空中机器人)笔记(四):无人机动力学建模

    在这一章里 xff0c 我们将探索四旋翼无人机动力学的相关知识 我将主要讲刚体动力学中的牛顿 欧拉方程以及在四旋翼无人机上的形式 上一章链接 xff1a Robotics Aerial Robotics xff08 空中机器人 xff09
  • Robotics: Aerial Robotics(空中机器人)笔记(六):无人机运动规划

    在之前的学习中我们已经讨论了如何根据给定轨迹对四旋翼进行控制 xff0c 在这一章里 xff0c 我们将探索四旋翼无人机在三维空间中的运动规划 xff0c 即给定一个三维的环境 xff0c 我们希望能够在这个三维环境中指定具体的点 xff0
  • MPC(模型预测控制)控制小车沿轨迹移动——C++实现

    任务说明 要求如下图所示 xff0c 给定一条轨迹 xff0c 要求控制小车沿这条轨迹移动 xff0c 同时可以适用于系统带有延时的情况 注意 xff0c 本篇文章只给出部分C 43 43 代码参考 主要流程 首先用运动学自行车模型 xff