锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

【Carsim Simulink自动驾驶仿真】基于MPC的轨迹跟踪控制

时间:2022-09-10 17:00:00 ke全铜连接器

如果对Carsim不了解基本用途,可参考:【Carsim Simulink基于自动驾驶模拟MPC的速度控制
如果对MPC算法原理不清楚,可以参考:如何理解MPC模型预测控制理论
项目介绍:
教程是北京理工大学无人驾驶车辆模型预测控制的第二版。使用的模拟软件是Carsim2020.0和MatlabR2021a。使用MPC控制思想跟踪和控制车辆轨迹,并给出模拟结果。

整整两天,踩了无数坑,所以篇幅比较大。如有其他问题,请一起讨论。

从网上下载的代码无法运行,因此本文的代码被修改和调试。

基于MPC轨迹跟踪控制

  • 效果图
    • 直线跟踪
      • 3m/s
      • 5m/s
      • 10m/s
    • 圆跟踪
      • 3m/s
      • 5m/s
      • 10m/s
  • MATLAB框架搭建
  • 数学遗漏问题及代码修改
    • 运动模型很少L
    • 目标函数线性项少系数改写后
  • 讨论代码中的其他问题
    • 输入维度不匹配
    • 超出数组范围的索引
      • 1.变量范围
      • 2.换个求解器
      • 3.所有初始值均为0
      • 4.对于kesi(4)和kesi(5)的赋值 (这是我的问题)
        • 一些理解
  • 参数的选取
  • 速度问题
  • 附录:全代码(修改后)

效果图

因为参数已经调整好了,效果和书不一样。

直线跟踪

在这里插入图片描述
图像为:路径,速度,误差和前轮偏角

前轮偏角局部放大图为:

3m/s

5m/s

10m/s


速度的具体图像如下:

圆跟踪


图为:路径、速度和前轮偏差(误差不知道Carsim中怎么画,知道的大佬请私信,呜呜呜):

放大轨迹后:

前轮偏角为:

放大前轮偏角后:

3m/s


速度为:

5m/s


速度为:

10m/s


速度为:

MATLAB框架搭建

书中给出的MATLAB框架如下:

因为对于这种方法输出需要再另外处理。所以我这里直接将速度乘3.6,角度也在程序中直接处理了。对应的框架图为:

代码的数学遗漏问题与修改

书中的代码和下载下来的代码不一样,所以还是检查一下这两个地方,

运动学模型少L

在书中,推导运动学模型的时候,最后一个数字分母是有一个l的:

但是在代码中,这个地方少了,需要加上。

改写之后的目标函数线性项少系数


这里的2在书中没有少,但是下载下来的代码中没有这个系数。如果没有的可以加一下。

代码中的其他问题及讨论

输入维度不匹配的情况

看一下S-Function的输入是3个还是5个,输出是2个还是直接给出5个,对应的代码中也应该和其一样。具体在S-Function中是初始化的第一个函数中的:

    sizes.NumOutputs      =5;%[speed,steering]
    sizes.NumInputs       =3;

索引超出数组范围

这个是我的主要问题,之所以报错,是因为求解器求解不出来优化问题,方法的话我找了一些,然后自己也试了一些:

1.变量的范围

这里有两种情况:

  • 第一种情况是检查变量范围delta_umin=[-0.05;-0.0082;];如果当中的-0.05是0.05,将其加一个负号。
  • 第二种情况其实扩大变量的范围可以求解,但是这里不建议,如果你在扩大范围之后可以求解,那么建议还是将其变回原来的数,更改其他值。

2.换一个求解器

使用interior-point-convex,而不是active-set

%options = optimset('Algorithm','active-set');
options = optimset('Algorithm','interior-point-convex');

3.初始值全部设为0

检查初始化函数mdlInitializeSizes中的x0U是否都为零。注意,这里的U表示的就是控制量与参考控制的差值。

function [sys,x0,str,ts] = mdlInitializeSizes
%找到以下两个值
x0 = [0;0;0];
U=[0;0];

4.对于kesi(4)和kesi(5)的赋值 (这个是我的问题)

这个我认为争议比较大,但是改了之后确实没有报错了。
先说一下,按照理论:

kesi(4)和kesi(5)就是这里的控制变量 u ~ \tilde{u} u~。而这个 u ~ \tilde{u} u~根据定义是:

当前速度与参考速度的插值,所以这里我们应该将Carsim中的5个变量全部输入到S-Funciton中,然后进行如下操作:

    U(1) = u(4)/3.6 - vd1;
    steer_SW = u(5)*pi/180;
    steering_angle = steer_SW/18;
    U(2) = steering_angle - vd2;
    kesi(4)=U(1); % vel-vel_ref
    kesi(5)=U(2); % steer_angle - steering_ref

