%% Set up basic symbols.
% Use sprintf() and char(sym()) to automate.
t = sym('t');

x = sym('x(t)');
dx=diff(x,t);
ddx=diff(dx,t);

a = sym('a(t)');
da = diff(a,t);
dda = diff(da,t);

prettyx = sym('x');
prettydx = sym('dx');
prettyddx = sym('ddx');
prettya = sym('a');
prettyda = sym('da');
prettydda = sym('dda');


%% Set up display symbols
% Use sprintf() and char(sym()) to automate.
ddprettyvars = { prettyddx, prettydda };
dprettyvars = { prettydx, prettyda };
prettyvars = { prettyx, prettya };
%allprettyvars = { prettydda, prettyddx, prettyda, prettydx, prettya, prettyx };

dduglyvars = { ddx, dda };
duglyvars = { dx, da };
uglyvars = { x, a };
%alluglyvars = { dda, ddx, da, dx, a, x };


%% Physical parameters of the segway - masses, inertias, lengths, gravity
syms Mw Iw Rw Hr Ir Mr g

%% Wheel kinetic and potential energy
Tw = (1/2) * Mw * dx^2 + (1/2)*Iw*(dx/Rw)^2
Vw = sym('0')

%% Rider kinetic and potential energy
Tr = (1/2)*Ir*(da^2) + (1/2)*Mr*((dx+Hr*da*cos(a))^2+(Hr*da*sin(a))^2)
Vr = Mr * g * Hr * cos(a)


%% The Lagrangian of the segway
T = Tw + Tr
V = Vw + Vr
L = T - V

% Matlab can't differentiate with respect to a variable in function(ugly)
% form, e.g. sym('x(t)')
% CAUTION: Must translate from ugly accelerations first to get
% substitutions right.
prettyL = L;
prettyL = subs(prettyL, dduglyvars, ddprettyvars);
prettyL = subs(prettyL, duglyvars, dprettyvars);
prettyL = subs(prettyL, uglyvars, prettyvars);

%% Differentiate the second term of the lagrangian.
dLdx = diff(prettyL, prettyx)
dLda = diff(prettyL, prettya)

%% Inner differentiation of the first term of the lagrangian.
dLdxdot = diff(prettyL, prettydx)
dLdadot = diff(prettyL, prettyda)

%% Uglify first term so Matlab knows x, a, etc. are functions of time.
% (not constants)
% CAUTION: must translate this time from pretty positions first to get
% substitutions right
uglydLdxdot = dLdxdot;
uglydLdxdot = subs(uglydLdxdot, prettyvars, uglyvars)
uglydLdxdot = subs(uglydLdxdot, dprettyvars, duglyvars);
uglydLdxdot = subs(uglydLdxdot, ddprettyvars, dduglyvars);

uglydLdadot = dLdadot;
uglydLdadot = subs(uglydLdadot, prettyvars, uglyvars)
uglydLdadot = subs(uglydLdadot, dprettyvars, duglyvars);
uglydLdadot = subs(uglydLdadot, ddprettyvars, dduglyvars);


%% Differentiate ugly first terms with respect to time.
uglydtdLdxdot = diff(uglydLdxdot, t)
uglydtdLdadot = diff(uglydLdadot, t)

%% Prettify first terms
dtdLdxdot = uglydtdLdxdot;
dtdLdxdot = subs(dtdLdxdot, dduglyvars, ddprettyvars);
dtdLdxdot = subs(dtdLdxdot, duglyvars, dprettyvars);
dtdLdxdot = subs(dtdLdxdot, uglyvars, prettyvars);

dtdLdadot = uglydtdLdadot;
dtdLdadot = subs(dtdLdadot, dduglyvars, ddprettyvars);
dtdLdadot = subs(dtdLdadot, duglyvars, dprettyvars);
dtdLdadot = subs(dtdLdadot, uglyvars, prettyvars);

%% Form pretty expressions for generalized forces

qx = dtdLdxdot - dLdx
qa = dtdLdadot - dLda

%% Gather into matrix form
% Forces are linear in ddx, dda
qx = expand(simplify(qx))
qa = expand(simplify(qa))
MM = sym(zeros(2));

%% Demonstrate use coeffs to get mass matrix
qxtmp = qx;
[Cc,Tc] = coeffs(qxtmp, prettyddx);
if length(Cc) == 2 && Tc(2) == prettyddx
  MM(1,1) = Cc(2);
  qxtmp = expand(qxtmp - Cc(2) * prettyddx);
end

%% Get mass matrix and rest in a loop.
qs = { qx, qa };
for i = 1:2
    for j = 1:2
        [Cc,Tc] = coeffs(qs{i}, ddprettyvars{j});
        if length(Cc) == 2 && Tc(2) == ddprettyvars{j}
          MM(i,j) = simplify(Cc(2));
          qs{i} = expand(qs{i} - Cc(2) * ddprettyvars{j});
        end
    end
end

rest = [ simplify(qs{1}); simplify(qs{2}) ];

        
  
