代码详解——NMPC之加入控制平顺性惩罚项
时间:2022-07-24
本文章向大家介绍代码详解——NMPC之加入控制平顺性惩罚项,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
应读者wonder留言,更新一篇NMPC路径跟踪控制加入控制平顺性惩罚项,即控制输入增量惩罚项的代码及仿真结果。
NMPC_main.m更新为:
NMPC参考路径设置 作者北京科技大学白国星 david.gx.bai@gmail.com
致谢:原始框架来自北京理工大学龚建伟教授团队著作《无人驾驶车辆模型预测控制》
clear all;
%%车辆参数初始化
l=1;%轴距
global v1;
global deltaf1;
v1=1;
deltaf1=0;
%% 控制参数初始化
Nx=3;%状态量个数
Np=25;%预测时域
Nc=3;%控制时域
%% 车辆位置初始化
State_Initial(1,1)=0;%x
State_Initial(2,1)=0;%y
State_Initial(3,1)=pi/6;%phi
%% 参考轨迹参数初始化
N=1000;%参考轨迹点数量
T=0.05;%采样周期
global Xrefg;
global Yrefg;
global PHIrefg;
%%参考轨迹生成
for k=1:1:N+Np
if k<200
Xrefg(k,1)=k*T; %横坐标
Yrefg(k,1)=2; %纵坐标
PHIrefg(k,1)=0; %航向角
elseif k<514
Xrefg(k,1)=10+10*sin( 0.1*(k-200)*T);
Yrefg(k,1)=12-10*cos(0.1*(k-200)*T);
PHIrefg(k,1)=0.1*(k-200)*T;
elseif k<714
Xrefg(k,1)=20;
Yrefg(k,1)=12+(k-514)*T;
PHIrefg(k,1)=1.57;
else
Xrefg(k,1)=20;
Yrefg(k,1)=22;
PHIrefg(k,1)=1.57;
end
end
%% 开始仿真
for j=1:1:N-300
%读取参考路径
Xref=zeros(Np,1);
Yref=zeros(Np,1);
PHIref=zeros(Np,1);
for Nref=1:1:Np
Xref(Nref,1)=Xrefg(j+Nref-1,1);
Yref(Nref,1)=Yrefg(j+Nref-1,1);
PHIref(Nref,1)=PHIrefg(j+Nref-1,1);
end
%%约束条件
for i=1:1:Nc
lb(2*i-1)=0.8;
lb(2*i)=-0.44;
ub(2*i-1)=1.2;
ub(2*i)=0.44;
end
%%选取求解算法
options = optimset('Algorithm','active-set'); %选择active-set为求解算法
%%求解算法预留
A=[];
b=[];
Aeq=[];
beq=[];
%%求解
[A,fval,exitflag]=fmincon(@(x)NMPC(x,State_Initial,Np,Nc,T,Xref,Yref,PHIref,v1,deltaf1),[0;0;0;0;0;0],A,b,Aeq,beq,lb,ub,[],options);%有约束求解,需要有2*Nc个0
%%获得控制输入
v_actual=A(1);
deltaf_actual=A(2);
v1=v_actual;
deltaf1=deltaf_actual;
%%车辆位置代入
X00(1)=State_Initial(1,1);
X00(2)=State_Initial(2,1);
X00(3)=State_Initial(3,1);
%%代入控制输入后,解算下一时刻车辆位置
Xref=dsolve('Dx-v_actual*cos(z)=0','Dy-v_actual*sin(z)=0','Dz-v_actual*tan(deltaf_actual)/l=0','x(0)=X00(1)','y(0)=X00(2)','z(0)=X00(3)');
t=T;
%%更新车辆位置
State_Initial(1,1)=eval(Xref.x);
State_Initial(2,1)=eval(Xref.y);
State_Initial(3,1)=eval(Xref.z);
%%绘图
figure(1)
plot(State_Initial(1,1),State_Initial(2,1),'b*');
hold on;
plot(Xrefg(j,1),Yrefg(j,1),'ro');
hold on;
axis([-5 25 -5 25])
end
NMPC.m更新为:
function cost = NMPC(x,State_Initial,Np,Nc,T,Xref,Yref,PHIref,v1,delta_f1)
%%车辆长度
l=1;
%%预测时域内初始位置代入
X=State_Initial(1,1);
Y=State_Initial(2,1);
PHI=State_Initial(3,1);
%%循环,获得预测位姿
for i=1:1:Np
if i==1
v(i,1)=x(1);
delta_f(i,1)=x(2);
dv(i,1)=v(i,1)-v1;
ddelta_f(i,1)=delta_f(i,1)-delta_f1;
X_predict(i,1)=X+T*v(i,1)*cos(PHI);
Y_predict(i,1)=Y+T*v(i,1)*sin(PHI);
PHI_predict(i,1)=PHI+T*v(i,1)*tan(delta_f(i,1))/l;
else
if i<Nc
v(i,1)=x(2*i-1);
delta_f(i,1)=x(2*i);
else
v(i,1)=x(2*Nc-1);
delta_f(i,1)=x(2*Nc);
end
dv(i,1)=v(i,1)-v(i-1,1);
ddelta_f(i,1)=delta_f(i,1)-delta_f(i-1,1);
X_predict(i,1)=X_predict(i-1)+T*v(i,1)*cos(PHI_predict(i-1));
Y_predict(i,1)=Y_predict(i-1)+T*v(i,1)*sin(PHI_predict(i-1));
PHI_predict(i,1)=PHI_predict(i-1)+T*v(i,1)*tan(delta_f(i,1))/l;
end
%%解算预测位姿和参考轨迹的误差
X_error(i,1)=X_predict(i,1)-Xref(i,1);
Y_error(i,1)=Y_predict(i,1)-Yref(i,1);
PHI_error(i,1)=PHI_predict(i,1)-PHIref(i,1);
end
%cost=Y_error'*Y_error+X_error'*X_error; 也可以不加航向误差
cost=Y_error'*Y_error+X_error'*X_error+0.01*PHI_error'*PHI_error+0.1*dv'*dv+0.1*ddelta_f'*ddelta_f;
end
当平顺性惩罚项权重系数为0.1时,对控制效果的影响不大:
与不加入该惩罚项时性能相近:
详见: 白国星,公众号:Path Tracking Letters代码详解——NMPC路径跟踪复杂参考路径设置
当平顺性惩罚项权重系数为100时,该惩罚项将严重影响路径跟踪控制效果:
总而言之,笔者认为加入平顺性惩罚项的意义并不明显。如果采用控制增量作为控制输入,并加入控制增量约束条件时,加入平顺性惩罚项的意义将更加薄弱。后续笔者将更新采用控制增量作为控制输入的NMPC路径跟踪控制代码。
- ExtJs学习笔记(9)_Window的基本用法
- DateTime在ExtJs中无法正确序列化的问题
- ELK实时日志分析平台环境部署--完整记录
- 梳理Linux下OSI七层网络与TCP/IP五层网络架构
- 字符编码-使用c#研究
- iframe高度自适应的IE解决方案
- javascript读写本机文本文件
- 崔立鹏:腾讯云为知识竞技游戏提供解决方案
- Mysql之binlog日志说明及利用binlog日志恢复数据操作记录
- 常用的AJAX弹出层代码
- Linux下检测IP地址冲突及解决方法
- linux如何挂载windows下的共享文件
- silverlight2中的定时器,以及如何动态改变控件的坐标
- 定时备份windows机器上的文件到linux服务器上的操作梳理(rsync)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Git如何解决本地冲突(纯净版)
- No qualifying bean of type 'org.springframework.transaction.PlatformTransactionManager' available:
- typescript中的class和interface
- SSH随笔
- Python爬虫+Flask,带你创建车标学习网站
- Go 堆栈的理解
- Kubernetes 与虚拟化和容器化的关系
- Golang 读、写文件
- 这次妥妥地拿下散列表---基础、如何设计以及扩展使用(LRU)
- 必看的Linux服务器高并发调优实战
- Vue3.0来了
- Golang 正则表达式(regexp)
- CentOS7基于ss5搭建Socks5代理服务器
- Go热门开源项目大全
- Python钉钉报警及Zabbix集成钉钉报警