百度Apollo 2.0 车辆控制算法之LQR控制算法解读

2023-05-16

百度Apollo 2.0 车辆控制算法之LQR控制算法解读

Apollo 中横向控制的LQR控制算法在Latcontroller..cc 中实现

根据车辆的二自由度动力学模型

(1)

根据魔术公式在小角度偏角的情况下有,轮胎的侧向力与轮胎的偏离角成正比. ,分别为前、后轮的侧偏刚度,

(2)

(3)在小角度的情况下有

所以有

(4)

因此上述车辆的动力学模型可以简化写成

(5)

 (6)期望横摆角角速度

(7) 横摆角角度偏差

 (7)横向偏差变化率求导数

 (8)横向偏差变化率

 

车辆模型的连续状态空间方程

(9)

状态变量X的选择分别为横向偏差、横向偏差变化率,横摆角角度偏差,横摆角角度偏差变化率。控制量u为前轮偏角。

选择合适的状态变量后得到A,B,B1,B2矩阵分别如下

   

由于只对横摆角角度偏差变化率的导数产生影响,在横向控制中主要是控制横向偏差、横向偏差变化率,横摆角角度偏差,横摆角角度偏差变化率,因而忽略了公式中项。车辆系统的状态空间方程表示为

 (10)

Init()函数中将A,B, 与Vx无关的系数先行计算,与Vx相关的系数参数计算根据Vx不断更新。

上述连续的状态空间方程用于计算机控制需要对连续的状态空间方程进行离散化,其中At采用双线性变换得到

, At来源见右边公式

, ,T为控制周期,本程序中为0.01s。

上述参数计算和离散化的过程在UpdateMatrix()函数和UpdateMatrixCompound()函数中

的离散化过程在Init()函数中实现

  matrix_b_ = Matrix::Zero(basic_state_size_, 1);

  matrix_bd_ = Matrix::Zero(basic_state_size_, 1);

  matrix_bdc_ = Matrix::Zero(matrix_size, 1);

  matrix_b_(1, 0) = cf_ / mass_;

  matrix_b_(3, 0) = lf_ * cf_ / iz_;

  matrix_bd_ = matrix_b_ * ts_;

的离散化过程在UpdateMatrix()函数中实现

void LatController::UpdateMatrix() {

  const double v =

      std::max(VehicleStateProvider::instance()->linear_velocity(), 0.2);

  matrix_a_(1, 1) = matrix_a_coeff_(1, 1) / v;

  matrix_a_(1, 3) = matrix_a_coeff_(1, 3) / v;

  matrix_a_(3, 1) = matrix_a_coeff_(3, 1) / v;

  matrix_a_(3, 3) = matrix_a_coeff_(3, 3) / v;

  Matrix matrix_i = Matrix::Identity(matrix_a_.cols(), matrix_a_.cols());

  matrix_ad_ = (matrix_i + ts_ * 0.5 * matrix_a_) *

               (matrix_i - ts_ * 0.5 * matrix_a_).inverse(); //双线性变换离散化A

}

通过上述介绍我们得到了车辆离散状态空间方程(11)中的At,Bt,则系统的最优前轮转角 (12)

定义如下目标函数

 (13)

其中Q为状态权重系数,R为控制量权重系数

当上述目标函数最小时就得到最优的状态反馈矩阵K

上述公式的,(14)

同时矩阵P满足黎卡提方程:

(15)

求解状态反馈矩阵K的在

    common::math::SolveLQRProblem(matrix_adc_, matrix_bdc_, matrix_q_,

                                  matrix_r_, lqr_eps_, lqr_max_iteration_,

                                  &matrix_k_); 函数中实现

函数输入为At,Bt,Q,R,最大迭代次数lqr_max_iteration_,最小精度lqr_eps_,函数输出为状态反馈矩阵matrix_k_。

当前最新的状态量是通过UpdateStateAnalyticalMatching()函数获得,由此我们可以通过 (12)

计算出当前的最优反馈控制量即最优前轮偏角。然而这还没玩完。

将公式(12)的控制量带入公式(10)得到系统状态反馈后的状态空间方程如下

  (13)

车辆沿固定曲率的轨迹运行时不为零。因此通过LQR调节的特征值使系统趋于稳定,但是系统的稳态偏差并不为0。

     为此在原有最优控制量的基础上增加一个前馈环节,使系统趋于稳定的同时系统的横向稳态偏差为0。

    (14)

公式中为前馈环节提供的前轮转角。

将公式(14)带入公式(10)得到

 (15)

设初始条件为0,对公式(15)进行拉普拉斯变换得到

  (16)

