Align the centers of rotation of Ry, Hexa, NASS with the sample

This commit is contained in:
Thomas Dehaeze 2018-10-30 14:37:19 +01:00
parent ef6f4613b1
commit 389fd66ba4
27 changed files with 90 additions and 32 deletions

View File

@ -9,3 +9,7 @@ runSimulation('vc', 'light', 'cl', 'none');
runSimulation('pz', 'light', 'cl', 'none'); runSimulation('pz', 'light', 'cl', 'none');
% runSimulation('vc', 'heavy', 'cl', 'none'); % runSimulation('vc', 'heavy', 'cl', 'none');
% runSimulation('pz', 'heavy', 'cl', 'none'); % runSimulation('pz', 'heavy', 'cl', 'none');
%%
opts_inputs = struct('Dw', true);
initializeInputs(opts_inputs);

View File

@ -9,12 +9,12 @@ initializeSample(struct('mass', 1));
initializeNanoHexapod(struct('actuator', 'lorentz')); initializeNanoHexapod(struct('actuator', 'lorentz'));
K = K_light_vc; %#ok K = K_light_vc; %#ok
save('./mat/controller.mat', 'K'); save('./mat/controllers.mat', 'K');
Gd_cl_light_vc = identifyPlant(); Gd_cl_light_vc = identifyPlant();
initializeNanoHexapod(struct('actuator', 'piezo')); initializeNanoHexapod(struct('actuator', 'piezo'));
K = K_light_pz; %#ok K = K_light_pz; %#ok
save('./mat/controller.mat', 'K'); save('./mat/controllers.mat', 'K');
Gd_cl_light_pz = identifyPlant(); Gd_cl_light_pz = identifyPlant();
%% Closed Loop - Heavy Sample %% Closed Loop - Heavy Sample
@ -22,12 +22,12 @@ initializeSample(struct('mass', 50));
initializeNanoHexapod(struct('actuator', 'lorentz')); initializeNanoHexapod(struct('actuator', 'lorentz'));
K = K_heavy_vc; %#ok K = K_heavy_vc; %#ok
save('./mat/controller.mat', 'K'); save('./mat/controllers.mat', 'K');
G_cl_heavy_vc = identifyPlant(); G_cl_heavy_vc = identifyPlant();
initializeNanoHexapod(struct('actuator', 'piezo')); initializeNanoHexapod(struct('actuator', 'piezo'));
K = K_heavy_pz; K = K_heavy_pz;
save('./mat/controller.mat', 'K'); save('./mat/controllers.mat', 'K');
G_cl_heavy_pz = identifyPlant(); G_cl_heavy_pz = identifyPlant();
%% Save the identified transfer functions %% Save the identified transfer functions

View File

@ -5,13 +5,53 @@ clear; close all; clc;
load('./mat/G.mat', 'G_light_vc', 'G_light_pz', 'G_heavy_vc', 'G_heavy_pz'); load('./mat/G.mat', 'G_light_vc', 'G_light_pz', 'G_heavy_vc', 'G_heavy_pz');
%% %%
fs = 10; s = tf('s');
K_light_vc = generateDiagPidControl(G_light_vc.G_cart, fs); %%
K_light_pz = generateDiagPidControl(G_light_pz.G_cart, fs); % bodeFig({minreal(G_light_vc.G_cart(1, 1))}, struct('phase', true));
K_heavy_vc = generateDiagPidControl(G_heavy_vc.G_cart, fs); %%
K_heavy_pz = generateDiagPidControl(G_heavy_pz.G_cart, fs); % sisotool(minreal(G_light_vc.G_cart(6, 6)))
K_light_vc = tf(zeros(6));
K_light_vc(1, 1) = 3.4802e06*(s+0.6983)*(s+131.6)/((s+5.306e-06)*(s+577.4));
K_light_vc(2, 2) = 5.3292e06*(s+0.6722)*(s+58.23)/((s+3.628e-06)*(s+734.6));
K_light_vc(3, 3) = 2.1727e06*(s+66.94)*(s+3.522)/((s+530.6)*(s+0.0006859));
K_light_vc(4, 4) = 6.4807e06*(s+2.095)*(s+111.1)/((s+0.0001246)*(s+577.4));
K_light_vc(5, 5) = 2.5184e06*(s+5.582)*(s+48.76)/((s+0.01558)*(s+453.8));
K_light_vc(6, 6) = 1.022e06*(s+6.152)*(s+40.15)/((s+0.001945)*(s+589.7));
%%
i = 6;
bodeFig({-G_light_vc.G_plant(i, i)*K_light_vc(i, i)}, struct('phase', true))
%%
% sisotool(minreal(G_light_pz.G_plant(1, 1)))
K_light_pz = tf(zeros(6));
% K_light_pz(1, 1) = 3.4802e06*(s+0.6983)*(s+131.6)/((s+5.306e-06)*(s+577.4));
% K_light_pz(2, 2) = 5.3292e06*(s+0.6722)*(s+58.23)/((s+3.628e-06)*(s+734.6));
% K_light_pz(3, 3) = 2.1727e06*(s+66.94)*(s+3.522)/((s+530.6)*(s+0.0006859));
% K_light_pz(4, 4) = 6.4807e06*(s+2.095)*(s+111.1)/((s+0.0001246)*(s+577.4));
% K_light_pz(5, 5) = 2.5184e06*(s+5.582)*(s+48.76)/((s+0.01558)*(s+453.8));
% K_light_pz(6, 6) = 1.022e06*(s+6.152)*(s+40.15)/((s+0.001945)*(s+589.7));
%%
K_heavy_vc = tf(zeros(6));
K_heavy_pz = tf(zeros(6));
%%
save('./mat/K_fb.mat', 'K_light_vc', 'K_light_pz', 'K_heavy_vc', 'K_heavy_pz');
%% Automatic generation of controllers
% fs = 100;
%
% K_light_vc = generateDiagPidControl(G_light_vc.G_cart, fs);
% K_light_pz = generateDiagPidControl(G_light_pz.G_cart, fs);
%
% K_heavy_vc = generateDiagPidControl(G_heavy_vc.G_cart, fs);
% K_heavy_pz = generateDiagPidControl(G_heavy_pz.G_cart, fs);
%% Save the MIMO control %% Save the MIMO control
save('./mat/K_fb.mat', 'K_light_vc', 'K_light_pz', 'K_heavy_vc', 'K_heavy_pz'); % save('./mat/K_fb.mat', 'K_light_vc', 'K_light_pz', 'K_heavy_vc', 'K_heavy_pz');

View File

@ -58,11 +58,11 @@ mass((T_mass_start+3)/sim_conf.Ts:(T_mass_start+5)/sim_conf.Ts, 1) = mass((T_mas
mass((T_mass_start+3)/sim_conf.Ts:(T_mass_start+5)/sim_conf.Ts, 2) = mass((T_mass_start+2)/sim_conf.Ts, 2)-2*pi*(-10/360)*(time_vector((T_mass_start+3)/sim_conf.Ts:(T_mass_start+5)/sim_conf.Ts)-time_vector((T_mass_start+3)/sim_conf.Ts)); mass((T_mass_start+3)/sim_conf.Ts:(T_mass_start+5)/sim_conf.Ts, 2) = mass((T_mass_start+2)/sim_conf.Ts, 2)-2*pi*(-10/360)*(time_vector((T_mass_start+3)/sim_conf.Ts:(T_mass_start+5)/sim_conf.Ts)-time_vector((T_mass_start+3)/sim_conf.Ts));
opts_inputs = struct(... opts_inputs = struct(...
'ty', ty, ... 'Dy', ty, ...
'ry', ry, ... 'Ry', ry, ...
'rz', rz, ... 'Rz', rz, ...
'u_hexa', u_hexa, ... 'Dh', u_hexa, ...
'mass', mass ... 'Rm', mass ...
); );
initializeInputs(opts_inputs); initializeInputs(opts_inputs);

View File

@ -3,7 +3,7 @@ clear; close all; clc;
%% Initialize simulation configuration %% Initialize simulation configuration
opts_sim = struct(... opts_sim = struct(...
'Tsim', 0.1 ... 'Tsim', 0.001 ...
); );
initializeSimConf(opts_sim); initializeSimConf(opts_sim);
@ -14,14 +14,14 @@ load('./mat/sim_conf.mat', 'sim_conf')
time_vector = 0:sim_conf.Ts:sim_conf.Tsim; time_vector = 0:sim_conf.Ts:sim_conf.Tsim;
% Translation Stage % Translation Stage
Ty = 0.20*ones(length(time_vector), 1); Ty = 0*ones(length(time_vector), 1);
% Tilt Stage % Tilt Stage
Ry = 2*pi*(3/360)*ones(length(time_vector), 1); Ry = 2*pi*(0/360)*ones(length(time_vector), 1);
% Ry = 2*pi*(3/360)*sin(2*pi*time_vector); % Ry = 2*pi*(3/360)*sin(2*pi*time_vector);
% Spindle % Spindle
Rz = 2*pi*3*(time_vector); Rz = 2*pi*0*(time_vector);
% Rz = 2*pi*(190/360)*ones(length(time_vector), 1); % Rz = 2*pi*(190/360)*ones(length(time_vector), 1);
% Micro Hexapod % Micro Hexapod

View File

@ -8,18 +8,20 @@ function [] = initializeExperiment(exp_name, sys_mass)
if strcmp(sys_mass, 'light') if strcmp(sys_mass, 'light')
opts_inputs = struct(... opts_inputs = struct(...
'ground_motion', true, ... 'Dw', true, ...
'rz', 60 ... % rpm 'Rz', 60 ... % rpm
); );
elseif strcpm(sys_mass, 'heavy') elseif strcpm(sys_mass, 'heavy')
opts_inputs = struct(... opts_inputs = struct(...
'ground_motion', true, ... 'Dw', true, ...
'rz', 1 ... % rpm 'Rz', 1 ... % rpm
); );
else else
error('sys_mass should be light or heavy'); error('sys_mass should be light or heavy');
end end
initializeInputs(opts_inputs); initializeInputs(opts_inputs);
elseif else
error('exp_name is only configured for tomography');
end
end end

View File

@ -19,6 +19,9 @@ function [granite] = initializeGranite()
granite.k.z = 1e8; % [N/m] granite.k.z = 1e8; % [N/m]
granite.c.z = 1e4; % [N/(m/s)] granite.c.z = 1e4; % [N/(m/s)]
%% Positioning parameters
granite.sample_pos = 0.8; % Z-offset for the initial position of the sample [m]
%% Save %% Save
save('./mat/stages.mat', 'granite', '-append'); save('./mat/stages.mat', 'granite', '-append');
end end

View File

@ -62,7 +62,7 @@ function [inputs] = initializeInputs(opts_param)
elseif islogical(opts.Rz) && opts.Rz == false elseif islogical(opts.Rz) && opts.Rz == false
Rz = zeros(length(t), 1); Rz = zeros(length(t), 1);
elseif isnumeric(opts.Rz) && length(opts.Rz) == 1 elseif isnumeric(opts.Rz) && length(opts.Rz) == 1
Rz = opts.Rz*(2*pi/360)*ones(length(t), 1); Rz = opts.Rz*(2*pi/60)*t;
else else
Rz = opts.Rz; Rz = opts.Rz;
end end

View File

@ -12,7 +12,8 @@ function [micro_hexapod] = initializeMicroHexapod(opts_param)
%% Stewart Object %% Stewart Object
micro_hexapod = struct(); micro_hexapod = struct();
micro_hexapod.h = 350; % Total height of the platform [mm] micro_hexapod.h = 350; % Total height of the platform [mm]
micro_hexapod.jacobian = 265; % Distance from the top platform to the Jacobian point [mm] % micro_hexapod.jacobian = 269.26; % Distance from the top platform to the Jacobian point [mm]
micro_hexapod.jacobian = 270; % Distance from the top platform to the Jacobian point [mm]
%% Bottom Plate - Mechanical Design %% Bottom Plate - Mechanical Design
BP = struct(); BP = struct();

View File

@ -13,6 +13,7 @@ function [nano_hexapod] = initializeNanoHexapod(opts_param)
nano_hexapod = struct(); nano_hexapod = struct();
nano_hexapod.h = 90; % Total height of the platform [mm] nano_hexapod.h = 90; % Total height of the platform [mm]
nano_hexapod.jacobian = 175; % Point where the Jacobian is computed => Center of rotation [mm] nano_hexapod.jacobian = 175; % Point where the Jacobian is computed => Center of rotation [mm]
% nano_hexapod.jacobian = 174.26; % Point where the Jacobian is computed => Center of rotation [mm]
%% Bottom Plate %% Bottom Plate
BP = struct(); BP = struct();

View File

@ -47,6 +47,9 @@ function [ry] = initializeRy(opts_param)
ry.c.rad = 10*(1/5)*sqrt(ry.k.rad/ry.m); ry.c.rad = 10*(1/5)*sqrt(ry.k.rad/ry.m);
ry.c.rrad = 10*(1/5)*sqrt(ry.k.rrad/ry.m); ry.c.rrad = 10*(1/5)*sqrt(ry.k.rrad/ry.m);
ry.c.tilt = 10*(1/1)*sqrt(ry.k.tilt/ry.m); ry.c.tilt = 10*(1/1)*sqrt(ry.k.tilt/ry.m);
%% Positioning parameters
ry.z_offset = 0.58178; % Z-Offset so that the center of rotation matches the sample center [m]
%% Save %% Save
save('./mat/stages.mat', 'ry', '-append'); save('./mat/stages.mat', 'ry', '-append');

BIN
mat/G.mat

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -7,7 +7,7 @@ function [K] = generateDiagPidControl(G, fs)
%% %%
K = tf(zeros(6)); K = tf(zeros(6));
for i = 1:5 for i = 1:6
input_name = G.InputName(i); input_name = G.InputName(i);
output_name = G.OutputName(i); output_name = G.OutputName(i);
K(i, i) = tf(pidtune(minreal(G(output_name, input_name)), 'PIDF', 2*pi*fs, pid_opts)); K(i, i) = tf(pidtune(minreal(G(output_name, input_name)), 'PIDF', 2*pi*fs, pid_opts));

View File

@ -24,6 +24,7 @@ function [sys] = identifyPlant(opts_param)
io(5) = linio([mdl, '/Dsm'], 1, 'output'); % Displacement of the sample io(5) = linio([mdl, '/Dsm'], 1, 'output'); % Displacement of the sample
io(6) = linio([mdl, '/Fnlm'], 1, 'output'); % Force sensor in NASS's legs io(6) = linio([mdl, '/Fnlm'], 1, 'output'); % Force sensor in NASS's legs
io(7) = linio([mdl, '/Dnlm'], 1, 'output'); % Displacement of NASS's legs io(7) = linio([mdl, '/Dnlm'], 1, 'output'); % Displacement of NASS's legs
io(8) = linio([mdl, '/Es'], 1, 'output'); % Position Error w.r.t. NASS base
%% Run the linearization %% Run the linearization
G = linearize(mdl, io, 0); G = linearize(mdl, io, 0);
@ -33,7 +34,8 @@ function [sys] = identifyPlant(opts_param)
'F1', 'F2', 'F3', 'F4', 'F5', 'F6'}; 'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
G.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz', ... G.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz', ...
'Fm1', 'Fm2', 'Fm3', 'Fm4', 'Fm5', 'Fm6', ... 'Fm1', 'Fm2', 'Fm3', 'Fm4', 'Fm5', 'Fm6', ...
'Dm1', 'Dm2', 'Dm3', 'Dm4', 'Dm5', 'Dm6'}; 'Dm1', 'Dm2', 'Dm3', 'Dm4', 'Dm5', 'Dm6', ...
'Edx', 'Rdy', 'Edz', 'Erx', 'Ery', 'Erz'};
%% Create the sub transfer functions %% Create the sub transfer functions
% From forces applied in the cartesian frame to displacement of the sample in the cartesian frame % From forces applied in the cartesian frame to displacement of the sample in the cartesian frame
@ -46,4 +48,6 @@ function [sys] = identifyPlant(opts_param)
sys.G_iff = minreal(G({'Fm1', 'Fm2', 'Fm3', 'Fm4', 'Fm5', 'Fm6'}, {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'})); sys.G_iff = minreal(G({'Fm1', 'Fm2', 'Fm3', 'Fm4', 'Fm5', 'Fm6'}, {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'}));
% From forces applied on NASS's legs to displacement of each leg % From forces applied on NASS's legs to displacement of each leg
sys.G_dleg = minreal(G({'Dm1', 'Dm2', 'Dm3', 'Dm4', 'Dm5', 'Dm6'}, {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'})); sys.G_dleg = minreal(G({'Dm1', 'Dm2', 'Dm3', 'Dm4', 'Dm5', 'Dm6'}, {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'}));
% From forces applied on NASS's legs to displacement of each leg
sys.G_plant = minreal(G({'Edx', 'Rdy', 'Edz', 'Erx', 'Ery', 'Erz'}, {'Fnx', 'Fny', 'Fnz', 'Mnx', 'Mny', 'Mnz'}));
end end

