summaryrefslogtreecommitdiffstats
path: root/uav_uncertainty.m
blob: 045321d344ba2257f8200adbc29da7455285748d (plain)
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
% Generate transfer functions for loop shaping stability (uncertainty)
% requirements from parameters specified in uav_params.m
%
% Copyright (C) 2024, Naoki Sean Pross, ETH Zürich
% This work is distributed under a permissive license, see LICENSE.txt
%
% Arguments:
%   PARAMS  Struct of design parameters and constants generated by uav_params
%   PLOT    When set to 'true' it plots the inverse magnitude of the
%           performance transfer function
%
% Return value:
%   UNCERT  Struct of uncertainty transfer functions


function [uncert] = uav_performance(params, do_plots)

s = tf('s');

% relative errors
eps_T = params.aerodynamics.ThrustOmegaPropUncertainty;
eps_r = params.mechanical.GyroscopicInertiaZUncertainty;
eps_S = params.aerodynamics.FlapAreaUncertainty;
eps_l = params.aerodynamics.LiftCoefficientUncertainty;
eps_d = params.aerodynamics.DragCoefficientsUncertainties(1);
% eps_0 = params.aerodynamics.DragCoefficients(2);

eps_omega = max(.5 * eps_T, eps_r);
eps_alpha = max(eps_l + eps_S + 2 * eps_omega, eps_S + eps_d + eps_omega);

b = 12;
T = 1;
G = make_weight(b, 4, 1);

W_malpha = eps_alpha * tf(1);
W_momega = eps_omega * tf(1);
W_mState = (1 - tf(1, [T, 1])) * blkdiag( ...
  .2 * eye(3), ...
  .1 * eye(3), ...
  .2 * eye(3) ...
);

uncert = struct(...
  'FlapAngleEpsilon', eps_alpha, ...
  'ThrustEpsilon', eps_omega, ...
  'FlapAngle', W_malpha * eye(4), ...
  'Thrust', W_momega, ...
  'StateLinApprox', W_mState);

if do_plots
  % Bode plots of performance requirements
  figure; hold on;
  bodemag(W_malpha);
  bodemag(W_momega);

  bodemag(W_mState(1,1));
  bodemag(W_mState(4,4));
  bodemag(W_mState(7,7));

  grid on;
  legend('$W_{m,\alpha}$', '$W_{m,\omega}$', ...
         ... % '$W_{m,\mathbf{P}}$', ...
         '$W_{m,\mathbf{\dot{P}}}$', ...
         '$W_{m,\mathbf{\Theta}}$', ...
         '$W_{m,\mathbf{\Omega}}$', ...
         'interpreter', 'latex')
  title('\bfseries Stability Requirement (only for $\mu$-Synthesis)', ...
        'interpreter', 'latex')
end

end

% Make a n-order performance weight function
%
% Arguments:
%   OMEGA  Cutting frequency (-3dB)
%   A      Magnitude at DC, i.e. |Wp(0)|
%   M      Magnitude at infinity, i.e. |Wp(inf)|
%   ORD    Order
function [Wp] = make_weight(omega, A, M, ord)

if nargin > 3
  n = ord;
else
  n = 1;
end

s = tf('s');
Wp = (s / (M^(1/n)) + omega)^n / (s + omega * A^(1/n))^n;

end
% vim: ts=2 sw=2 et: