利用MPC原理控制差速两轮小车进行目标点追踪,仿真后发现规划出的“最优”输入走出来的路径很奇怪,有一个奇怪的尖角。我把R置零,代价函数应该只考虑了输出误差,此时为什么没有直接靠近目标点,而是拐了一个尖角?
clc;
clear all;
%% 生成参考轨迹 计算所有期望值
T=0.1; %采样时间
L=0.245; %轮间距
t=0:1:10*pi;
xr=5*sin(0.2*t);
yr=5-5*cos(0.2*t); %逆时针的圆
thetar=0.2*t;
N=length(xr);
Xr=[xr' yr' thetar'];
%参考控制量装载
vcr=kron(ones(N,1),0.25);
w=kron(ones(N,1),0.05);
Ur=[vcr w];
%% 控制系统的基本信息
Nx=3;
Nu=2;
Np=30; %预测步长
Nc=10; %控制步长
Row=10; %松弛因子
X0=[0 0 0]; %车辆初始状态
U0=[0 0];
%% 控制系统维度信息
qe0={(X0-Xr(2,:))'}; % 加了转置,状态量按列看
%!!!!单点跟踪时需要修改
qe0=cell2mat(qe0);
ue(:,1)=[0;0];
ue_collect(:,1)=ue(:,1); %用来记录所有产生的ue
qe(:,1)=qe0;
qe_collect(:,1)=qe;
delta_ue=[0;0];
delta_ue_collect(:,1)=[0;0];
X_real(:,1)=X0';
j=0; %用来记录到达参考点误差限内的误差值
k=0; %填充实际状态量
which_dot_flag=0;
Q=[1 0 0;0 1 0;0 0 1]; %theta位的修改会影响轨迹点处的震荡
q=eye(Np);
Q_bar=1*kron(q,Q);
R=1*eye(Nu*Nc);
%%单点跟踪************************
i=2 ;%针对第i个轨迹参考点
theta=Xr(i,3); %theta为期望角度,或期望朝向
A_star=[1 0 -0.25*T*sin(theta);
0 1 0.25*T*cos(theta);
0 0 1;];
B_star=[T*cos(theta) 0;
T*sin(theta) 0;
0 T]; %????????????
A_tilde_cell={A_star B_star;
zeros(2,3) eye(2);};
B_tilde_cell={B_star;eye(2);};
C_tilde_cell={eye(3) zeros(3,2);};
A_tilde=cell2mat(A_tilde_cell);
B_tilde=cell2mat(B_tilde_cell);
C_tilde=cell2mat(C_tilde_cell); %A_tilde*kesi(k)+B_tilde*Δue(k)
PHI_cell=cell(Np,1); %构建并填充PHI和TAHETA
THETA_cell=cell(Np,Nc);
for r=1:1:Np
PHI_cell{r,1}=C_tilde*A_tilde^r;
for s=1:1:Nc
if s<=r
THETA_cell{r,s}=C_tilde*(A_tilde^(r-s))*B_tilde;
else
THETA_cell{r,s}=zeros(Nx,Nu);
end
end
end
PHI=cell2mat(PHI_cell);
THETA=cell2mat(THETA_cell);
H_cell=cell(2,2); %构建H
H_cell{1,1}=2*((THETA')*Q_bar*THETA+R);
H_cell{1,2}=2*zeros(Nu*Nc,1);
H_cell{2,1}=2*zeros(1,Nu*Nc);
H_cell{2,2}=2*Row;
H=cell2mat(H_cell);
H=(H+H')/2;
for m=1:1:200 %控制周期的个数
kesi(:,1)=[qe(:,1);ue(:,1)]; % qe与ue相差一个时刻
E=PHI*kesi(:,1); %%%此处可能存在问题,需改正
%事实上,E=PHI*kesi-Yref,而Yref=0
f_cell=cell(1,2);
f_cell{1,1}=2*E'*Q_bar*THETA;
f_cell{1,2}=0;
f=cell2mat(f_cell);
%生成约束
%不等式约束
A_t=zeros(Nc,Nc);
for p=1:1:Nc
for q=1:1:Nc
if q<=p
A_t(p,q)=1;
else
A_t(p,q)=0;
end
end
end
A_I=kron(A_t,eye(Nu));%对应于falcone论文约束处理的矩阵A,求克罗内克积
Ut=kron(ones(Nc,1),ue(:,1));%此处感觉论文里的克罗内科积有问题,暂时交换顺序
umin=[-0.75;-0.2;];%维数与控制变量的个数相同
umax=[0.75;0.2]; %控制量的边界
delta_umin=[-0.5;-0.1;]; %控制量增量的边界
delta_umax=[0.5;0.1];
% umin=[-1;-1;];%维数与控制变量的个数相同
% umax=[1;1]; %控制量的边界
% delta_umin=[-0.5;-0.5;]; %控制量增量的边界
% delta_umax=[0.5;0.5];
Umin=kron(ones(Nc,1),umin);
Umax=kron(ones(Nc,1),umax);
A_cons_cell={A_I zeros(Nu*Nc,1);-A_I zeros(Nu*Nc,1)};
b_cons_cell={Umax-Ut;-Umin+Ut};
A_cons=cell2mat(A_cons_cell);%(求解方程)状态量不等式约束增益矩阵,转换为绝对值的取值范围
b_cons=cell2mat(b_cons_cell);%(求解方程)状态量不等式约束的取值
% 状态量约束
M=10; %取值为10意义不明 改改看看
delta_Umin=kron(ones(Nc,1),delta_umin);
delta_Umax=kron(ones(Nc,1),delta_umax);
lb=[delta_Umin;0];%(求解方程)状态量下界,包含控制时域内控制增量和松弛因子
ub=[delta_Umax;M];%(求解方程)状态量上界,包含控制时域内控制增量和松弛因子
%options = optimset('Algorithm','active-set');
options = optimset('Algorithm','interior-point-convex');
[X,fval,exitflag]=quadprog(H,f,A_cons,b_cons,[],[],lb,ub,[],options);
%计算发现X是单列向量,但X不是[ΔU 伊普西隆]吗,ΔU包含的控制量呢
%控制量也是按列排的,所以两两一组为一个时刻的ue,最后一位是伊普西隆
delta_ue(:,1)=[X(1,1);X(2,1);]; % 仅有一列,会被覆写
ue(:,1)=delta_ue(:,1)+ue(:,1); %为靠近轨迹点计算出的ue
qe(:,1)=A_star*qe(:,1)+B_star*ue(:,1); %计算写入最优输入后与轨迹点的误差,并且此处开始进入下一时刻
k=k+1; %每计算一次qe,即更新一次状态信息,就准备向X_real填充新的数据
X_real(:,k+1)=qe(:,1)+Xr(i,:)';
M_collect(:,k)=X(Nu*Nc+1,1); %记录松弛因子
delta_ue_collect(:,k)=delta_ue;
ue_collect(:,k)=ue;
qe_collect(:,k+1)=qe; %记录写入最优输入后与参考点的误差
fval_collect(:,k)=fval;
end
%%单点绘图**************************
figure(1)
n=1:1:201;
yyaxis left
plot(n,qe_collect(1,:),'r-',n,qe_collect(2,:),'b-')
ylabel('误差(m)')
yyaxis right
plot(n,qe_collect(3,:),'c-')
xlabel('T')
ylabel('误差(rad)')
title('状态误差')
legend('x误差','y误差','方向误差')
figure(2)
n=1:1:200;
u=ue_collect+kron(ones(1,200),[0.25;0.05]);
subplot(1,2,1)
plot(n,kron(ones(1,200),0.25),'r-',n,u(1,:),'b-')
xlabel('T')
ylabel('误差(m/s)')
title('速度跟踪')
legend('期望速度','实际速度')
subplot(1,2,2)
plot(n,kron(ones(1,200),0.05),'r-',n,u(2,:),'b-')
xlabel('T')
ylabel('误差(m/s)')
title('角速度跟踪')
legend('期望角速度','实际角速度')
figure(3)
plot(Xr(i,1),Xr(i,2),'r*',X_real(1,:),X_real(2,:),'b-')
xlabel('x')
ylabel('y')
title('跟踪轨迹')
legend('目标点','跟踪轨迹')
不知道你这个问题是否已经解决, 如果还没有解决的话: