无人机NMPC控制器Matlab代码案例解读

进一步学习仿真ing,欢迎纠错指点

直接看核心初始化及step函数部分

function setupImpl(obj,~,~,~)

% Perform one-time calculations, such as computing constants

% 初始化函数,只执行一次,重点在于solver求解器的初始化。

import casadi.*

%model params

dt=;  %根据实际参数及需求填入数据

m=;

g=;

J=diag([  ]);

l=;

belta=pi/4;

cm=;

ct=;

%control params

Q_p=diag([,,]);

Q_v=diag([,,]);

Q_q=diag([,,]);

Q_Omega=diag([,,]);

Q_u=diag([,,,]);

Omega_max_tilt=;

Omega_max_tor=;

%continous model

x=SX.sym('x',3);

v=SX.sym('v',3);

q=SX.sym('q',4);

Omega=SX.sym('Omega',3);

u=SX.sym('u',4);

X=[x;v;q;Omega];

T=u(1)+u(2)+u(3)+u(4);

G1_bar=[-l*sin(belta) l*sin(belta) l*sin(belta) -l*sin(belta);

l*cos(belta) -l*cos(belta) l*cos(belta) -l*cos(belta);

cm/ct cm/ct -cm/ct -cm/ct];

tao=G1_bar*u;

Omega_dot=J\(-cross(Omega,J*Omega)+tao);

A=[-q(2) -q(3) -q(4);

q(1) -q(4) q(3)

q(4) q(1) -q(2)

-q(3) q(2) q(1)];

q_dot=0.5*A*Omega;

R=[q(1)^2+q(2)^2-q(3)^2-q(4)^2 2*(q(2)*q(3)-q(1)*q(4)) 2*(q(2)*q(4)+q(1)*q(3));

2*(q(2)*q(3)+q(1)*q(4)) q(1)^2-q(2)^2+q(3)^2-q(4)^2 2*(q(3)*q(4)-q(1)*q(2));

2*(q(2)*q(4)-q(1)*q(3)) 2*(q(3)*q(4)+q(1)*q(2)) q(1)^2-q(2)^2-q(3)^2+q(4)^2];

v_dot=[0;0;g]-T/m*R*[0;0;1];

x_dot=v;

X_dot=[x_dot;v_dot;q_dot;Omega_dot];

f=Function('f',{X,u},{X_dot}); % 以上案例意在构建四旋翼连续系统动力学模型,{X,u}输入,{X_dot}输出。

%discrete model

X_now=SX.sym('X_now',13); % x v q Omega:3+3+4+3共13维。当前状态。

u_now=SX.sym('u_now',4); % actuator input % 当前控制输入

k1=f(X_now,u_now);

k2=f(X_now+dt/2*k1,u_now);

k3=f(X_now+dt/2*k2,u_now);

k4=f(X_now+dt*k3,u_now); 

X_next=X_now+dt/6*(k1+2*k2+2*k3+k4); % 由四步微分预测下一步状态

F=Function('F',{X_now,u_now},{X_next},{'X_now','u_now'},{'X_next'}); % 以上内容在连续系统的基础上构建离散的动力学模型,{X_now,u_now}输入,{X_next}输出。

% 离散模型形如公式:

%cost fcn & constraints

cost=0;

N=20;

U_N={};%decision variables %初始化为空 % 元胞数组可包含不同格式数据

U0=[];% initial guess

lbU=[];% lower bound   % 对状态及控制输入的限制

ubU=[];% upper bound

ineq={};% constraints of NLP % 不等式约束,后边作为casadi求解的参数需求。

lbg = []; % 对四元数及omega的限制

ubg = [];

%add mesured system state X0 in decision variables

X0=SX.sym('X0',13);

U_N={U_N{:},X0};  % 大U_N先填入13维x0,最终U_N为[13维状态,4维当前控制输入,4维下一步控制输入...,4维第N步控制输入]的形式

U0=[U0;zeros(13,1)];

lbU=[lbU;zeros(13,1)];

ubU=[ubU;zeros(13,1)];

Ref=SX.sym('Ref',17,N+1); %期望值为17*(N+1)矩阵 % 此处只是声名,step函数中赋值

Xr=Ref(1:13,:);  % 13*(N+1)维

Ur=Ref(14:17,:);

Xk=X0;  %  xk和Uk是纯的一步状态(13维)和输入控制(4维)

for i=0:N-1

Uk=SX.sym(['U_' num2str(i)],4); ;% 4维第i步控制输入u,待求解

% cost=cost+(Xr_N(:,i+1)-Xk)'*Q_x*(Xr_N(:,i+1)-Xk)+(Ur_N(:,i+1)-Uk)'*Q_u*(Ur_N(:,i+1)-Uk);