假设汽车以固定纵向速度Vx沿某一固定曲率的弯道行驶,则通过纵向车速Vx和道路的半径R可以计算出期望汽车横摆角速度:

   (6)

公式(6)可知横摆角速度的拉普拉斯变换结果为

 (17)

假设为固定值,则其拉普拉斯变换结果为

(18)

根据终值定理,系统的稳态误差为

 (19)

将A,B,B1,K带入公式(19)得到

 (20)

观察公式(20)中的第一项和第三项。可知道对横摆角角度偏差无影响,选择合适的可将横向偏差稳态值趋向与0。

 (21)

要想横向偏差的稳态值趋于零,则

 (22)

因此

   (23)

,不足转向梯度系数  (24)

公式(23)可以简化为

  (25)

Apollo程序中计算控制量的函数为ComputeControlCommand()函数

 

前馈环节计算的前轮转角对应如下程序

double LatController::ComputeFeedForward(double ref_curvature) const {

  const double kv =

      lr_ * mass_ / 2 / cf_ / wheelbase_ - lf_ * mass_ / 2 / cr_ / wheelbase_; //对应公式(24)

 

  // then change it from rad to %

  const double v = VehicleStateProvider::instance()->linear_velocity();

  const double steer_angle_feedforwardterm =

      (wheelbase_ * ref_curvature + kv * v * v * ref_curvature -

       matrix_k_(0, 2) *

           (lr_ * ref_curvature -

            lf_ * mass_ * v * v * ref_curvature / 2 / cr_ / wheelbase_)) *

      180 / M_PI * steer_transmission_ratio_ /

      steer_single_direction_max_degree_ * 100; //对应公式(25),并将角度由弧度转变为角度,最后转变为百分比

  return steer_angle_feedforwardterm;

}

 

最终的前轮转角的控制量为最优状态反馈控制量与前馈控制前轮转角之和。对应程序如下

  const double steer_angle_feedback = -(matrix_k_ * matrix_state_)(0, 0) * 180 /

                                      M_PI * steer_transmission_ratio_ /

                                      steer_single_direction_max_degree_ * 100;

 //计算状态反馈对应的控制量,将弧度转变为角度,最后转变为百分比。

// steer_transmission_ratio_表示方向盘转动角度与车轮转动角度的比值,在车辆信息中定义该参数,

// steer_single_direction_max_degree表示最大的方向盘转动的角度,单位为度

  const double steer_angle_feedforward = ComputeFeedForward(debug->curvature());

//计算前馈控制对应的控制量

 

  // Clamp the steer angle to -100.0 to 100.0

  double steer_angle = common::math::Clamp(

      steer_angle_feedback + steer_angle_feedforward, -100.0, 100.0); //将状态反馈的控制量与前馈控制控制量进行叠加,并进行限幅处理。

计算的出前轮转角经过上下限的限幅后进行输出

  if (FLAGS_set_steer_limit) {

    const double steer_limit =

        std::atan(max_lat_acc_ * wheelbase_ /

                  (VehicleStateProvider::instance()->linear_velocity() *

                   VehicleStateProvider::instance()->linear_velocity())) *

        steer_transmission_ratio_ * 180 / M_PI /

        steer_single_direction_max_degree_ * 100; //计算前轮转角的上下限限幅值。

 

    // Clamp the steer angle

    double steer_angle_limited =

        common::math::Clamp(steer_angle, -steer_limit, steer_limit); //对前轮转角进行上下限的限幅处理

    steer_angle_limited = digital_filter_.Filter(steer_angle_limited); //对前轮转角进行低通滤波处理

    cmd->set_steering_target(steer_angle_limited);

    debug->set_steer_angle_limited(steer_angle_limited);

  } else {

    steer_angle = digital_filter_.Filter(steer_angle);//对前轮转角进行低通滤波处理

    cmd->set_steering_target(steer_angle);

  }

 

 

部分成员函数介绍

1、LoadControlConf 成员函数用于获取控制参数包括车身参数、LQR控制的精度、最大迭代次数等。

其中车辆的参数来自modules\common\data\ mkz_config.pb.txt文件

LQR的控制参数来自modules\control\conf\ lincoln.pb.txt文件

2、InitializeFilters成员函数用于设置巴斯沃特低通低通滤波参数, 以及对 lateral_error、heading_error进行均值滤波。滤波器的参数来自modules\control\conf\ lincoln.pb.txt文件

 

3、Init成员函数用于初始化 状态空间方程的A,B,K, Q,R 以及控制系统的相关参数。

LoadLatGainScheduler函数的作用?

