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

@ -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);

@ -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

@ -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');

@ -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);

@ -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

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -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

@ -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

@ -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

@ -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();

@ -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();

@ -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.

@ -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));

@ -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

@ -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