View File

@ -3,14 +3,14 @@ function [] = runSimulation(sys_name, sys_mass, ctrl_type, act_damp)
if strcmp(ctrl_type, 'cl') && strcmp(act_damp, 'none') if strcmp(ctrl_type, 'cl') && strcmp(act_damp, 'none')
K_obj = load('./mat/K_fb.mat'); K_obj = load('./mat/K_fb.mat');
K = K_obj.(sprintf('K_%s_%s', sys_mass, sys_name)); %#ok K = K_obj.(sprintf('K_%s_%s', sys_mass, sys_name)); %#ok
save('./mat/controller.mat', 'K'); save('./mat/controllers.mat', 'K');
elseif strcmp(ctrl_type, 'cl') && strcmp(act_damp, 'iff') elseif strcmp(ctrl_type, 'cl') && strcmp(act_damp, 'iff')
K_obj = load('./mat/K_fb_iff.mat'); K_obj = load('./mat/K_fb_iff.mat');
K = K_obj.(sprintf('K_%s_%s_iff', sys_mass, sys_name)); %#ok K = K_obj.(sprintf('K_%s_%s_iff', sys_mass, sys_name)); %#ok
save('./mat/controller.mat', 'K'); save('./mat/controllers.mat', 'K');
elseif strcmp(ctrl_type, 'ol') elseif strcmp(ctrl_type, 'ol')
K = tf(zeros(6)); %#ok K = tf(zeros(6)); %#ok
save('./mat/controller.mat', 'K'); save('./mat/controllers.mat', 'K');
else else
error('ctrl_type should be cl or ol'); error('ctrl_type should be cl or ol');
end end
@ -46,7 +46,7 @@ function [] = runSimulation(sys_name, sys_mass, ctrl_type, act_damp)
sim('sim_nano_station_ctrl.slx'); sim('sim_nano_station_ctrl.slx');
%% Split the Dsample matrix into vectors %% Split the Dsample matrix into vectors
[Dx, Dy, Dz, Rx, Ry, Rz] = matSplit(Dsample.Data, 1); %#ok [Dx, Dy, Dz, Rx, Ry, Rz] = matSplit(Es.Data, 1); %#ok
time = Dsample.Time; %#ok time = Dsample.Time; %#ok
%% Save the result %% Save the result