-
Notifications
You must be signed in to change notification settings - Fork 1
/
EngineGuidRate.m
106 lines (91 loc) · 2.73 KB
/
EngineGuidRate.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
classdef EngineGuidRate < EngineAero
properties (Access = protected)
% New state scalars
PRA;
bank;
count;
target;
% New state vectors
Q0;
Qir;
MRP;
PRV;
end
properties (Access = protected, Constant)
tolMRP = 0.01;
offtime = 10; % after W*dt [seconds]
end
methods (Access = protected)
function Mc = controls(self, ~, ~, sc)
% Rate
Wref = zeros(3, 1);
dWref = zeros(3, 1);
deltaW = self.W - Wref;
% Attitude - body w.r.t. reference
q0 = self.Q(1); q1 = self.Q(2); q2 = self.Q(3); q3 = self.Q(4);
Qref = [q0, -q1, -q2, -q3 ;
q1, q0, q3, -q2 ;
q2, -q3, q0, q1 ;
q3, q2, -q1, q0];
Qbr = self.bank * Qref * self.Qir;
self.MRP = Qbr(2:4) / (1 + Qbr(1)); % Quaternions -> Modified Rodrigues Parameters
% Lyapunov-derived control law
Mc = sc.I * (dWref - cross(self.W, Wref)) + cross(self.W, sc.I * self.W) - diag(sc.hold) * self.MRP - diag(sc.damp) * deltaW;
end
function [val, ter, sgn] = event(self, t, sc, pl)
% Call superclass method
[val, ter, sgn] = event@EngineAero(self, t, sc, pl);
if ~self.bank && t >= sc.tref(self.count)
self.initroll();
elseif self.bank && self.PRA == self.target && (max(abs(self.MRP)) < self.tolMRP || t - sc.tref(self.count) - self.offtime > pi/sc.maxW)
self.stoproll();
elseif self.bank && (t - sc.tref(self.count)) > 0
self.rateroll(sc.maxW * (t - sc.tref(self.count)));
end
% Append new event outputs
val = [val; t - sc.tref(self.count)];
ter = [ter; false];
sgn = [sgn; +1];
end
function initroll(self)
% Start bank angle roll
self.Q0 = self.Q;
self.PRV = self.Urel / norm(self.Urel);
self.target = (mod(self.count, 2) * 2 - 1) * pi;
% For next checks
self.MRP = ones(3, 1);
self.Qir = zeros(4, 1);
self.bank = true;
end
function stoproll(self)
% Reached final attitude, stop enforcing MRP
self.bank = false;
self.count = self.count + 1;
end
function rateroll(self, maxroll)
% Rate-limit bank angle rotation
self.PRA = sign(self.target) * min(abs(self.target), maxroll); % sc.maxW * (t - sc.tref(self.count))
q0 = cos(self.PRA/2); q1 = self.PRV(1) * sin(self.PRA/2); q2 = self.PRV(2) * sin(self.PRA/2); q3 = self.PRV(3) * sin(self.PRA/2);
Qref = [q0, -q1, -q2, -q3;
q1, q0, q3, -q2;
q2, -q3, q0, q1;
q3, q2, -q1, q0];
Qri = Qref * self.Q0; % quaternion addition
self.Qir = [Qri(1); -Qri(2:4)];
end
function initreset(self)
% Call superclass method
initreset@EngineAero(self);
% New state scalars
self.PRA = 0;
self.bank = false;
self.count = 1;
self.target = 0;
% New state vectors
self.Q0 = zeros(4, 1);
self.Qir = zeros(4, 1);
self.MRP = zeros(3, 1);
self.PRV = zeros(3, 1);
end
end
end