q_e=quat_subtract(Xr(7:10,i+1),Xk(7:10));    %(7:10)的数据为4*1的四元数,q_e求四元数差值

 % cost函数参考:

cost=cost+(Xr(1:3,i+1)-Xk(1:3))'*Q_p*(Xr(1:3,i+1)-Xk(1:3))+(Xr(4:6,i+1)-Xk(4:6))'*Q_v*(Xr(4:6,i+1)-Xk(4:6))+q_e(2:4)'*Q_q*q_e(2:4)+(Xr(11:13,i+1)-Xk(11:13))'*Q_Omega*(Xr(11:13,i+1)-Xk(11:13))+(Ur(:,i+1)-Uk)'*Q_u*(Ur(:,i+1)-Uk); 

% 此部分cost对应公式前半部分

U_N={U_N{:},Uk};% 动态扩展,将Uk添加至尾部。U_N扩展为[13维状态,4维当前控制输入...,4维第i步控制输入]。

U0=[U0;1.84;1.84;1.84;1.84];

lbU=[lbU;0;0;0;0]; % max_thrust - u_max,此时lbU增至13+4*i维向量。

ubU=[ubU;8.5;8.5;8.5;8.5]; % 同理

ineq={ineq{:},Xk(7)^2+Xk(8)^2+Xk(9)^2+Xk(10)^2,Xk(11),Xk(12),Xk(13)};

lbg=[lbg;1;-Omega_max_tilt;-Omega_max_tilt;-Omega_max_tor];

ubg=[ubg;1;Omega_max_tilt;Omega_max_tilt;Omega_max_tor]; 

% 以上三句:将姿态表示限制为单位四元数,对角速度上下限进行限制

% 数组扩展变化同理

Xk1=F('X_now',Xk,'u_now',Uk); % 由F求解下一个状态

Xk=Xk1.X_next; % 更新状态

end

% 循环后U_N成为[13维状态,4维当前控制输入,4维下一步控制输入...,4维第N步控制输入]形式,后续lbg、ubg同理。

q_e=quat_subtract(Xr(7:10,end),Xk(7:10));

cost=cost+(Xr(1:3,end)-Xk(1:3))'*Q_p*(Xr(1:3,end)-Xk(1:3))+(Xr(4:6,end)-Xk(4:6))'*Q_v*(Xr(4:6,end)-Xk(4:6))+q_e(2:4)'*Q_q*q_e(2:4)+(Xr(11:13,end)-Xk(11:13))'*Q_Omega*(Xr(11:13,end)-Xk(11:13));

% end为最后一次,对应公式后半部分

ineq={ineq{:},Xk(7)^2+Xk(8)^2+Xk(9)^2+Xk(10)^2,Xk(11),Xk(12),Xk(13)};

lbg=[lbg;1;-Omega_max_tilt;-Omega_max_tilt;-Omega_max_tor];

ubg=[ubg;1;Omega_max_tilt;Omega_max_tilt;Omega_max_tor];

%create solver %下文仅创建求解器,未求解

prob=struct('f',cost,'x',vertcat(U_N{:}),'g',vertcat(ineq{:}),'p',Ref);

solver = nlpsol('solver', 'ipopt', prob);

% vertcat(U_N{:})使得求解结果x为13+4*N?维垂直向量形式

obj.mpc_solver=solver;

obj.x0=U0;   % 初始值

obj.lbx=lbU; 

obj.ubx=ubU;

obj.lbg=lbg;

obj.ubg=ubg;

参考自 用casadi求解求解具有线性约束的二次规划 - 知乎 (zhihu.com)

end

function u = stepImpl(obj,Xr_N,Ur_N,X_in)

% Implement algorithm. Calculate y as a function of input u and

% discrete states.

w0=obj.x0; 

lbw=obj.lbx;

ubw=obj.ubx;

solver=obj.mpc_solver;

lbw(1:13)=X_in; %substitute mesured state into the solver

ubw(1:13)=X_in; 

% 以上两句话以边界约束的形式将此刻状态X_in传入求解函数,也即求解结果x的前13维其实是输入的当前状态

Ref=zeros(17,21);

Ref(1:13,:)=Xr_N;  % 期望状态为矩阵,也即连续轨迹

Ref(14:17,:)=Ur_N;

sol = solver('x0', w0, 'lbx', lbw, 'ubx', ubw,...

'lbg', obj.lbg, 'ubg', obj.ubg, 'p', Ref);

u = full(sol.x(14:17)); % 结果的14-17项即为所需控制输入u

end

function resetImpl(~)

% Initialize / reset discrete-state properties

end

end

end

  • 30
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值