LoadLatGainScheduler函数用于获取 lateral_error、heading_error 增益的策略。

 

4、ComputeControlCommand 函数最重要,计算控制量

 

通过LQR求解黎卡提方程得到控制量

SolveLQRProblem(matrix_adc_, matrix_bdc_, matrix_q_updated_,

                                  matrix_r_, lqr_eps_, lqr_max_iteration_,

                                  &matrix_k_);

//在高速运行时,控制量权重矩阵matrix_q_的系数根据速度变化进行调整

  // Add gain sheduler for higher speed steering

  if (FLAGS_enable_gain_scheduler) {

    matrix_q_updated_(0, 0) =

        matrix_q_(0, 0) *

        lat_err_interpolation_->Interpolate(

            VehicleStateProvider::instance()->linear_velocity());

    matrix_q_updated_(2, 2) =

        matrix_q_(2, 2) *

        heading_err_interpolation_->Interpolate(

            VehicleStateProvider::instance()->linear_velocity());

    common::math::SolveLQRProblem(matrix_adc_, matrix_bdc_, matrix_q_updated_,

                                  matrix_r_, lqr_eps_, lqr_max_iteration_,

                                  &matrix_k_);

  } else {

    common::math::SolveLQRProblem(matrix_adc_, matrix_bdc_, matrix_q_,

                                  matrix_r_, lqr_eps_, lqr_max_iteration_,

                                  &matrix_k_);

  }

 

5、UpdateMatrix()函数

用于更新matrix_a_(离散之前的A矩阵) 和matrix_ad_(离散之后的A矩阵)

matrix_a_ 由中系数分为两类,一类与速度无关,另外一类与速度相关放在matrix_a_coeff_

从何得到线性时变状态空间方程。

matrix_adc_ 由matrix_ad_ 和 过去的变量对应的矩阵组合而成

 matrix_bdc_. 由matrix_bd_ 和过去变量对应的矩组合而成。

 

6、GetLateralError()函数

获取横向偏差,具体计算过程为根据车辆当前的位置查找参考轨迹最近点,形成直线L。

计算出车辆位置与最近点的距离std::sqrt(dx * dx + dy * dy),同时计算出该条线与x轴正方向之间的角度point_angle,将该角度减去参考轨迹的方向角得到直线L与参考轨迹速度方向之间的夹角point2path_angle。

横向偏差为std::sin(point2path_angle) * std::sqrt(dx * dx + dy * dy);

7、UpdateStateAnalyticalMatching()函数获取状态偏差,ComputeLateralErrors()函数主要通过根据当前车辆的位置计算出在参考轨迹上上离车辆当前位置最近点作为参考点,通过参考点与实际车辆位置就可以获得各种状态偏差(横向偏差、横向偏差变化率、航向角偏差、航向角偏差变化率)。

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

百度Apollo 2.0 车辆控制算法之LQR控制算法解读 的相关文章

