mirror of
https://gitlab.com/lander-team/lander-cpp.git
synced 2025-06-17 07:36:47 +00:00
fixed LQR
This commit is contained in:
parent
90311ff17e
commit
c6b1f0fc2c
66
build/debug/gainCalc.m
Normal file
66
build/debug/gainCalc.m
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
clear all; clc;
|
||||||
|
%% User Defined Values
|
||||||
|
M0 = 1.2; % [kg]
|
||||||
|
vehicleHeight = 0.5318; % [m]
|
||||||
|
vehicleRadius = 0.05105; % [m]
|
||||||
|
|
||||||
|
%% Calcs
|
||||||
|
I11 = (1/12) * vehicleHeight^2 + 0.25 * vehicleRadius^2; % (1/12) * h^2 + 0.25 * r^2
|
||||||
|
I22 = (1/12) * vehicleHeight^2 + 0.25 * vehicleRadius^2; % (1/12) * h^2 + 0.25 * r^2
|
||||||
|
I33 = 0.5 * vehicleRadius^2; % 0.5 * r^2
|
||||||
|
I = M0 * [I11 0 0; 0 I22 0; 0 0 I33];
|
||||||
|
|
||||||
|
Q = eye(6) * I(3, 3);
|
||||||
|
Mu = 398600;
|
||||||
|
r0 = [6678; 0; 0];
|
||||||
|
|
||||||
|
k1 = (I(2,2) - I(3,3)) / I(1,1);
|
||||||
|
k2 = (I(1,1) - I(3,3)) / I(2,2);
|
||||||
|
k3 = (I(2,2) - I(1,1)) / I(3,3);
|
||||||
|
|
||||||
|
n = sqrt(Mu/(norm(r0)^3));
|
||||||
|
|
||||||
|
F = -2 * n^2 * [4 * k1, 0, 0; 0, 3 * k2, 0; 0, 0, k3];
|
||||||
|
G = n * [0, 0, (1 - k1); 0, 0, 0; (k3 - 1), 0, 0];
|
||||||
|
|
||||||
|
Iinv = [1 / I(1,1), 0, 0; 0, 1 / I(2,2), 0; 0, 0, 1 / I(3,3)];
|
||||||
|
|
||||||
|
A = [zeros(3,3), 0.5 * eye(3); F, G];
|
||||||
|
B = [zeros(3,3); Iinv];
|
||||||
|
|
||||||
|
R = eye(3)*10^-6;
|
||||||
|
Rinv = R^-1;
|
||||||
|
|
||||||
|
S = icare(A, B, Q, R);
|
||||||
|
|
||||||
|
K = Rinv * B' * S;
|
||||||
|
|
||||||
|
%% Outputs
|
||||||
|
% Copy results in command window to LQRcalc function in C++
|
||||||
|
fprintf("double K11 = %3.5f;\n", K(1, 1))
|
||||||
|
fprintf("double K12 = %3.5f;\n", K(1, 2))
|
||||||
|
fprintf("double K13 = %3.5f;\n", K(1, 3))
|
||||||
|
fprintf("double K14 = %3.5f;\n", K(1, 4))
|
||||||
|
fprintf("double K15 = %3.5f;\n", K(1, 5))
|
||||||
|
fprintf("double K16 = %3.5f;\n", K(1, 6))
|
||||||
|
fprintf("double K21 = %3.5f;\n", K(2, 1))
|
||||||
|
fprintf("double K22 = %3.5f;\n", K(2, 2))
|
||||||
|
fprintf("double K23 = %3.5f;\n", K(2, 3))
|
||||||
|
fprintf("double K24 = %3.5f;\n", K(2, 4))
|
||||||
|
fprintf("double K25 = %3.5f;\n", K(2, 5))
|
||||||
|
fprintf("double K26 = %3.5f;\n", K(2, 6))
|
||||||
|
fprintf("double K31 = %3.5f;\n", K(3, 1))
|
||||||
|
fprintf("double K32 = %3.5f;\n", K(3, 2))
|
||||||
|
fprintf("double K33 = %3.5f;\n", K(3, 3))
|
||||||
|
fprintf("double K34 = %3.5f;\n", K(3, 4))
|
||||||
|
fprintf("double K35 = %3.5f;\n", K(3, 5))
|
||||||
|
fprintf("double K36 = %3.5f;\n", K(3, 6))
|
||||||
|
|
||||||
|
syms yaw pitch roll yawdot pitchdot rolldot gain
|
||||||
|
w = [0.5*yaw 0.5*pitch 0.5*roll yawdot pitchdot rolldot]';
|
||||||
|
|
||||||
|
syms K11 K12 K13 K14 K15 K16 K21 K22 K23 K24 K25 K26 K31 K32 K33 K34 K35 K36
|
||||||
|
K = gain * [K11 K12 K13 K14 K15 K16; K21 K22 K23 K24 K25 K26; K31 K32 K33 K34 K35 K36];
|
||||||
|
|
||||||
|
simplify(K*w)
|
||||||
|
|
Binary file not shown.
BIN
build/debug/outputs/Accel-Vel-Alt vs Time.png
Normal file
BIN
build/debug/outputs/Accel-Vel-Alt vs Time.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
BIN
build/debug/outputs/Euler Angles vs Time.png
Normal file
BIN
build/debug/outputs/Euler Angles vs Time.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
BIN
build/debug/outputs/Servo Position vs Time.png
Normal file
BIN
build/debug/outputs/Servo Position vs Time.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
File diff suppressed because it is too large
Load Diff
@ -18,10 +18,19 @@ roll = T(:, 13);
|
|||||||
yawdot = T(:, 14);
|
yawdot = T(:, 14);
|
||||||
pitchdot = T(:, 15);
|
pitchdot = T(:, 15);
|
||||||
rolldot = T(:, 16);
|
rolldot = T(:, 16);
|
||||||
Servo1 = T(:, 17);
|
yawddot = T(:, 17);
|
||||||
Servo2 = T(:, 18);
|
pitchddot = T(:, 18);
|
||||||
m = T(:, 19);
|
rollddot = T(:, 19);
|
||||||
thrust = T(:, 20);
|
I11 = T(:, 20);
|
||||||
|
I22 = T(:, 21);
|
||||||
|
I33 = T(:, 22);
|
||||||
|
I11dot = T(:, 23);
|
||||||
|
I22dot = T(:, 24);
|
||||||
|
I33dot = T(:, 25);
|
||||||
|
Servo1 = T(:, 26);
|
||||||
|
Servo2 = T(:, 27);
|
||||||
|
m = T(:, 28);
|
||||||
|
thrust = T(:, 29);
|
||||||
|
|
||||||
% Acceleration
|
% Acceleration
|
||||||
subplot(3, 1, 1)
|
subplot(3, 1, 1)
|
||||||
|
BIN
build/release/outputs/Accel-Vel-Alt vs Time.png
Normal file
BIN
build/release/outputs/Accel-Vel-Alt vs Time.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
BIN
build/release/outputs/Euler Angles vs Time.png
Normal file
BIN
build/release/outputs/Euler Angles vs Time.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
BIN
build/release/outputs/Servo Position vs Time.png
Normal file
BIN
build/release/outputs/Servo Position vs Time.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
4318
build/release/simOut.csv
Normal file
4318
build/release/simOut.csv
Normal file
File diff suppressed because it is too large
Load Diff
@ -21,7 +21,7 @@ struct sVars
|
|||||||
double yawddotPrev, pitchddotPrev, rollddotPrev;
|
double yawddotPrev, pitchddotPrev, rollddotPrev;
|
||||||
|
|
||||||
double m, m0, mp, mb, mdot;
|
double m, m0, mp, mb, mdot;
|
||||||
double vehicleHeight, vehicleRadius;
|
double vehicleHeight, vehicleRadius, momentArm;
|
||||||
|
|
||||||
double tb;
|
double tb;
|
||||||
double vb;
|
double vb;
|
||||||
|
16
src/main.cpp
16
src/main.cpp
@ -14,22 +14,23 @@ int main()
|
|||||||
Vars.vz = 0; // [m/s]
|
Vars.vz = 0; // [m/s]
|
||||||
|
|
||||||
// Initial YPR
|
// Initial YPR
|
||||||
Vars.yaw = 0; // [rad]
|
Vars.yaw = 15 * 3.1416 / 180; // [rad]
|
||||||
Vars.pitch = 0; // [rad]
|
Vars.pitch = 0 * 3.1416 / 180; // [rad]
|
||||||
Vars.roll = 0; // [rad]
|
Vars.roll = 0 * 3.1416 / 180; // [rad]
|
||||||
|
|
||||||
// Initial YPRdot
|
// Initial YPRdot
|
||||||
Vars.yawdot = 0; // [rad/s]
|
Vars.yawdot = 0 * 3.1416 / 180; // [rad/s]
|
||||||
Vars.pitchdot = 0; // [rad/s]
|
Vars.pitchdot = 0 * 3.1416 / 180; // [rad/s]
|
||||||
Vars.rolldot = 0; // [rad/s]
|
Vars.rolldot = 0 * 3.1416 / 180; // [rad/s]
|
||||||
|
|
||||||
// Servo Limitation
|
// Servo Limitation
|
||||||
Vars.maxServo = 0; // [degs]
|
Vars.maxServo = 15; // [degs]
|
||||||
|
|
||||||
// Vehicle Properties
|
// Vehicle Properties
|
||||||
Vars.m0 = 1.2; // [kg]
|
Vars.m0 = 1.2; // [kg]
|
||||||
Vars.vehicleHeight = 0.5318; // [m]
|
Vars.vehicleHeight = 0.5318; // [m]
|
||||||
Vars.vehicleRadius = 0.05105; // [m]
|
Vars.vehicleRadius = 0.05105; // [m]
|
||||||
|
Vars.momentArm = 0.145; // [m]
|
||||||
|
|
||||||
// Sim Step Size
|
// Sim Step Size
|
||||||
Vars.stepSize = 1; // [ms]
|
Vars.stepSize = 1; // [ms]
|
||||||
@ -43,6 +44,7 @@ int main()
|
|||||||
sim(Vars);
|
sim(Vars);
|
||||||
|
|
||||||
std::cout << "Finished";
|
std::cout << "Finished";
|
||||||
|
std::cin.get();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
70
src/sim.cpp
70
src/sim.cpp
@ -28,7 +28,7 @@ void sim(struct sVars &Vars)
|
|||||||
// Output file header. These are the variables that we output - useful for
|
// Output file header. These are the variables that we output - useful for
|
||||||
// debugging
|
// debugging
|
||||||
outfile << "t, x, y, z, vx, vy, vz, ax, ay, az, yaw, pitch, roll, yawdot, "
|
outfile << "t, x, y, z, vx, vy, vz, ax, ay, az, yaw, pitch, roll, yawdot, "
|
||||||
"pitchdot, rolldot, Servo1, Servo2, m, thrust, burnElapsed, Fz, "
|
"pitchdot, rolldot, yawddot, pitchddot, rollddot, I11, I22, I33, I11dot, I22dot, I33dot, Servo1, Servo2, m, thrust, burnElapsed, Fz, "
|
||||||
"LQRx, LQRy"
|
"LQRx, LQRy"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
@ -108,8 +108,7 @@ void thrustSelection(struct sVars &Vars, int t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
Vars.burnElapsed =
|
Vars.burnElapsed = 2000; // arbitrary number to ensure we don't burn
|
||||||
2000; // 2000 just an arbitrary number to make sure we don't burn
|
|
||||||
|
|
||||||
bool b_thrustSelect;
|
bool b_thrustSelect;
|
||||||
|
|
||||||
@ -135,12 +134,15 @@ void thrustSelection(struct sVars &Vars, int t)
|
|||||||
|
|
||||||
void lqrCalc(struct sVars &Vars)
|
void lqrCalc(struct sVars &Vars)
|
||||||
{
|
{
|
||||||
|
|
||||||
Vars.I11 = Vars.m * ((1 / 12) * pow(Vars.vehicleHeight, 2) +
|
Vars.I11 = Vars.m * ((1 / 12) * pow(Vars.vehicleHeight, 2) +
|
||||||
pow(Vars.vehicleRadius, 2) / 4);
|
pow(Vars.vehicleRadius, 2) / 4);
|
||||||
Vars.I22 = Vars.m * ((1 / 12) * pow(Vars.vehicleHeight, 2) +
|
Vars.I22 = Vars.m * ((1 / 12) * pow(Vars.vehicleHeight, 2) +
|
||||||
pow(Vars.vehicleRadius, 2) / 4);
|
pow(Vars.vehicleRadius, 2) / 4);
|
||||||
Vars.I33 = Vars.m * 0.5 * pow(Vars.vehicleRadius, 2);
|
Vars.I33 = Vars.m * 0.5 * pow(Vars.vehicleRadius, 2);
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
double n = sqrt(398600 / pow(6678, 3));
|
double n = sqrt(398600 / pow(6678, 3));
|
||||||
double k1 = (Vars.I22 - Vars.I33) / Vars.I11;
|
double k1 = (Vars.I22 - Vars.I33) / Vars.I11;
|
||||||
double k2 = (Vars.I11 - Vars.I33) / Vars.I22;
|
double k2 = (Vars.I11 - Vars.I33) / Vars.I22;
|
||||||
@ -164,6 +166,7 @@ void lqrCalc(struct sVars &Vars)
|
|||||||
Algorithm taken from LQR wikipedia page:
|
Algorithm taken from LQR wikipedia page:
|
||||||
https://en.wikipedia.org/wiki/Algebraic_Riccati_equation#Solution
|
https://en.wikipedia.org/wiki/Algebraic_Riccati_equation#Solution
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
double gain = 0.25;
|
double gain = 0.25;
|
||||||
|
|
||||||
double K11 =
|
double K11 =
|
||||||
@ -190,9 +193,47 @@ void lqrCalc(struct sVars &Vars)
|
|||||||
(pow(abs(F33), 2) * pow(abs(Vars.I33), 4) * pow(abs(R33), 2) + 1));
|
(pow(abs(F33), 2) * pow(abs(Vars.I33), 4) * pow(abs(R33), 2) + 1));
|
||||||
|
|
||||||
// Matrix Multiply K with [YPR/2; w123] column vector and divide by moment arm
|
// Matrix Multiply K with [YPR/2; w123] column vector and divide by moment arm
|
||||||
double momentArm = 0.145;
|
Vars.LQRx = (K11 * Vars.yaw / 2 + K16 * Vars.rolldot) / Vars.momentArm;
|
||||||
Vars.LQRx = (K11 * Vars.yaw / 2 + K16 * Vars.rolldot) / momentArm;
|
Vars.LQRy = (K22 * Vars.pitch / 2) / Vars.momentArm;
|
||||||
Vars.LQRy = (K22 * Vars.pitch / 2) / momentArm;
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
double K11 = 39.54316;
|
||||||
|
double K12 = 0.00000;
|
||||||
|
double K13 = -0.00000;
|
||||||
|
double K14 = 39.55769;
|
||||||
|
double K15 = 0.00000;
|
||||||
|
double K16 = 0.00000;
|
||||||
|
double K21 = 0.00000;
|
||||||
|
double K22 = 39.54316;
|
||||||
|
double K23 = 0.00000;
|
||||||
|
double K24 = 0.00000;
|
||||||
|
double K25 = 39.55769;
|
||||||
|
double K26 = 0.00000;
|
||||||
|
double K31 = 0.00000;
|
||||||
|
double K32 = 0.00000;
|
||||||
|
double K33 = 39.54316;
|
||||||
|
double K34 = 0.00000;
|
||||||
|
double K35 = 0.00000;
|
||||||
|
double K36 = 39.54394;
|
||||||
|
|
||||||
|
double gain = 0.25 * pow(10, -4);
|
||||||
|
|
||||||
|
// Matrix Multiply K with [YPR/2; w123] column vector and divide by moment arm
|
||||||
|
Vars.LQRx = gain * ((K12 * Vars.pitch) / 2 + K15 * Vars.pitchdot + (K13 * Vars.roll) / 2 + K16 * Vars.rolldot + (K11 * Vars.yaw) / 2 + K14 * Vars.yawdot) / -Vars.momentArm;
|
||||||
|
Vars.LQRy = gain * ((K22 * Vars.pitch) / 2 + K25 * Vars.pitchdot + (K23 * Vars.roll) / 2 + K26 * Vars.rolldot + (K21 * Vars.yaw) / 2 + K24 * Vars.yawdot) / -Vars.momentArm;
|
||||||
|
|
||||||
|
// LQR Force limiter X
|
||||||
|
if (Vars.LQRx > Vars.thrust)
|
||||||
|
Vars.LQRx = Vars.thrust;
|
||||||
|
else if (Vars.LQRx < -1 * Vars.thrust)
|
||||||
|
Vars.LQRx = -1 * Vars.thrust;
|
||||||
|
|
||||||
|
// LQR Force limiter Y
|
||||||
|
if (Vars.LQRy > Vars.thrust)
|
||||||
|
Vars.LQRy = Vars.thrust;
|
||||||
|
else if (Vars.LQRy < -1 * Vars.thrust)
|
||||||
|
Vars.LQRy = -1 * Vars.thrust;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TVC(struct sVars &Vars, double g)
|
void TVC(struct sVars &Vars, double g)
|
||||||
@ -236,9 +277,8 @@ void TVC(struct sVars &Vars, double g)
|
|||||||
(Vars.m * g);
|
(Vars.m * g);
|
||||||
|
|
||||||
// Calculate moment created by Fx and Fy
|
// Calculate moment created by Fx and Fy
|
||||||
double momentArm = 0.145;
|
Vars.momentX = Vars.Fx * Vars.momentArm;
|
||||||
Vars.momentX = Vars.Fx * momentArm;
|
Vars.momentY = Vars.Fy * Vars.momentArm;
|
||||||
Vars.momentY = Vars.Fy * momentArm;
|
|
||||||
Vars.momentZ = 0;
|
Vars.momentZ = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -378,6 +418,18 @@ void write2CSV(struct sVars &Vars, std::fstream &outfile, int t)
|
|||||||
outfile << Vars.pitchdot * 180 / 3.1416 << ", ";
|
outfile << Vars.pitchdot * 180 / 3.1416 << ", ";
|
||||||
outfile << Vars.rolldot * 180 / 3.1416 << ", ";
|
outfile << Vars.rolldot * 180 / 3.1416 << ", ";
|
||||||
|
|
||||||
|
outfile << Vars.yawddot * 180 / 3.1416 << ", ";
|
||||||
|
outfile << Vars.pitchddot * 180 / 3.1416 << ", ";
|
||||||
|
outfile << Vars.rollddot * 180 / 3.1416 << ", ";
|
||||||
|
|
||||||
|
outfile << Vars.I11 << ", ";
|
||||||
|
outfile << Vars.I22 << ", ";
|
||||||
|
outfile << Vars.I33 << ", ";
|
||||||
|
|
||||||
|
outfile << Vars.I11dot << ", ";
|
||||||
|
outfile << Vars.I22dot << ", ";
|
||||||
|
outfile << Vars.I33dot << ", ";
|
||||||
|
|
||||||
outfile << Vars.xServoDegs << ", ";
|
outfile << Vars.xServoDegs << ", ";
|
||||||
outfile << Vars.yServoDegs << ", ";
|
outfile << Vars.yServoDegs << ", ";
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user