之前我从来没有怀疑过这里,直到我看到书中的代码和网上下载的不一样的时候,我就尝试了一下书上的代码,即将前四行全部注释掉:

%    U(1) = u(4)/3.6 - vd1;
%    steer_SW = u(5)*pi/180;
%    steering_angle = steer_SW/18;
%    U(2) = steering_angle - vd2;
    kesi(4)=U(1); % vel-vel_ref
    kesi(5)=U(2); % steer_angle - steering_ref

这样改之后我的代码就不会出现问题了。

一些理解

首先我们要清楚,kesi(4,5)控制减去参考控制,求解器解出来的X前后两次的控制差值
我们先看能跑对的程序,大致过程可以简化成设置值,求解,给出输出三步:

U = [0,0]
for 循环:
#第一步:设置kesi
    kesi(4)=U(1); % vel-vel_ref
    kesi(5)=U(2); % steer_angle - steering_ref
#第二步:求解
	[X,~,~]=quadprog(H,f,A_cons,b_cons,[],[],lb,ub,[],options);
#第三步:给出输出
	u_dot(1)=X(1);
    u_dot(2)=X(2);
    U(1)=kesi(4)+u_dot(1);%用于存储上一个时刻的控制量
    U(2)=kesi(5)+u_dot(2);
    u_real(1) = U(1) + vd1;
    u_real(2) = U(2) + vd2;

这里列一个表格:

时间 求解之前的U,也就是上一步的U kesi u_dot 求解之后的U 输出
k-1 u k − 1 − u k − 1 r e f u_{k-1}-u_{k-1}^{ref} uk1uk1ref u k − 1 − u k − 1 r e f u_{k-1}-u_{k-1}^{ref} uk1uk1ref u k − u k r e f − u k − 1 + u k − 1 r e f u_k-u_{k}^{ref}-u_{k-1}+u_{k-1}^{ref} ukukrefuk1+uk1ref u k − 1 − u k − 1 r e f + u k − u k r e f − u k − 1 + u k − 1 r e f = u k − u k r e f u_{k-1}-u_{k-1}^{ref}+u_k-u_{k}^{ref}-u_{k-1}+u_{k-1}^{ref}=u_k-u_{k}^{ref} uk1uk1ref+ukukrefuk1+uk1ref=ukukref u_k
之后就可以征程循环。注意这里的初始值设置为[0,0]是合理的。

我出错的程序:

U = [0,0]
for 循环:
#第一步:设置kesi
    U(1) = u(4)/3.6 - vd1;
    steer_SW = u(5)*pi/180;
    steering_angle = steer_SW/18;
    U(2) = steering_angle - vd2;
    kesi(4)=U(1); % vel-vel_ref
    kesi(5)=U(2); % steer_angle - steering_ref
#第二步:求解
	[X,~,~]=quadprog(H,f,A_cons,b_cons,[],[],lb,ub,[],options);
#第三步:给出输出
	u_dot(1)=X(1);
    u_dot(2)=X(2);
    U(1)=kesi(4)+u_dot(1);%用于存储上一个时刻的控制量
    U(2)=kesi(5)+u_dot(2);
    u_real(1) = U(1) + vd1;
    u_real(2) = U(2) + vd2;

建立同样的表格,这里唯一不一样的是,之前的输入其实是记忆到了程序里面,这里的输入变成了从程序中获取:

时间 求解之前的U,也就是上一步的U kesi u_dot 求解之后的U 输出
k-1 u k − 1 i n p u t − u k − 1 r e f u_{k-1}^{input}-u_{k-1}^{ref} uk1inputuk1ref u k − 1 i n p u t − u k − 1 r e f u_{k-1}^{input}-u_{k-1}^{ref} uk1inputuk1ref u k − u k r e f − u k − 1 i n p u t + u k − 1 r e f u_k-u_{k}^{ref}-u_{k-1}^{input}+u_{k-1}^{ref} ukukrefuk1input+uk1ref u k − u k r e f u_k-u_{k}^{ref} ukukref u_k
k u k i n p u t − u k r e f u_{k}^{input}-u_{k}^{ref} ukinputukref
但是按照道理来说,这个和上一个表格是一样的,这里不一样的是速度输入之后需要进行变换,输出的时候也要进行变换,这变换之后会存在的误差比较大。还有一种可能,这里其实输入进来的是速度和方向盘转角,这个方向盘转角和轮胎转角之间有一个系数,这个系数这里设置的18,但是具体设置多少,也没有具体的深究。
总之我个人感觉可能是上一时刻的输出 u k u_k uk和这一时刻的输入 u k i n p u t u_k^{input} ukinp
锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章