随机推荐

  • 软件工程3.0

  • pod、container、sidecar

    pod是一个小家庭 xff0c 它把密不可分的家庭成员 container 聚在一起 xff0c Infra container则是家长 xff0c 掌管家中共通资源 xff0c 解决顺序和依赖关系 xff0c 家庭成员通过sidecar方
  • 4种SQL标准的事务隔离级别

    SQL标准的事务隔离级别包括 xff1a 读未提交 xff08 read uncommitted xff09 xff1a 一个事务还没提交时 xff0c 它做的变更就能被别的事务看到 读提交 xff08 read committed xff
  • 设计容器网络插件的初步思路

    同一个 Pod 里面的所有用户容器的进出流量 xff0c 可以认为都是通过 Infra 容器完成的 当为Kubernetes 开发一个网络插件时 xff0c 应该重点考虑的是如何配置这个 Pod 的 Network Namespace xf
  • 各种显示接口DBI、DPI、LTDC、DSI、FSMC

    各种显示接口DBI DPI LTDC DSI FSMC qq 23899395 2019 06 05 17 30 36 4810 收藏 36 版权 首先 xff0c MIPI xff08 Mobile Industry Processor
  • 在ubuntu 16.04安装ROS Kinetic

    ubuntu16 04 已经发布一个月了 xff0c ROS的Kinetic也已经发布 xff0c 需要了解ROS发行版及支持维护的时间等 xff0c 可以参考如下网页 xff1a http wiki ros org Distributio
  • ROS创建工作空间和功能包

    所有的ROS程序 xff0c 包括我们自己开发的程序 xff0c 都被组织成功能包 xff0c 而ROS的功能包被存放在称之为工作空间的目录下 因此 xff0c 在我们写程序之前 xff0c 第一步是创建一个工作空间以容纳我们的功能包 1
  • MPU-6000(6050)介绍

    MPU 6000 xff08 6050 xff09 简介 MPU 60X0是全球首例9 轴运动处理传感器 它集成了3 轴MEMS陀螺仪 xff0c 3 轴MEMS加速度计 xff0c 以及一个可扩展的数字运动处理器DMP xff08 Dig
  • lwip/uip移植之一

    最近一直想移植一个tcp ip协议栈到板子上 xff0c 于是想到了lwip和uip lwip是一个比较完整的协议栈 xff0c 功能强大 xff0c 结合ucos系统更是方便完美 xff0c 但是需要几十k的ram xff0c 这点在我f
  • Nvidia Xavier GPIO 输入输出 中断 PWM

    文章目录 前言Jetson GPIO安装可用引脚点亮LEDGPIO输出示例GPIO输入示例GPIO EventGPIO InterruptPWM微信公众号 前言 Nvidia Jetson AGX Xavier 硬件相关 这篇讲到Xavie
  • Jetson Xavier/XavierNX/TX2 CANFD 配置使用

    目录 TX2 Xavier NX Xavier CAN特性TX2 Xavier NX Xavier 载板引出位置CAN收发器NVIDIA CAN DriverXavier CAN 引脚配置Jetson CAN 设置设置开机运行查看连接状态C
  • Altium Designer使用Git构想

    今天看了dtysky的 体三维显示器 PCB部分 LED阵列 用脚本写的上万个LED的自动布局和自动布线 很震惊 很欣赏 很喜欢 或许有很多我们可以想象的空间 这篇主要写Git Git主要管理文本文件 二进制文件却不大合适 尽管有 使用 G
  • 如何拿到阿里offer的?面试流程及面试题

    一个偶然的开始 交待一下 非广告 xff0c 第一次用拉勾 xff0c 感觉做的挺好 xff0c 以前一直用51job 从7月分开始 xff0c 打算找工作 xff0c 一个偶然的机会 xff0c 拉勾上一个蚂蚁金服的同学找到我 xff0c
  • STM32和Linux(转载)

    Linux和stm32 一个是软件平台一个是硬件平台 xff0c 完全不一样的 xff08 记住 xff0c 是平台 xff01 xff09 这样说吧 xff0c 既然你喜欢单片机 xff0c 就先学stm32 xff0c 把硬件基础打牢
  • PX4飞控问题之参数重置问题

    PX4在上电的时候会出现参数重置的问题 xff0c 出现这个问题的机率很小 xff0c 可能上电几千甚至上万次才会出现一次重置的情况 xff0c 但一旦出现了参数重置 xff0c 飞机就无法飞行 xff0c 得重新校准传感器 要解决这个问题
  • STM32硬件基础--LTDC显示图像

    STM32硬件基础 LTDC显示图像 海东青电子 2019 11 13 23 40 05字数 2 635阅读 3 102 海东青电子原创文章 xff0c 转载请注明出处 xff1a https www jianshu com p 21638
  • PX4轨迹生成公式推导

    PX4轨迹生成公式推导下载链接 对于多旋翼 飞行任务的时候 通过地面站画出航点 上传给飞控 飞控通过轨迹生成算法生成平滑的目标位置 速度及加速度 给位置控制模块控制飞机的位置 速度及加速度 PX4轨迹生成的方法为 约束加加速度的S型速度曲线
  • 植保无人机航线规划

    最近折腾了植保无人机航线规划的算法 支持任意多边形 不包括自相交多边形 的边界及障碍区域 其中涉及到了多边形内缩外扩 多边形的分解 多边形交集 并集 差集 深度优先搜索 最短路径算法 耗时两个多月 用C 实现整套算法 生成的库在missio
  • 现代控制工程笔记(一)控制系统的状态空间描述

    文章目录 1 基本概念2 系统的状态空间描述状态空间描述框图状态变量选取的非唯一性 3 由系统微分方程列写状态空间表达式一 微分方程中不包含输入函数的导数项相变量法其他方法 xff1a 二 微分方程中包含输入函数的导数项 4 由传递函数列写
  • 百度Apollo 2.0 车辆控制算法之LQR控制算法解读

    百度Apollo 2 0 车辆控制算法之LQR控制算法解读 Apollo 中横向控制的LQR控制算法在Latcontroller cc 中实现 根据车辆的二自由度动力学模型 1 根据魔术公式在小角度偏角的情况下有 轮胎的侧向力与轮胎的偏离角