# Feedback control - need to update an algebraic variable within ODE function.

4 views (last 30 days)
Conor Ryan on 12 Apr 2020
Answered: James Tursa on 7 May 2020
I am trying to code a quaternion feedback controller for the rotation of a satellite. I have a function which i use ode45 with and returns the quaternions x(1) to x(4) and angular velocities x(5) to x(7). Within this function I also find the control torque u1, u2 and u3 which depend on the values obtained from the quaternions and the angular velocities. I want u1,u2 and u3 to initially be 0, and then update depending on the values obtained from using ode45. This is then fed back into xdot(5)-xdot(7) and then the control is completed. I am having difficulty with initialising u1,u2 and u3 to be zero and then updating as the function runs. Any help appreciated, thanks.
function [xdot] = Feedback(t,x)
ue1 = 0.1; %External Torques (M)
ue2 = 0.1;
ue3 = 0.1;
J1 = 431; %Moments of Inertia
J2 = 421;
J3 = 485;
q1c = 0.5; %Desired Quaternions
q2c = -0.5;
q3c = 0.5;
q4c = 0.5;
k = 1; %Controller constants
c1 = 4;
c2 = 4;
c3 = 4;
xdot = zeros(7,1); % a column vector
% Quaternions
xdot(1)=((x(7)*x(2)-x(6)*x(3)+x(5)*x(4))*.5);
xdot(2)=((-x(7)*x(1)+x(5)*x(3)+x(6)*x(4))*.5);
xdot(3)=((x(6)*x(1)-x(5)*x(2)+x(7)*x(4))*.5);
xdot(4)=((-x(5)*x(1)-x(6)*x(2)-x(7)*x(3))*.5);
% Angular Velocities
xdot(5)=(u1+ue1+(J2-J3)*x(6)*x(7))/J1;
xdot(6)=(u2+ue2+(J3-J1)*x(7)*x(5))/J2;
xdot(7)=(u3+ue3+(J1-J2)*x(5)*x(6))/J3;
% Error Quaternions
qe1=(q4c*x(1)+q3c*x(2)-q2c*x(3)-q1c*x(4));
qe2=(-q3c*x(1)+q4c*x(2)+q1c*x(3)-q2c*x(4));
qe3=(q2c*x(1)-q1c*x(2)+q4c*x(3)-q3c*x(4));
% Control Torques
u1=-k*qe1-c1*x(5);
u2=-k*qe2-c2*x(6);
u3=-k*qe3-c3*x(7);
end

Conor Ryan on 13 Apr 2020 Conor Ryan on 13 Apr 2020 Conor Ryan on 13 Apr 2020
For the omega dot 1,2 and 3 there should also be the terms ue1, ue2 and ue3 added beside the terms u1, u2 and u3 respectively which are just constants = 0.1.

James Tursa on 7 May 2020
I think you are using the wrong tool for this. ode45( ) is an adaptive integrator, which means that it has the freedom to change stepsizes and make derivative function calls at times that are not necessarily increasing. E.g. ode45( ) might try to make a step with dt, then detect that the estimated error terms are too large, so it will decrease dt and try again. This will result in ode45( ) making calls to your derivative function at times that are not strictly increasing ... there will be some calls at times that are before the time of an earlier call. I think this is going to mess up your feedback control that you have inside your derivative function. Calculating your feedback control at the end of your derivative function and making it persistent inside the derivative function so that it gets used in the next integration step isn't going to fix this problem.
I would offer two things you could try:
1) Use your own hand-coded RK4 code where you can dictate that the derivative function calls are always going forward in time, AND at the same time you can dictate when to calculate and apply your control feedback, which will be fed into the next integration step. The RK4 code isn't that difficult to write and this is probably the simplest thing to try.
2) Code things up in Simulink with an actual feedback loop (you will need to put in a feedback delay to avoid an algebraic loop error).