% L12_2dfan.m - ducted fan example for L12.2
% RMM, 14 Jan 03

%%
%% Ducted fan dynamics
%%
%% These are the dynamics for the ducted fan, written in state space
%% form.
%%

% System parameters
J = 0.0475;			% inertia around pitch axis
m = 1.5;			% mass of fan
r = 0.25;			% distance to flaps
g = 10;				% gravitational constant
gamma = 0.51;			% counterweighted mass
d = 0.2;	 		% damping factor (estimated)
l = 0.05;			% offset of center of mass

% System matrices (entire plant: 2 input, 2 output)
A = [  0     0     0     1     0     0;
       0     0     0     0     1     0;
       0     0     0     0     0     1;
       0     0  -gamma -d/m    0     0;
       0     0     0     0   -d/m    0;
       0     0 -m*g*l/J  0     0     0 ];
 
B = [  0     0;
       0     0;
       0     0;
      1/m    0;
       0    1/m;
      r/J    0    ];

C = [  1     0    0      0     0     0;
       0     1    0      0     0     0 ];

D = [  0     0;   0      0];

%%
%% Construct inputs and outputs corresponding to steps in xy position
%%
%% The vectors xd and yd correspond to the states that are the desired
%% equilibrium states for the system.  The matrices Cx and Cy are the 
%% corresponding outputs.
%%
%% The way these vectors are used is to compute the closed loop system
%% dynamics as
%%
%%	xdot = Ax + B u		=>	xdot = (A-BK)x + K xd
%%         u = -K(x - xd)		   y = Cx
%%
%% The closed loop dynamics can be simulated using the "step" command, 
%% with K*xd as the input vector (assumes that the "input" is unit size,
%% so that xd corresponds to the desired steady state.
%%

xd = [1; 0; 0; 0; 0; 0];  Cx = [1 0 0 0 0 0];
yd = [0; 1; 0; 0; 0; 0];  Cy = [0 1 0 0 0 0];

%%
%% LQR design
%%

% Start with a diagonal weighting
Q1 = diag([1, 1, 1, 1, 1, 1]);
R1a = 0.1 * diag([1, 1]);
K1a = lqr(A, B, Q1, R1a);

% Close the loop: xdot = Ax + B K (x-xd)
H1ax = ss(A-B*K1a,B(:,1)*K1a(1,:)*xd,Cx,0);
H1ay = ss(A-B*K1a,B(:,2)*K1a(2,:)*yd,Cy,0);
figure(1); step(H1ax, H1ay, 10);
legend('x', 'y');

% Look at different input weightings
R1b = diag([1, 1]); K1b = lqr(A, B, Q1, R1b);
H1bx = ss(A-B*K1b,B(:,1)*K1b(1,:)*xd,Cx,0);

R1c = diag([10, 10]); K1c = lqr(A, B, Q1, R1c);
H1cx = ss(A-B*K1c,B(:,1)*K1c(1,:)*xd,Cx,0);

figure(2); step(H1ax, H1bx, H1cx, 10);
legend('rho = 0.1', 'rho = 1', 'rho = 10');

% Output weighting
Q2 = [Cx; Cy]' * [Cx; Cy];
R2 = 0.1 * diag([1, 1]);
K2 = lqr(A, B, Q2, R2);

H2x = ss(A-B*K2,B(:,1)*K2(1,:)*xd,Cx,0);
H2y = ss(A-B*K2,B(:,2)*K2(2,:)*yd,Cy,0);
figure(3); step(H2x, H2y, 10);
legend('x', 'y');

%%
%% Physically motivated weighting
%%
%% Shoot for 1 cm error in x, 10 cm error in y.  Try to keep the angle
%% less than 5 degrees in making the adjustments.  Penalize side forces
%% due to loss in efficiency.
%%

Q3 = diag([100, 10, 2*pi/5, 0, 0, 0]);
R3 = 0.1 * diag([1, 10]);
K3 = lqr(A, B, Q3, R3);

H3x = ss(A-B*K3,B(:,1)*K3(1,:)*xd,Cx,0);
H3y = ss(A-B*K3,B(:,2)*K3(2,:)*yd,Cy,0);
figure(4); step(H3x, H3y, 10);
legend('x', 'y');

%%
%% Velocity control
%%
%% In this example, we modify the system so that we control the
%% velocity of the system in the x direction.  We ignore the 
%% dynamics in the vertical (y) direction.  These dynamics demonstrate
%% the role of the feedforward system since the equilibrium point 
%% corresponding to vd neq 0 requires a nonzero input.
%%
%% For this example, we use a control law u = -K(x-xd) + ud and convert 
%% this to the form u = -K x + N r, where r is the reference input and
%% N is computed as described in class.
%%

% Extract system dynamics: theta, xdot, thdot
Av = A([3 4 6], [3 4 6]);
Bv = B([3 4 6], 1);
Cv = [0 1 0];				% choose vx as output
Dv = 0;	

% Design the feedback term using LQR
Qv = diag([2*pi/5, 10, 0]);
Rv = 0.1;
Kv = lqr(Av, Bv, Qv, Rv);

% Design the feedforward term by solve for eq pt in terms of reference r
T = [Av Bv; Cv Dv];			% system matrix
Nxu = T \ [0; 0; 0; 1];			% compute [Nx; Nu]
Nx = Nxu(1:3); Nu = Nxu(4);		% extract Nx and Nu
N = Nu + Kv*Nx;				% compute feedforward term

%%
%% Design #1: no feedforward input, ud
%%

Nv1 = [0; 1; 0];
Hv1 = ss(Av-Bv*Kv, Bv*Kv*Nx, Cv, 0);
step(Hv1, 10);

%%
%% Design #2: compute feedforward gain corresponding to equilibrium point
%%

Hv2 = ss(Av-Bv*Kv, Bv*N, Cv, 0);
step(Hv2, 10);

%%
%% Design #3: integral action
%%
%% Add a new state to the system that is given by xidot = v - vd.  We
%% construct the control law by computing an LQR gain for the augmented
%% system.
%%

Ai = [Av, [0; 0; 0]; [Cv, 0]];
Bi = [Bv; 0];
Ci = [Cv, 0];
Di = Dv;

% Design the feedback term, including weight on integrator error
Qi = diag([2*pi/5, 10, 0, 10]);
Ri = 0.1;
Ki = lqr(Ai, Bi, Qi, Ri);

% Desired state (augmented)
xid = [0; 1; 0; 0];

% Construct the closed loop system (including integrator)
Hi = ss(Ai-Bi*Ki,Bi*Ki*xid - [0; 0; 0; Ci*xid],Ci,0);
step(Hi, 10);
