-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtestMyDesign_Nonlinear.m
More file actions
199 lines (149 loc) · 5.38 KB
/
testMyDesign_Nonlinear.m
File metadata and controls
199 lines (149 loc) · 5.38 KB
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% This file will run a complete simulation of the nonlinear crane model
% with the provided controller/state estimator/target generator in the file
% `FunctionTemplate.m`.
%
% Author: Ian McInerney
% Revision: 2021.2
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear variables
close all
% The percentage perturbation to perform on each crane model parameter
% The default is 10%
perturbSize = 0.1;
% The part of the core coursework that is being worked on
partNum = 6;
% Introduce a second ellipse to the course for part 2
useSecondEllipse = 0;
%% Load the parameters for the Simulation model
load('Crane_NominalParameters.mat');
%% Create the shape to test on
testCourse = defaultCourse( 0, partNum );
% Only for part 2 - add a second ellipse
if( partNum == 2 && useSecondEllipse == 1 )
% Define the new ellipse
ellipse.a = 0.3;
ellipse.b = 0.17;
ellipse.xc = 0.25;
ellipse.yc = 0.35;
testCourse.shape.constraints.ellipses{2} = ellipse;
% Add another index to the penalties array for the new ellipse
testCourse.penalties = [ testCourse.penalties, -1];
end
%% Perturb the parameters
% Extract the crane parameters
% The following parameters could all be perturbed:
% Tx friction coefficient in x direction
% Ty friction coefficient in y direction
% Tl friction coefficient in z direction
% Vx force coefficient in x direction
% Vy force coefficient in y direction
% Vl force coefficient in z direction
% MR mass of rail
% M mass of cart
% m mass of pendulum
% r length
rng(15012);
randPerturb = @() ( ( rand()-0.5 ) * perturbSize ) + 1;
perturbFun = @(x) randPerturb() * x;
craneParams.m = testCourse.perturb.m * m;
craneParams.M = testCourse.perturb.M * M;
craneParams.MR = testCourse.perturb.MR * MR;
craneParams.r = testCourse.perturb.r * r;
craneParams.Tl = testCourse.perturb.Tl * Tl;
craneParams.Tx = testCourse.perturb.Tx * Tx;
craneParams.Ty = testCourse.perturb.Ty * Ty;
craneParams.Vl = testCourse.perturb.Vl * Vl;
craneParams.Vx = testCourse.perturb.Vx * Vx;
craneParams.Vy = testCourse.perturb.Vy * Vy;
%% Extract the student functions
extractFunctions( ['FunctionTemplate.m'], 1 );
%% Declare other simulation parameters
tstep = 0.01; % Step size for simulation. Has to be less than minimum allowed Ts
Fs_default = 20; % sampling frequency
Ts_default = 1/Fs_default; % sampling period
x0 = [ testCourse.shape.start(1,1); % x of cart
0 % x dot of cart
testCourse.shape.start(1,2); % y of cart
0; % y dot of cart
0; % theta of pendulum
0; % theta dot of pendulum
0; % phi of pendulum
0; % phi dot of pendulum
craneParams.r; % r of pendulum (length)
0; % r dot of pendulum
0]; % Internal computation variable
%% Call the setup function for the student
tic;
param = mySetup( testCourse.shape );
setupTime = toc;
tStart = tic; % pair 2: tic
fprintf('Setup time: %fs\n', setupTime );
%% Extract the user-defined sampling time, if there is one
if( isfield( param, 'Ts' ) )
Ts = param.Ts;
Fs = 1/Ts;
else
Ts = Ts_default;
Fs = Fs_default;
end
if( ( Ts < 0.01 ) || ( Ts > 1 ) )
error( 'Ts must be in the interval [0.01, 1]' )
end
%% Set the simulation time
T = 20;
%% Setup the simulation
% create waiting bar
hw = waitbar( 0,'Please wait...' );
warning( 'on' );
% Initial conditions
x = x0';
y = x0(1:8,:);
u = [0; 0];
ind = 1;
% Setup variables to hold the results
time = 0;
inputs = [u; 0]';
states = x0';
% Variable to hold optimization time
numSamples = T/Ts;
allContTime = [0];
% ODE Options
odeOpts = odeset( 'RelTol', 1e-3, 'MaxStep', 0.01 );
%% Iterate for the simulation time
for t=0:Ts:T
ind = ind+1;
waitbar( t/T, hw, 'Please wait...' );
tic;
% Call the state estimator
x_hat = myStateEstimator( u(1:2,:), y, param );
% Call the target generator
ref = myTargetGenerator( x_hat, param );
% Call the controller function
u = myMPController( ref, x_hat, param );
u = [u; 0]; % we won't use the third input, which is in the Z axis (i.e. the third input increases/decreases the length of the pendulum).
% Saturate the inputs to [-1, 1] for the simulation
usat = min( max( u, -1 ), 1 );
contTime = toc;
% Setup the simulation model
mod = @(t, state) crane_nl_model( usat, state, craneParams );
% Simulate
[tt, x] = ode23t( mod, [t:tstep:t + Ts], x(end,:), odeOpts );
% The output is simply all the states except the Z axis portion
y = x(end,1:8)';
% Keep the state variables around for analysis
% We ignore the first entry since it is the same as the entry from the
% last loop
time = [time; tt(2:end, end)];
states = [states; x(2:end, :)];
inputs = [inputs; u'.*ones( size( tt, 1 ) - 1, 1 ) ];
% Save the computation time for analysis
allContTime = [allContTime; contTime.*ones( size( tt, 1 ) - 1, 1 )];
end
close(hw);
tEnd = toc(tStart) % pair 2: toc
%% Visualize the Course
[~, ~, ~, text] = analyzeCourse( [], time, states, inputs, allContTime, testCourse, r, 1 );
fprintf(text)