diff --git a/docs/flexible_joints_study.html b/docs/flexible_joints_study.html index 2e773ce..3eccd2c 100644 --- a/docs/flexible_joints_study.html +++ b/docs/flexible_joints_study.html @@ -1,10 +1,9 @@ -
- +Let’s initialize all the stages with default parameters. @@ -128,8 +134,8 @@ initializeMirror(); Let’s consider the heaviest mass which should we the most problematic with it comes to the flexible joints.
initializeSample('mass', 50, 'freq', 200*ones(6,1)); -initializeReferences('Rz_type', 'rotating-not-filtered', 'Rz_period', 60); +initializeSample('mass', 50, 'freq', 200*ones(6,1)); +initializeReferences('Rz_type', 'rotating-not-filtered', 'Rz_period', 60);
Kf_M = 15*ones(6,1); -Kf_F = 15*ones(6,1); -Kt_M = 20*ones(6,1); -Kt_F = 20*ones(6,1); +Kf_M = 15*ones(6,1); +Kf_F = 15*ones(6,1); +Kt_M = 20*ones(6,1); +Kt_F = 20*ones(6,1);
k_opt = 1e5; % [N/m] -c_opt = 2e2; % [N/(m/s)] +k_opt = 1e5; % [N/m] +c_opt = 2e2; % [N/(m/s)]
We identify the dynamics from actuators force \(\tau_i\) to relative motion sensors \(d\mathcal{L}_i\) with and without considering the flexible joint stiffness. @@ -189,8 +195,8 @@ It is shown that the adding of stiffness for the flexible joints does increase a
Let’s now identify the dynamics from \(\bm{\tau}^\prime\) to \(\bm{\epsilon}_{\mathcal{X}_n}\) (for the primary controller designed in the frame of the legs). @@ -210,10 +216,10 @@ The plant dynamics is not found to be changing significantly.
Considering realistic flexible joint bending stiffness for the nano-hexapod does not seems to impose any limitation on the DVF control nor on the primary control.
@@ -239,7 +245,7 @@ This will help to determine the requirements on the joint’s stiffness. Let’s consider the following bending stiffness of the flexible joints:Ks = [1, 5, 10, 50, 100]; % [Nm/rad]
+Ks = [1, 5, 10, 50, 100]; % [Nm/rad]
The dynamics from the actuators to the relative displacement sensor in each leg is identified and shown in Figure 3. @@ -279,8 +285,8 @@ It is shown that the bending stiffness of the flexible joints does indeed change
The dynamics from \(\bm{\tau}^\prime\) to \(\bm{\epsilon}_{\mathcal{X}_n}\) (for the primary controller designed in the frame of the legs) is shown in Figure 5. @@ -299,10 +305,10 @@ It is shown that the bending stiffness of the flexible joints have very little i
The bending stiffness of the flexible joint does not significantly change the dynamics.
@@ -333,16 +339,16 @@ We choose realistic values of the axial stiffness of the joints:Kz_F = 60e6*ones(6,1); % [N/m] -Kz_M = 60e6*ones(6,1); % [N/m] -Cz_F = 1*ones(6,1); % [N/(m/s)] -Cz_M = 1*ones(6,1); % [N/(m/s)] +Ka_F = 60e6*ones(6,1); % [N/m] +Ka_M = 60e6*ones(6,1); % [N/m] +Ca_F = 1*ones(6,1); % [N/(m/s)] +Ca_M = 1*ones(6,1); % [N/(m/s)]
Let’s initialize all the stages with default parameters. @@ -363,15 +369,15 @@ initializeMirror(); Let’s consider the heaviest mass which should we the most problematic with it comes to the flexible joints.
initializeSample('mass', 50, 'freq', 200*ones(6,1)); -initializeReferences('Rz_type', 'rotating-not-filtered', 'Rz_period', 60); +initializeSample('mass', 50, 'freq', 200*ones(6,1)); +initializeReferences('Rz_type', 'rotating-not-filtered', 'Rz_period', 60);
The dynamics from actuators force \(\tau_i\) to relative motion sensors \(d\mathcal{L}_i\) with and without considering the flexible joint stiffness are identified. @@ -390,11 +396,11 @@ The obtained dynamics are shown in Figure 6.
Kdvf = 5e3*s/(1+s/2/pi/1e3)*eye(6); +Kdvf = 5e3*s/(1+s/2/pi/1e3)*eye(6);
For the realistic value of the flexible joint axial stiffness, the dynamics is not much impact, and this should not be a problem for control.
@@ -439,7 +445,7 @@ We wish now to see what is the impact of the axial stiffness of the flexi Let’s consider the following values for the axial stiffness:Kzs = [1e4, 1e5, 1e6, 1e7, 1e8, 1e9]; % [N/m]
+Kas = [1e4, 1e5, 1e6, 1e7, 1e8, 1e9]; % [N/m]
The dynamics from the actuators to the relative displacement sensor in each leg is identified and shown in Figure 8. @@ -491,8 +497,8 @@ It can be seen that very little active damping can be achieve for axial stiffnes
The dynamics from \(\bm{\tau}^\prime\) to \(\bm{\epsilon}_{\mathcal{X}_n}\) (for the primary controller designed in the frame of the legs) is shown in Figure 11. @@ -508,10 +514,10 @@ The dynamics from \(\bm{\tau}^\prime\) to \(\bm{\epsilon}_{\mathcal{X}_n}\) (for
The axial stiffness of the flexible joints should be maximized.
@@ -533,14 +539,14 @@ We may interpolate the results and say that the axial joint stiffness should beIn this study we considered the bending, torsional and axial stiffnesses of the flexible joints used for the nano-hexapod.
@@ -575,10 +581,80 @@ As there is generally a trade-off between bending stiffness and axial stiffness,+Let’s initialize all the stages with default parameters. +
+initializeGround(); +initializeGranite(); +initializeTy(); +initializeRy(); +initializeRz(); +initializeMicroHexapod(); +initializeAxisc('type', 'none'); +initializeMirror('type', 'none'); +initializeMirror(); ++
+Let’s consider the heaviest mass which should we the most problematic with it comes to the flexible joints. +
+initializeSample('mass', 50, 'freq', 200*ones(6,1)); +initializeReferences('Rz_type', 'rotating-not-filtered', 'Rz_period', 60); ++
flex_joint = load('./mat/flexor_025.mat', 'int_xyz', 'int_i', 'n_xyz', 'n_i', 'nodes', 'M', 'K'); +apa = load('./mat/APA300ML_simplified_model.mat'); ++
initializeNanoHexapod('actuator', 'amplified', ... + 'ke', apa.ke, 'ka', apa.ka, 'k1', apa.k1, 'c1', apa.c1, 'F_gain', apa.F_gain, ... + 'type_M', 'spherical_3dof', ... + 'Kr_M', flex_joint.K(1,1)*ones(6,1), ... + 'Ka_M', flex_joint.K(3,3)*ones(6,1), ... + 'Kf_M', flex_joint.K(4,4)*ones(6,1), ... + 'Kt_M', flex_joint.K(6,6)*ones(6,1), ... + 'type_F', 'spherical_3dof', ... + 'Kr_F', flex_joint.K(1,1)*ones(6,1), ... + 'Ka_F', flex_joint.K(3,3)*ones(6,1), ... + 'Kf_F', flex_joint.K(4,4)*ones(6,1), ... + 'Kt_F', flex_joint.K(6,6)*ones(6,1)); ++
initializeNanoHexapod(); ++
Created: 2020-05-05 mar. 11:50
+Created: 2020-11-03 mar. 09:45
function [] = initializeSimscapeConfiguration(args) +function [] = initializeSimscapeConfiguration(args)
arguments - args.gravity logical {mustBeNumericOrLogical} = true -end + args.gravity logical {mustBeNumericOrLogical} = true +end
conf_simscape = struct();@@ -286,25 +286,25 @@ end
if args.gravity +if args.gravity conf_simscape.type = 1; -else +else conf_simscape.type = 2; -end +end
save('./mat/conf_simscape.mat', 'conf_simscape'); +save('./mat/conf_simscape.mat', 'conf_simscape');
function [] = initializeLoggingConfiguration(args) +function [] = initializeLoggingConfiguration(args)
arguments - args.log char {mustBeMember(args.log,{'none', 'all', 'forces'})} = 'none' - args.Ts (1,1) double {mustBeNumeric, mustBePositive} = 1e-3 -end + args.log char {mustBeMember(args.log,{'none', 'all', 'forces'})} = 'none' + args.Ts (1,1) double {mustBeNumeric, mustBePositive} = 1e-3 +end
conf_log = struct();@@ -352,18 +352,18 @@ end
switch args.log - case 'none' +switch args.log + case 'none' conf_log.type = 0; - case 'all' + case 'all' conf_log.type = 1; - case 'forces' + case 'forces' conf_log.type = 2; -end +end
save('./mat/conf_log.mat', 'conf_log'); +save('./mat/conf_log.mat', 'conf_log');
The model of the Ground is composed of:
@@ -425,32 +425,32 @@ The model of the Ground is composed of:function [ground] = initializeGround(args) +function [ground] = initializeGround(args)
arguments - args.type char {mustBeMember(args.type,{'none', 'rigid'})} = 'rigid' - args.rot_point (3,1) double {mustBeNumeric} = zeros(3,1) % Rotation point for the ground motion [m] -end + args.type char {mustBeMember(args.type,{'none', 'rigid'})} = 'rigid' + args.rot_point (3,1) double {mustBeNumeric} = zeros(3,1) % Rotation point for the ground motion [m] +end
First, we initialize the granite
structure.
granite
structure.
switch args.type - case 'none' +switch args.type + case 'none' ground.type = 0; - case 'rigid' + case 'rigid' ground.type = 1; -end +end
ground.shape = [2, 2, 0.5]; % [m] -ground.density = 2800; % [kg/m3] +ground.shape = [2, 2, 0.5]; % [m] +ground.density = 2800; % [kg/m3]
The ground
structure is saved.
save('./mat/stages.mat', 'ground', '-append'); +save('./mat/stages.mat', 'ground', '-append');
ground
structure is saved.
The Simscape model of the granite is composed of:
@@ -553,38 +553,39 @@ The outputsample_pos
corresponds to the impact point of the X-ray.
function [granite] = initializeGranite(args) +function [granite] = initializeGranite(args)
arguments - args.type char {mustBeMember(args.type,{'rigid', 'flexible', 'none', 'modal-analysis', 'init'})} = 'flexible' - args.Foffset logical {mustBeNumericOrLogical} = false - args.density (1,1) double {mustBeNumeric, mustBeNonnegative} = 2800 % Density [kg/m3] - args.K (3,1) double {mustBeNumeric, mustBeNonnegative} = [4e9; 3e8; 8e8] % [N/m] - args.C (3,1) double {mustBeNumeric, mustBeNonnegative} = [4.0e5; 1.1e5; 9.0e5] % [N/(m/s)] - args.x0 (1,1) double {mustBeNumeric} = 0 % Rest position of the Joint in the X direction [m] - args.y0 (1,1) double {mustBeNumeric} = 0 % Rest position of the Joint in the Y direction [m] - args.z0 (1,1) double {mustBeNumeric} = 0 % Rest position of the Joint in the Z direction [m] -end + args.type char {mustBeMember(args.type,{'rigid', 'flexible', 'none', 'modal-analysis', 'init'})} = 'flexible' + args.Foffset logical {mustBeNumericOrLogical} = false + args.density (1,1) double {mustBeNumeric, mustBeNonnegative} = 2800 % Density [kg/m3] + args.K (3,1) double {mustBeNumeric, mustBeNonnegative} = [4e9; 3e8; 8e8] % [N/m] + args.C (3,1) double {mustBeNumeric, mustBeNonnegative} = [4.0e5; 1.1e5; 9.0e5] % [N/(m/s)] + args.x0 (1,1) double {mustBeNumeric} = 0 % Rest position of the Joint in the X direction [m] + args.y0 (1,1) double {mustBeNumeric} = 0 % Rest position of the Joint in the Y direction [m] + args.z0 (1,1) double {mustBeNumeric} = 0 % Rest position of the Joint in the Z direction [m] + args.sample_pos (1,1) double {mustBeNumeric} = 0.8 % Height of the measurment point [m] +end
First, we initialize the granite
structure.
granite
structure.
switch args.type - case 'none' +switch args.type + case 'none' granite.type = 0; - case 'rigid' + case 'rigid' granite.type = 1; - case 'flexible' + case 'flexible' granite.type = 2; - case 'modal-analysis' + case 'modal-analysis' granite.type = 3; - case 'init' + case 'init' granite.type = 4; -end +end
Properties of the Material and link to the geometry of the granite.
granite.density = args.density; % [kg/m3] -granite.STEP = './STEPS/granite/granite.STEP'; +granite.density = args.density; % [kg/m3] +granite.STEP = './STEPS/granite/granite.STEP';
granite.sample_pos = 0.8; % [m]
+granite.sample_pos = args.sample_pos; % [m]
granite.K = args.K; % [N/m] -granite.C = args.C; % [N/(m/s)] +granite.K = args.K; % [N/m] +granite.C = args.C; % [N/(m/s)]
if args.Foffset && ~strcmp(args.type, 'none') && ~strcmp(args.type, 'rigid') && ~strcmp(args.type, 'init') - load('mat/Foffset.mat', 'Fgm'); - granite.Deq = -Fgm'./granite.K; -else +if args.Foffset && ~strcmp(args.type, 'none') && ~strcmp(args.type, 'rigid') && ~strcmp(args.type, 'init') + load('mat/Foffset.mat', 'Fgm'); + granite.Deq = -Fgm'./granite.K; +else granite.Deq = zeros(6,1); -end +end
The granite
structure is saved.
save('./mat/stages.mat', 'granite', '-append'); +save('./mat/stages.mat', 'granite', '-append');
The Simscape model of the Translation stage consist of:
@@ -718,32 +719,32 @@ It is used to impose the motion in the Y directionfunction [ty] = initializeTy(args) +function [ty] = initializeTy(args)
arguments - args.type char {mustBeMember(args.type,{'none', 'rigid', 'flexible', 'modal-analysis', 'init'})} = 'flexible' - args.Foffset logical {mustBeNumericOrLogical} = false -end + args.type char {mustBeMember(args.type,{'none', 'rigid', 'flexible', 'modal-analysis', 'init'})} = 'flexible' + args.Foffset logical {mustBeNumericOrLogical} = false +end
First, we initialize the ty
structure.
ty
structure.
switch args.type - case 'none' +switch args.type + case 'none' ty.type = 0; - case 'rigid' + case 'rigid' ty.type = 1; - case 'flexible' + case 'flexible' ty.type = 2; - case 'modal-analysis' + case 'modal-analysis' ty.type = 3; - case 'init' + case 'init' ty.type = 4; -end +end
Define the density of the materials as well as the geometry (STEP files).
% Ty Granite frame -ty.granite_frame.density = 7800; % [kg/m3] => 43kg -ty.granite_frame.STEP = './STEPS/Ty/Ty_Granite_Frame.STEP'; +% Ty Granite frame +ty.granite_frame.density = 7800; % [kg/m3] => 43kg +ty.granite_frame.STEP = './STEPS/Ty/Ty_Granite_Frame.STEP'; -% Guide Translation Ty -ty.guide.density = 7800; % [kg/m3] => 76kg -ty.guide.STEP = './STEPS/ty/Ty_Guide.STEP'; +% Guide Translation Ty +ty.guide.density = 7800; % [kg/m3] => 76kg +ty.guide.STEP = './STEPS/ty/Ty_Guide.STEP'; -% Ty - Guide_Translation12 -ty.guide12.density = 7800; % [kg/m3] -ty.guide12.STEP = './STEPS/Ty/Ty_Guide_12.STEP'; +% Ty - Guide_Translation12 +ty.guide12.density = 7800; % [kg/m3] +ty.guide12.STEP = './STEPS/Ty/Ty_Guide_12.STEP'; -% Ty - Guide_Translation11 -ty.guide11.density = 7800; % [kg/m3] -ty.guide11.STEP = './STEPS/ty/Ty_Guide_11.STEP'; +% Ty - Guide_Translation11 +ty.guide11.density = 7800; % [kg/m3] +ty.guide11.STEP = './STEPS/ty/Ty_Guide_11.STEP'; -% Ty - Guide_Translation22 -ty.guide22.density = 7800; % [kg/m3] -ty.guide22.STEP = './STEPS/ty/Ty_Guide_22.STEP'; +% Ty - Guide_Translation22 +ty.guide22.density = 7800; % [kg/m3] +ty.guide22.STEP = './STEPS/ty/Ty_Guide_22.STEP'; -% Ty - Guide_Translation21 -ty.guide21.density = 7800; % [kg/m3] -ty.guide21.STEP = './STEPS/Ty/Ty_Guide_21.STEP'; +% Ty - Guide_Translation21 +ty.guide21.density = 7800; % [kg/m3] +ty.guide21.STEP = './STEPS/Ty/Ty_Guide_21.STEP'; -% Ty - Plateau translation -ty.frame.density = 7800; % [kg/m3] -ty.frame.STEP = './STEPS/ty/Ty_Stage.STEP'; +% Ty - Plateau translation +ty.frame.density = 7800; % [kg/m3] +ty.frame.STEP = './STEPS/ty/Ty_Stage.STEP'; -% Ty Stator Part -ty.stator.density = 5400; % [kg/m3] -ty.stator.STEP = './STEPS/ty/Ty_Motor_Stator.STEP'; +% Ty Stator Part +ty.stator.density = 5400; % [kg/m3] +ty.stator.STEP = './STEPS/ty/Ty_Motor_Stator.STEP'; -% Ty Rotor Part -ty.rotor.density = 5400; % [kg/m3] -ty.rotor.STEP = './STEPS/ty/Ty_Motor_Rotor.STEP'; +% Ty Rotor Part +ty.rotor.density = 5400; % [kg/m3] +ty.rotor.STEP = './STEPS/ty/Ty_Motor_Rotor.STEP';
ty.K = [2e8; 1e8; 2e8; 6e7; 9e7; 6e7]; % [N/m, N*m/rad] -ty.C = [8e4; 5e4; 8e4; 2e4; 3e4; 2e4]; % [N/(m/s), N*m/(rad/s)] +ty.K = [2e8; 1e8; 2e8; 6e7; 9e7; 6e7]; % [N/m, N*m/rad] +ty.C = [8e4; 5e4; 8e4; 2e4; 3e4; 2e4]; % [N/(m/s), N*m/(rad/s)]
if args.Foffset && ~strcmp(args.type, 'none') && ~strcmp(args.type, 'rigid') && ~strcmp(args.type, 'init') - load('mat/Foffset.mat', 'Ftym'); - ty.Deq = -Ftym'./ty.K; -else +if args.Foffset && ~strcmp(args.type, 'none') && ~strcmp(args.type, 'rigid') && ~strcmp(args.type, 'init') + load('mat/Foffset.mat', 'Ftym'); + ty.Deq = -Ftym'./ty.K; +else ty.Deq = zeros(6,1); -end +end
The ty
structure is saved.
save('./mat/stages.mat', 'ty', '-append'); +save('./mat/stages.mat', 'ty', '-append');
The Simscape model of the Tilt stage is composed of:
@@ -902,33 +903,33 @@ The Ry motion is imposed by the input.function [ry] = initializeRy(args) +function [ry] = initializeRy(args)
arguments - args.type char {mustBeMember(args.type,{'none', 'rigid', 'flexible', 'modal-analysis', 'init'})} = 'flexible' - args.Foffset logical {mustBeNumericOrLogical} = false + args.type char {mustBeMember(args.type,{'none', 'rigid', 'flexible', 'modal-analysis', 'init'})} = 'flexible' + args.Foffset logical {mustBeNumericOrLogical} = false args.Ry_init (1,1) double {mustBeNumeric} = 0 -end +end
First, we initialize the ry
structure.
ry
structure.
switch args.type - case 'none' +switch args.type + case 'none' ry.type = 0; - case 'rigid' + case 'rigid' ry.type = 1; - case 'flexible' + case 'flexible' ry.type = 2; - case 'modal-analysis' + case 'modal-analysis' ry.type = 3; - case 'init' + case 'init' ry.type = 4; -end +end
Properties of the Material and link to the geometry of the Tilt stage.
% Ry - Guide for the tilt stage -ry.guide.density = 7800; % [kg/m3] -ry.guide.STEP = './STEPS/ry/Tilt_Guide.STEP'; +% Ry - Guide for the tilt stage +ry.guide.density = 7800; % [kg/m3] +ry.guide.STEP = './STEPS/ry/Tilt_Guide.STEP'; -% Ry - Rotor of the motor -ry.rotor.density = 2400; % [kg/m3] -ry.rotor.STEP = './STEPS/ry/Tilt_Motor_Axis.STEP'; +% Ry - Rotor of the motor +ry.rotor.density = 2400; % [kg/m3] +ry.rotor.STEP = './STEPS/ry/Tilt_Motor_Axis.STEP'; -% Ry - Motor -ry.motor.density = 3200; % [kg/m3] -ry.motor.STEP = './STEPS/ry/Tilt_Motor.STEP'; +% Ry - Motor +ry.motor.density = 3200; % [kg/m3] +ry.motor.STEP = './STEPS/ry/Tilt_Motor.STEP'; -% Ry - Plateau Tilt -ry.stage.density = 7800; % [kg/m3] -ry.stage.STEP = './STEPS/ry/Tilt_Stage.STEP'; +% Ry - Plateau Tilt +ry.stage.density = 7800; % [kg/m3] +ry.stage.STEP = './STEPS/ry/Tilt_Stage.STEP';
ry.z_offset = 0.58178; % [m]
+ry.z_offset = 0.58178; % [m]
ry.Ry_init = args.Ry_init; % [rad]
+ry.Ry_init = args.Ry_init; % [rad]
ry.K = [3.8e8; 4e8; 3.8e8; 1.2e8; 6e4; 1.2e8]; ry.C = [1e5; 1e5; 1e5; 3e4; 1e3; 3e4]; @@ -1012,46 +1013,46 @@ ry.C = [1e5; 1e5; 1e5; 3e4; 1e3; 3e4];
if args.Foffset && ~strcmp(args.type, 'none') && ~strcmp(args.type, 'rigid') && ~strcmp(args.type, 'init') - load('mat/Foffset.mat', 'Fym'); - ry.Deq = -Fym'./ry.K; -else +if args.Foffset && ~strcmp(args.type, 'none') && ~strcmp(args.type, 'rigid') && ~strcmp(args.type, 'init') + load('mat/Foffset.mat', 'Fym'); + ry.Deq = -Fym'./ry.K; +else ry.Deq = zeros(6,1); -end +end
The ry
structure is saved.
save('./mat/stages.mat', 'ry', '-append'); +save('./mat/stages.mat', 'ry', '-append');
The Simscape model of the Spindle is composed of:
@@ -1077,32 +1078,32 @@ The Simscape model of the Spindle is composed of:function [rz] = initializeRz(args) +function [rz] = initializeRz(args)
arguments - args.type char {mustBeMember(args.type,{'none', 'rigid', 'flexible', 'modal-analysis', 'init'})} = 'flexible' - args.Foffset logical {mustBeNumericOrLogical} = false -end + args.type char {mustBeMember(args.type,{'none', 'rigid', 'flexible', 'modal-analysis', 'init'})} = 'flexible' + args.Foffset logical {mustBeNumericOrLogical} = false +end
First, we initialize the rz
structure.
rz
structure.
switch args.type - case 'none' +switch args.type + case 'none' rz.type = 0; - case 'rigid' + case 'rigid' rz.type = 1; - case 'flexible' + case 'flexible' rz.type = 2; - case 'modal-analysis' + case 'modal-analysis' rz.type = 3; - case 'init' + case 'init' rz.type = 4; -end +end
Properties of the Material and link to the geometry of the spindle.
% Spindle - Slip Ring -rz.slipring.density = 7800; % [kg/m3] -rz.slipring.STEP = './STEPS/rz/Spindle_Slip_Ring.STEP'; +% Spindle - Slip Ring +rz.slipring.density = 7800; % [kg/m3] +rz.slipring.STEP = './STEPS/rz/Spindle_Slip_Ring.STEP'; -% Spindle - Rotor -rz.rotor.density = 7800; % [kg/m3] -rz.rotor.STEP = './STEPS/rz/Spindle_Rotor.STEP'; +% Spindle - Rotor +rz.rotor.density = 7800; % [kg/m3] +rz.rotor.STEP = './STEPS/rz/Spindle_Rotor.STEP'; -% Spindle - Stator -rz.stator.density = 7800; % [kg/m3] -rz.stator.STEP = './STEPS/rz/Spindle_Stator.STEP'; +% Spindle - Stator +rz.stator.density = 7800; % [kg/m3] +rz.stator.STEP = './STEPS/rz/Spindle_Stator.STEP';
rz.K = [7e8; 7e8; 2e9; 1e7; 1e7; 1e7]; rz.C = [4e4; 4e4; 7e4; 1e4; 1e4; 1e4]; @@ -1168,46 +1169,46 @@ rz.C = [4e4; 4e4; 7e4; 1e4; 1e4; 1e4];
if args.Foffset && ~strcmp(args.type, 'none') && ~strcmp(args.type, 'rigid') && ~strcmp(args.type, 'init') - load('mat/Foffset.mat', 'Fzm'); - rz.Deq = -Fzm'./rz.K; -else +if args.Foffset && ~strcmp(args.type, 'none') && ~strcmp(args.type, 'rigid') && ~strcmp(args.type, 'init') + load('mat/Foffset.mat', 'Fzm'); + rz.Deq = -Fzm'./rz.K; +else rz.Deq = zeros(6,1); -end +end
The rz
structure is saved.
save('./mat/stages.mat', 'rz', '-append'); +save('./mat/stages.mat', 'rz', '-append');
@@ -1224,77 +1225,77 @@ The rz
structure is saved.
function [micro_hexapod] = initializeMicroHexapod(args) +function [micro_hexapod] = initializeMicroHexapod(args)
arguments - args.type char {mustBeMember(args.type,{'none', 'rigid', 'flexible', 'modal-analysis', 'init', 'compliance'})} = 'flexible' - % initializeFramesPositions - args.H (1,1) double {mustBeNumeric, mustBePositive} = 350e-3 - args.MO_B (1,1) double {mustBeNumeric} = 270e-3 - % generateGeneralConfiguration - args.FH (1,1) double {mustBeNumeric, mustBePositive} = 50e-3 - args.FR (1,1) double {mustBeNumeric, mustBePositive} = 175.5e-3 - args.FTh (6,1) double {mustBeNumeric} = [-10, 10, 120-10, 120+10, 240-10, 240+10]*(pi/180) - args.MH (1,1) double {mustBeNumeric, mustBePositive} = 45e-3 - args.MR (1,1) double {mustBeNumeric, mustBePositive} = 118e-3 - args.MTh (6,1) double {mustBeNumeric} = [-60+10, 60-10, 60+10, 180-10, 180+10, -60-10]*(pi/180) - % initializeStrutDynamics - args.Ki (6,1) double {mustBeNumeric, mustBeNonnegative} = 2e7*ones(6,1) - args.Ci (6,1) double {mustBeNumeric, mustBeNonnegative} = 1.4e3*ones(6,1) - % initializeCylindricalPlatforms + args.type char {mustBeMember(args.type,{'none', 'rigid', 'flexible', 'modal-analysis', 'init', 'compliance'})} = 'flexible' + % initializeFramesPositions + args.H (1,1) double {mustBeNumeric, mustBePositive} = 350e-3 + args.MO_B (1,1) double {mustBeNumeric} = 270e-3 + % generateGeneralConfiguration + args.FH (1,1) double {mustBeNumeric, mustBePositive} = 50e-3 + args.FR (1,1) double {mustBeNumeric, mustBePositive} = 175.5e-3 + args.FTh (6,1) double {mustBeNumeric} = [-10, 10, 120-10, 120+10, 240-10, 240+10]*(pi/180) + args.MH (1,1) double {mustBeNumeric, mustBePositive} = 45e-3 + args.MR (1,1) double {mustBeNumeric, mustBePositive} = 118e-3 + args.MTh (6,1) double {mustBeNumeric} = [-60+10, 60-10, 60+10, 180-10, 180+10, -60-10]*(pi/180) + % initializeStrutDynamics + args.Ki (6,1) double {mustBeNumeric, mustBeNonnegative} = 2e7*ones(6,1) + args.Ci (6,1) double {mustBeNumeric, mustBeNonnegative} = 1.4e3*ones(6,1) + % initializeCylindricalPlatforms args.Fpm (1,1) double {mustBeNumeric, mustBePositive} = 10 - args.Fph (1,1) double {mustBeNumeric, mustBePositive} = 26e-3 - args.Fpr (1,1) double {mustBeNumeric, mustBePositive} = 207.5e-3 + args.Fph (1,1) double {mustBeNumeric, mustBePositive} = 26e-3 + args.Fpr (1,1) double {mustBeNumeric, mustBePositive} = 207.5e-3 args.Mpm (1,1) double {mustBeNumeric, mustBePositive} = 10 - args.Mph (1,1) double {mustBeNumeric, mustBePositive} = 26e-3 - args.Mpr (1,1) double {mustBeNumeric, mustBePositive} = 150e-3 - % initializeCylindricalStruts + args.Mph (1,1) double {mustBeNumeric, mustBePositive} = 26e-3 + args.Mpr (1,1) double {mustBeNumeric, mustBePositive} = 150e-3 + % initializeCylindricalStruts args.Fsm (1,1) double {mustBeNumeric, mustBePositive} = 1 - args.Fsh (1,1) double {mustBeNumeric, mustBePositive} = 100e-3 - args.Fsr (1,1) double {mustBeNumeric, mustBePositive} = 25e-3 + args.Fsh (1,1) double {mustBeNumeric, mustBePositive} = 100e-3 + args.Fsr (1,1) double {mustBeNumeric, mustBePositive} = 25e-3 args.Msm (1,1) double {mustBeNumeric, mustBePositive} = 1 - args.Msh (1,1) double {mustBeNumeric, mustBePositive} = 100e-3 - args.Msr (1,1) double {mustBeNumeric, mustBePositive} = 25e-3 - % inverseKinematics + args.Msh (1,1) double {mustBeNumeric, mustBePositive} = 100e-3 + args.Msr (1,1) double {mustBeNumeric, mustBePositive} = 25e-3 + % inverseKinematics args.AP (3,1) double {mustBeNumeric} = zeros(3,1) args.ARB (3,3) double {mustBeNumeric} = eye(3) - % Force that stiffness of each joint should apply at t=0 - args.Foffset logical {mustBeNumericOrLogical} = false -end + % Force that stiffness of each joint should apply at t=0 + args.Foffset logical {mustBeNumericOrLogical} = false +end
stewart = initializeStewartPlatform(); stewart = initializeFramesPositions(stewart, ... - 'H', args.H, ... - 'MO_B', args.MO_B); + 'H', args.H, ... + 'MO_B', args.MO_B); stewart = generateGeneralConfiguration(stewart, ... - 'FH', args.FH, ... - 'FR', args.FR, ... - 'FTh', args.FTh, ... - 'MH', args.MH, ... - 'MR', args.MR, ... - 'MTh', args.MTh); + 'FH', args.FH, ... + 'FR', args.FR, ... + 'FTh', args.FTh, ... + 'MH', args.MH, ... + 'MR', args.MR, ... + 'MTh', args.MTh); stewart = computeJointsPose(stewart);@@ -1302,42 +1303,42 @@ stewart = computeJointsPose(stewart);
stewart = initializeStrutDynamics(stewart, ... - 'K', args.Ki, ... - 'C', args.Ci); + 'K', args.Ki, ... + 'C', args.Ci); stewart = initializeJointDynamics(stewart, ... - 'type_F', 'universal_p', ... - 'type_M', 'spherical_p'); + 'type_F', 'universal_p', ... + 'type_M', 'spherical_p');
stewart = initializeCylindricalPlatforms(stewart, ... - 'Fpm', args.Fpm, ... - 'Fph', args.Fph, ... - 'Fpr', args.Fpr, ... - 'Mpm', args.Mpm, ... - 'Mph', args.Mph, ... - 'Mpr', args.Mpr); + 'Fpm', args.Fpm, ... + 'Fph', args.Fph, ... + 'Fpr', args.Fpr, ... + 'Mpm', args.Mpm, ... + 'Mph', args.Mph, ... + 'Mpr', args.Mpr); stewart = initializeCylindricalStruts(stewart, ... - 'Fsm', args.Fsm, ... - 'Fsh', args.Fsh, ... - 'Fsr', args.Fsr, ... - 'Msm', args.Msm, ... - 'Msh', args.Msh, ... - 'Msr', args.Msr); + 'Fsm', args.Fsm, ... + 'Fsh', args.Fsh, ... + 'Fsr', args.Fsr, ... + 'Msm', args.Msm, ... + 'Msh', args.Msh, ... + 'Msr', args.Msr); stewart = computeJacobian(stewart); stewart = initializeStewartPose(stewart, ... - 'AP', args.AP, ... - 'ARB', args.ARB); + 'AP', args.AP, ... + 'ARB', args.ARB);
stewart = initializeInertialSensor(stewart, 'type', 'none'); +stewart = initializeInertialSensor(stewart, 'type', 'none');
if args.Foffset && ~strcmp(args.type, 'none') && ~strcmp(args.type, 'rigid') && ~strcmp(args.type, 'init') - load('mat/Foffset.mat', 'Fhm'); - stewart.actuators.dLeq = -Fhm'./args.Ki; -else +if args.Foffset && ~strcmp(args.type, 'none') && ~strcmp(args.type, 'rigid') && ~strcmp(args.type, 'init') + load('mat/Foffset.mat', 'Fhm'); + stewart.actuators.dLeq = -Fhm'./args.Ki; +else stewart.actuators.dLeq = zeros(6,1); -end +end
switch args.type - case 'none' +switch args.type + case 'none' stewart.type = 0; - case 'rigid' + case 'rigid' stewart.type = 1; - case 'flexible' + case 'flexible' stewart.type = 2; - case 'modal-analysis' + case 'modal-analysis' stewart.type = 3; - case 'init' + case 'init' stewart.type = 4; - case 'compliance' + case 'compliance' stewart.type = 5; -end +end
The micro_hexapod
structure is saved.
micro_hexapod = stewart; -save('./mat/stages.mat', 'micro_hexapod', '-append'); +save('./mat/stages.mat', 'micro_hexapod', '-append');
The Simscape model of the Center of gravity compensator is composed of:
@@ -1429,31 +1430,31 @@ The Simscape model of the Center of gravity compensator is composed of:function [axisc] = initializeAxisc(args) +function [axisc] = initializeAxisc(args)
arguments - args.type char {mustBeMember(args.type,{'none', 'rigid', 'flexible'})} = 'flexible' -end + args.type char {mustBeMember(args.type,{'none', 'rigid', 'flexible'})} = 'flexible' +end
First, we initialize the axisc
structure.
axisc
structure.
switch args.type - case 'none' +switch args.type + case 'none' axisc.type = 0; - case 'rigid' + case 'rigid' axisc.type = 1; - case 'flexible' + case 'flexible' axisc.type = 2; -end +end
Properties of the Material and link to the geometry files.
% Structure -axisc.structure.density = 3400; % [kg/m3] -axisc.structure.STEP = './STEPS/axisc/axisc_structure.STEP'; +% Structure +axisc.structure.density = 3400; % [kg/m3] +axisc.structure.STEP = './STEPS/axisc/axisc_structure.STEP'; -% Wheel -axisc.wheel.density = 2700; % [kg/m3] -axisc.wheel.STEP = './STEPS/axisc/axisc_wheel.STEP'; +% Wheel +axisc.wheel.density = 2700; % [kg/m3] +axisc.wheel.STEP = './STEPS/axisc/axisc_wheel.STEP'; -% Mass -axisc.mass.density = 7800; % [kg/m3] -axisc.mass.STEP = './STEPS/axisc/axisc_mass.STEP'; +% Mass +axisc.mass.density = 7800; % [kg/m3] +axisc.mass.STEP = './STEPS/axisc/axisc_mass.STEP'; -% Gear -axisc.gear.density = 7800; % [kg/m3] -axisc.gear.STEP = './STEPS/axisc/axisc_gear.STEP'; +% Gear +axisc.gear.density = 7800; % [kg/m3] +axisc.gear.STEP = './STEPS/axisc/axisc_gear.STEP';
The axisc
structure is saved.
save('./mat/stages.mat', 'axisc', '-append'); +save('./mat/stages.mat', 'axisc', '-append');
axisc
structure is saved.
The Simscape Model of the mirror is just a solid body.
The output mirror_center
corresponds to the center of the Sphere and is the point of measurement for the metrology
@@ -1554,35 +1555,35 @@ The output mirror_center
corresponds to the center of the Sphere an
function [] = initializeMirror(args) +function [] = initializeMirror(args)
arguments - args.type char {mustBeMember(args.type,{'none', 'rigid', 'flexible'})} = 'rigid' - args.shape char {mustBeMember(args.shape,{'spherical', 'conical'})} = 'spherical' - args.angle (1,1) double {mustBeNumeric, mustBePositive} = 45 % [deg] - args.mass (1,1) double {mustBeNumeric, mustBePositive} = 10 % [kg] - args.freq (6,1) double {mustBeNumeric, mustBeNonnegative} = 200*ones(6,1) % [Hz] -end + args.type char {mustBeMember(args.type,{'none', 'rigid', 'flexible'})} = 'rigid' + args.shape char {mustBeMember(args.shape,{'spherical', 'conical'})} = 'spherical' + args.angle (1,1) double {mustBeNumeric, mustBePositive} = 45 % [deg] + args.mass (1,1) double {mustBeNumeric, mustBePositive} = 10 % [kg] + args.freq (6,1) double {mustBeNumeric, mustBeNonnegative} = 200*ones(6,1) % [Hz] +end
First, we initialize the mirror
structure.
mirror
structure.
switch args.type - case 'none' +switch args.type + case 'none' mirror.type = 0; - case 'rigid' + case 'rigid' mirror.type = 1; - case 'flexible' + case 'flexible' mirror.type = 2; -end +end
mirror.K = zeros(6,1); -mirror.K(1:3) = mirror.mass * (2*pi*mirror.freq(1:3)).^2; +mirror.K(1:3) = mirror.mass * (2*pi*mirror.freq(1:3)).^2; mirror.C = zeros(6,1); -mirror.C(1:3) = 0.2 * sqrt(mirror.K(1:3).*mirror.mass); +mirror.C(1:3) = 0.2 * sqrt(mirror.K(1:3).*mirror.mass);
mirror.Deq = zeros(6,1);@@ -1652,30 +1653,30 @@ mirror.C(1:3) = 0.2 * sqrt(mirror.K(1:3).*mirror.mass); We define the geometrical values.
mirror.h = 0.05; % Height of the mirror [m] +mirror.h = 0.05; % Height of the mirror [m] -mirror.thickness = 0.025; % Thickness of the plate supporting the sample [m] +mirror.thickness = 0.02; % Thickness of the plate supporting the sample [m] -mirror.hole_rad = 0.125; % radius of the hole in the mirror [m] +mirror.hole_rad = 0.125; % radius of the hole in the mirror [m] -mirror.support_rad = 0.1; % radius of the support plate [m] +mirror.support_rad = 0.1; % radius of the support plate [m] -% point of interest offset in z (above the top surfave) [m] -switch args.type - case 'none' - mirror.jacobian = 0.20; - case 'rigid' - mirror.jacobian = 0.20 - mirror.h; - case 'flexible' - mirror.jacobian = 0.20 - mirror.h; -end +% point of interest offset in z (above the top surfave) [m] +switch args.type + case 'none' + mirror.jacobian = 0.205; + case 'rigid' + mirror.jacobian = 0.205 - mirror.h; + case 'flexible' + mirror.jacobian = 0.205 - mirror.h; +end -mirror.rad = 0.180; % radius of the mirror (at the bottom surface) [m] +mirror.rad = 0.180; % radius of the mirror (at the bottom surface) [m]
mirror.cone_length = mirror.rad*tand(args.angle)+mirror.h+mirror.jacobian; % Distance from Apex point of the cone to jacobian point +mirror.cone_length = mirror.rad*tand(args.angle)+mirror.h+mirror.jacobian; % Distance from Apex point of the cone to jacobian point
mirror.shape = [... - mirror.support_rad+5e-3 mirror.h-mirror.thickness - mirror.hole_rad mirror.h-mirror.thickness; ... + mirror.support_rad+5e-3 mirror.h-mirror.thickness + mirror.hole_rad mirror.h-mirror.thickness; ... mirror.hole_rad 0; ... mirror.rad 0 ... ]; @@ -1697,17 +1698,17 @@ We first start with the internal part. Then, we define the reflective used part of the mirror.-@@ -1715,37 +1716,37 @@ end Finally, we close the shape.if strcmp(args.shape, 'spherical') - mirror.sphere_radius = sqrt((mirror.jacobian+mirror.h)^2+mirror.rad^2); % Radius of the sphere [mm] +if strcmp(args.shape, 'spherical') + mirror.sphere_radius = sqrt((mirror.jacobian+mirror.h)^2+mirror.rad^2); % Radius of the sphere [mm] - for z = linspace(0, mirror.h, 101) - mirror.shape = [mirror.shape; sqrt(mirror.sphere_radius^2-(z-mirror.jacobian-mirror.h)^2) z]; - end -elseif strcmp(args.shape, 'conical') - mirror.shape = [mirror.shape; mirror.rad+mirror.h/tand(args.angle) mirror.h]; -else - error('Shape should be either conical or spherical'); -end + for z = linspace(0, mirror.h, 101) + mirror.shape = [mirror.shape; sqrt(mirror.sphere_radius^2-(z-mirror.jacobian-mirror.h)^2) z]; + end +elseif strcmp(args.shape, 'conical') + mirror.shape = [mirror.shape; mirror.rad+mirror.h/tand(args.angle) mirror.h]; +else + error('Shape should be either conical or spherical'); +end-mirror.shape = [mirror.shape; mirror.support_rad+5e-3 mirror.h]; +mirror.shape = [mirror.shape; mirror.support_rad+5e-3 mirror.h];
The mirror
structure is saved.
save('./mat/stages.mat', 'mirror', '-append'); +save('./mat/stages.mat', 'mirror', '-append');
@@ -1762,153 +1763,159 @@ The mirror
structure is saved.
function [nano_hexapod] = initializeNanoHexapod(args) +function [nano_hexapod] = initializeNanoHexapod(args)
arguments - args.type char {mustBeMember(args.type,{'none', 'rigid', 'flexible', 'init'})} = 'flexible' - % initializeFramesPositions - args.H (1,1) double {mustBeNumeric, mustBePositive} = 90e-3 - args.MO_B (1,1) double {mustBeNumeric} = 175e-3 - % generateGeneralConfiguration - args.FH (1,1) double {mustBeNumeric, mustBePositive} = 15e-3 - args.FR (1,1) double {mustBeNumeric, mustBePositive} = 100e-3 - args.FTh (6,1) double {mustBeNumeric} = [-10, 10, 120-10, 120+10, 240-10, 240+10]*(pi/180) - args.MH (1,1) double {mustBeNumeric, mustBePositive} = 15e-3 - args.MR (1,1) double {mustBeNumeric, mustBePositive} = 90e-3 - args.MTh (6,1) double {mustBeNumeric} = [-60+10, 60-10, 60+10, 180-10, 180+10, -60-10]*(pi/180) - % initializeStrutDynamics - args.actuator char {mustBeMember(args.actuator,{'piezo', 'lorentz', 'amplified'})} = 'piezo' + args.type char {mustBeMember(args.type,{'none', 'rigid', 'flexible', 'init'})} = 'flexible' + % initializeFramesPositions + args.H (1,1) double {mustBeNumeric, mustBePositive} = 95e-3 + args.MO_B (1,1) double {mustBeNumeric} = 170e-3 + % generateGeneralConfiguration + args.FH (1,1) double {mustBeNumeric, mustBePositive} = 15e-3 + args.FR (1,1) double {mustBeNumeric, mustBePositive} = 100e-3 + args.FTh (6,1) double {mustBeNumeric} = [-10, 10, 120-10, 120+10, 240-10, 240+10]*(pi/180) + args.MH (1,1) double {mustBeNumeric, mustBePositive} = 15e-3 + args.MR (1,1) double {mustBeNumeric, mustBePositive} = 90e-3 + args.MTh (6,1) double {mustBeNumeric} = [-60+10, 60-10, 60+10, 180-10, 180+10, -60-10]*(pi/180) + % initializeStrutDynamics + args.actuator char {mustBeMember(args.actuator,{'piezo', 'lorentz', 'amplified'})} = 'piezo' args.k1 (1,1) double {mustBeNumeric} = 1e6 args.ke (1,1) double {mustBeNumeric} = 5e6 args.ka (1,1) double {mustBeNumeric} = 60e6 args.c1 (1,1) double {mustBeNumeric} = 10 - args.ce (1,1) double {mustBeNumeric} = 10 - args.ca (1,1) double {mustBeNumeric} = 10 - args.k (1,1) double {mustBeNumeric} = -1 - args.c (1,1) double {mustBeNumeric} = -1 - % initializeJointDynamics - args.type_F char {mustBeMember(args.type_F,{'universal', 'spherical', 'universal_p', 'spherical_p', 'universal_3dof'})} = 'universal' - args.type_M char {mustBeMember(args.type_M,{'universal', 'spherical', 'universal_p', 'spherical_p', 'spherical_3dof'})} = 'spherical' - args.Kf_M (6,1) double {mustBeNumeric, mustBeNonnegative} = 15*ones(6,1) - args.Cf_M (6,1) double {mustBeNumeric, mustBeNonnegative} = 1e-4*ones(6,1) - args.Kt_M (6,1) double {mustBeNumeric, mustBeNonnegative} = 20*ones(6,1) - args.Ct_M (6,1) double {mustBeNumeric, mustBeNonnegative} = 1e-3*ones(6,1) - args.Kz_M (6,1) double {mustBeNumeric, mustBeNonnegative} = 60e6*ones(6,1) - args.Cz_M (6,1) double {mustBeNumeric, mustBeNonnegative} = 1e2*ones(6,1) - args.Kf_F (6,1) double {mustBeNumeric, mustBeNonnegative} = 15*ones(6,1) - args.Cf_F (6,1) double {mustBeNumeric, mustBeNonnegative} = 1e-4*ones(6,1) - args.Kt_F (6,1) double {mustBeNumeric, mustBeNonnegative} = 20*ones(6,1) - args.Ct_F (6,1) double {mustBeNumeric, mustBeNonnegative} = 1e-3*ones(6,1) - args.Kz_F (6,1) double {mustBeNumeric, mustBeNonnegative} = 60e6*ones(6,1) - args.Cz_F (6,1) double {mustBeNumeric, mustBeNonnegative} = 1e2*ones(6,1) - % initializeCylindricalPlatforms + args.F_gain (1,1) double {mustBeNumeric} = 1 + args.k (1,1) double {mustBeNumeric} = -1 + args.c (1,1) double {mustBeNumeric} = -1 + % initializeJointDynamics + args.type_F char {mustBeMember(args.type_F,{'universal', 'spherical', 'universal_p', 'spherical_p', 'universal_3dof', 'spherical_3dof', 'flexible'})} = 'universal' + args.type_M char {mustBeMember(args.type_M,{'universal', 'spherical', 'universal_p', 'spherical_p', 'universal_3dof', 'spherical_3dof', 'flexible'})} = 'spherical' + args.Ka_M (6,1) double {mustBeNumeric, mustBeNonnegative} = 1.2e8*ones(6,1) + args.Ca_M (6,1) double {mustBeNumeric, mustBeNonnegative} = 1e1*ones(6,1) + args.Kr_M (6,1) double {mustBeNumeric, mustBeNonnegative} = 1.1e7*ones(6,1) + args.Cr_M (6,1) double {mustBeNumeric, mustBeNonnegative} = 1e1*ones(6,1) + args.Kf_M (6,1) double {mustBeNumeric, mustBeNonnegative} = 33*ones(6,1) + args.Cf_M (6,1) double {mustBeNumeric, mustBeNonnegative} = 1e-4*ones(6,1) + args.Kt_M (6,1) double {mustBeNumeric, mustBeNonnegative} = 236*ones(6,1) + args.Ct_M (6,1) double {mustBeNumeric, mustBeNonnegative} = 1e-3*ones(6,1) + args.Kf_F (6,1) double {mustBeNumeric, mustBeNonnegative} = 33*ones(6,1) + args.Cf_F (6,1) double {mustBeNumeric, mustBeNonnegative} = 1e-4*ones(6,1) + args.Kt_F (6,1) double {mustBeNumeric, mustBeNonnegative} = 236*ones(6,1) + args.Ct_F (6,1) double {mustBeNumeric, mustBeNonnegative} = 1e-3*ones(6,1) + args.Ka_F (6,1) double {mustBeNumeric, mustBeNonnegative} = 1.2e8*ones(6,1) + args.Ca_F (6,1) double {mustBeNumeric, mustBeNonnegative} = 1e1*ones(6,1) + args.Kr_F (6,1) double {mustBeNumeric, mustBeNonnegative} = 1.1e7*ones(6,1) + args.Cr_F (6,1) double {mustBeNumeric, mustBeNonnegative} = 1e1*ones(6,1) + % initializeCylindricalPlatforms args.Fpm (1,1) double {mustBeNumeric, mustBePositive} = 1 - args.Fph (1,1) double {mustBeNumeric, mustBePositive} = 10e-3 - args.Fpr (1,1) double {mustBeNumeric, mustBePositive} = 150e-3 + args.Fph (1,1) double {mustBeNumeric, mustBePositive} = 10e-3 + args.Fpr (1,1) double {mustBeNumeric, mustBePositive} = 150e-3 args.Mpm (1,1) double {mustBeNumeric, mustBePositive} = 1 - args.Mph (1,1) double {mustBeNumeric, mustBePositive} = 10e-3 - args.Mpr (1,1) double {mustBeNumeric, mustBePositive} = 120e-3 - % initializeCylindricalStruts + args.Mph (1,1) double {mustBeNumeric, mustBePositive} = 10e-3 + args.Mpr (1,1) double {mustBeNumeric, mustBePositive} = 120e-3 + % initializeCylindricalStruts args.Fsm (1,1) double {mustBeNumeric, mustBePositive} = 0.1 - args.Fsh (1,1) double {mustBeNumeric, mustBePositive} = 50e-3 - args.Fsr (1,1) double {mustBeNumeric, mustBePositive} = 5e-3 + args.Fsh (1,1) double {mustBeNumeric, mustBePositive} = 50e-3 + args.Fsr (1,1) double {mustBeNumeric, mustBePositive} = 5e-3 args.Msm (1,1) double {mustBeNumeric, mustBePositive} = 0.1 - args.Msh (1,1) double {mustBeNumeric, mustBePositive} = 50e-3 - args.Msr (1,1) double {mustBeNumeric, mustBePositive} = 5e-3 - % inverseKinematics + args.Msh (1,1) double {mustBeNumeric, mustBePositive} = 50e-3 + args.Msr (1,1) double {mustBeNumeric, mustBePositive} = 5e-3 + % inverseKinematics args.AP (3,1) double {mustBeNumeric} = zeros(3,1) args.ARB (3,3) double {mustBeNumeric} = eye(3) - % Equilibrium position of each leg + % Equilibrium position of each leg args.dLeq (6,1) double {mustBeNumeric} = zeros(6,1) - % Force that stiffness of each joint should apply at t=0 - args.Foffset logical {mustBeNumericOrLogical} = false -end + % Force that stiffness of each joint should apply at t=0 + args.Foffset logical {mustBeNumericOrLogical} = false +end
stewart = initializeStewartPlatform(); -stewart = initializeFramesPositions(stewart, 'H', args.H, 'MO_B', args.MO_B); +stewart = initializeFramesPositions(stewart, 'H', args.H, 'MO_B', args.MO_B); -stewart = generateGeneralConfiguration(stewart, 'FH', args.FH, 'FR', args.FR, 'FTh', args.FTh, 'MH', args.MH, 'MR', args.MR, 'MTh', args.MTh); +stewart = generateGeneralConfiguration(stewart, 'FH', args.FH, 'FR', args.FR, 'FTh', args.FTh, 'MH', args.MH, 'MR', args.MR, 'MTh', args.MTh); stewart = computeJointsPose(stewart);
if args.k > 0 && args.c > 0 - stewart = initializeStrutDynamics(stewart, 'type', 'classical', 'K', args.k*ones(6,1), 'C', args.c*ones(6,1)); -elseif args.k > 0 - stewart = initializeStrutDynamics(stewart, 'type', 'classical', 'K', args.k*ones(6,1), 'C', 1.5*sqrt(args.k)*ones(6,1)); -elseif strcmp(args.actuator, 'piezo') - stewart = initializeStrutDynamics(stewart, 'type', 'classical', 'K', 1e7*ones(6,1), 'C', 1e2*ones(6,1)); -elseif strcmp(args.actuator, 'lorentz') - stewart = initializeStrutDynamics(stewart, 'type', 'classical', 'K', 1e4*ones(6,1), 'C', 1e2*ones(6,1)); -elseif strcmp(args.actuator, 'amplified') - stewart = initializeStrutDynamics(stewart, 'type', 'amplified', ... - 'k1', args.k1*ones(6,1), ... - 'c1', args.c1*ones(6,1), ... - 'ka', args.ka*ones(6,1), ... - 'ca', args.ca*ones(6,1), ... - 'ke', args.ke*ones(6,1), ... - 'ce', args.ce*ones(6,1)); -else - error('args.actuator should be piezo, lorentz or amplified'); -end +if args.k > 0 && args.c > 0 + stewart = initializeStrutDynamics(stewart, 'type', 'classical', 'K', args.k*ones(6,1), 'C', args.c*ones(6,1)); +elseif args.k > 0 + stewart = initializeStrutDynamics(stewart, 'type', 'classical', 'K', args.k*ones(6,1), 'C', 1.5*sqrt(args.k)*ones(6,1)); +elseif strcmp(args.actuator, 'piezo') + stewart = initializeStrutDynamics(stewart, 'type', 'classical', 'K', 1e7*ones(6,1), 'C', 1e2*ones(6,1)); +elseif strcmp(args.actuator, 'lorentz') + stewart = initializeStrutDynamics(stewart, 'type', 'classical', 'K', 1e4*ones(6,1), 'C', 1e2*ones(6,1)); +elseif strcmp(args.actuator, 'amplified') + stewart = initializeStrutDynamics(stewart, 'type', 'amplified', ... + 'k1', args.k1*ones(6,1), ... + 'c1', args.c1*ones(6,1), ... + 'ka', args.ka*ones(6,1), ... + 'ke', args.ke*ones(6,1), ... + 'F_gain', args.F_gain*ones(6,1)); +else + error('args.actuator should be piezo, lorentz or amplified'); +end
stewart = initializeJointDynamics(stewart, ... - 'type_F', args.type_F, ... - 'type_M', args.type_M, ... - 'Kf_M' , args.Kf_M, ... - 'Cf_M' , args.Cf_M, ... - 'Kt_M' , args.Kt_M, ... - 'Ct_M' , args.Ct_M, ... - 'Kz_M' , args.Kz_M, ... - 'Cz_M' , args.Cz_M, ... - 'Kf_F' , args.Kf_F, ... - 'Cf_F' , args.Cf_F, ... - 'Kt_F' , args.Kt_F, ... - 'Ct_F' , args.Ct_F, ... - 'Kz_F' , args.Kz_F, ... - 'Cz_F' , args.Cz_F); + 'type_F', args.type_F, ... + 'type_M', args.type_M, ... + 'Kf_M', args.Kf_M, ... + 'Cf_M', args.Cf_M, ... + 'Kt_M', args.Kt_M, ... + 'Ct_M', args.Ct_M, ... + 'Kf_F', args.Kf_F, ... + 'Cf_F', args.Cf_F, ... + 'Kt_F', args.Kt_F, ... + 'Ct_F', args.Ct_F, ... + 'Ka_F', args.Ka_F, ... + 'Ca_F', args.Ca_F, ... + 'Kr_F', args.Kr_F, ... + 'Cr_F', args.Cr_F, ... + 'Ka_M', args.Ka_M, ... + 'Ca_M', args.Ca_M, ... + 'Kr_M', args.Kr_M, ... + 'Cr_M', args.Cr_M);
stewart = initializeCylindricalPlatforms(stewart, 'Fpm', args.Fpm, 'Fph', args.Fph, 'Fpr', args.Fpr, 'Mpm', args.Mpm, 'Mph', args.Mph, 'Mpr', args.Mpr); +stewart = initializeCylindricalPlatforms(stewart, 'Fpm', args.Fpm, 'Fph', args.Fph, 'Fpr', args.Fpr, 'Mpm', args.Mpm, 'Mph', args.Mph, 'Mpr', args.Mpr); -stewart = initializeCylindricalStruts(stewart, 'Fsm', args.Fsm, 'Fsh', args.Fsh, 'Fsr', args.Fsr, 'Msm', args.Msm, 'Msh', args.Msh, 'Msr', args.Msr); +stewart = initializeCylindricalStruts(stewart, 'Fsm', args.Fsm, 'Fsh', args.Fsh, 'Fsr', args.Fsr, 'Msm', args.Msm, 'Msh', args.Msh, 'Msr', args.Msr); stewart = computeJacobian(stewart); -stewart = initializeStewartPose(stewart, 'AP', args.AP, 'ARB', args.ARB); +stewart = initializeStewartPose(stewart, 'AP', args.AP, 'ARB', args.ARB);
stewart = initializeInertialSensor(stewart, 'type', 'accelerometer'); +stewart = initializeInertialSensor(stewart, 'type', 'accelerometer');
-if args.Foffset && ~strcmp(args.type, 'none') && ~strcmp(args.type, 'rigid') && ~strcmp(args.type, 'init') - load('mat/Foffset.mat', 'Fnm'); - stewart.actuators.dLeq = -Fnm'./stewart.Ki; -else +if args.Foffset && ~strcmp(args.type, 'none') && ~strcmp(args.type, 'rigid') && ~strcmp(args.type, 'init') + load('mat/Foffset.mat', 'Fnm'); + stewart.actuators.dLeq = -Fnm'./stewart.Ki; +else stewart.actuators.dLeq = args.dLeq; -end +end
switch args.type - case 'none' +switch args.type + case 'none' stewart.type = 0; - case 'rigid' + case 'rigid' stewart.type = 1; - case 'flexible' + case 'flexible' stewart.type = 2; - case 'init' + case 'init' stewart.type = 4; -end +end
nano_hexapod = stewart; -save('./mat/stages.mat', 'nano_hexapod', '-append'); +save('./mat/stages.mat', 'nano_hexapod', '-append');
The Simscape model of the sample environment is composed of:
@@ -1997,37 +2004,37 @@ This could be the case for cable forces for instance.function [sample] = initializeSample(args) +function [sample] = initializeSample(args)
arguments - args.type char {mustBeMember(args.type,{'rigid', 'flexible', 'none', 'init'})} = 'flexible' - args.radius (1,1) double {mustBeNumeric, mustBePositive} = 0.1 % [m] - args.height (1,1) double {mustBeNumeric, mustBePositive} = 0.3 % [m] - args.mass (1,1) double {mustBeNumeric, mustBePositive} = 50 % [kg] - args.freq (6,1) double {mustBeNumeric, mustBePositive} = 100*ones(6,1) % [Hz] - args.offset (1,1) double {mustBeNumeric} = 0 % [m] - args.Foffset logical {mustBeNumericOrLogical} = false -end + args.type char {mustBeMember(args.type,{'rigid', 'flexible', 'none', 'init'})} = 'flexible' + args.radius (1,1) double {mustBeNumeric, mustBePositive} = 0.1 % [m] + args.height (1,1) double {mustBeNumeric, mustBePositive} = 0.3 % [m] + args.mass (1,1) double {mustBeNumeric, mustBePositive} = 50 % [kg] + args.freq (6,1) double {mustBeNumeric, mustBePositive} = 100*ones(6,1) % [Hz] + args.offset (1,1) double {mustBeNumeric} = 0 % [m] + args.Foffset logical {mustBeNumericOrLogical} = false +end
First, we initialize the sample
structure.
sample
structure.
switch args.type - case 'none' +switch args.type + case 'none' sample.type = 0; - case 'rigid' + case 'rigid' sample.type = 1; - case 'flexible' + case 'flexible' sample.type = 2; - case 'init' + case 'init' sample.type = 3; -end +end
We define the geometrical parameters of the sample as well as its mass and position.
sample.radius = args.radius; % [m] -sample.height = args.height; % [m] -sample.mass = args.mass; % [kg] -sample.offset = args.offset; % [m] +sample.radius = args.radius; % [m] +sample.height = args.height; % [m] +sample.mass = args.mass; % [kg] +sample.offset = args.offset; % [m]
sample.inertia = [1/12 * sample.mass * (3*sample.radius^2 + sample.height^2); ... - 1/12 * sample.mass * (3*sample.radius^2 + sample.height^2); ... - 1/2 * sample.mass * sample.radius^2]; +sample.inertia = [1/12 * sample.mass * (3*sample.radius^2 + sample.height^2); ... + 1/12 * sample.mass * (3*sample.radius^2 + sample.height^2); ... + 1/2 * sample.mass * sample.radius^2];
sample.K = zeros(6, 1); sample.C = zeros(6, 1); @@ -2098,8 +2105,8 @@ sample.C = zeros(6, 1); Translation Stiffness and Damping:-@@ -2107,36 +2114,36 @@ sample.C(1:3) = 0.1 * sqrt(sample.K(1:3)*sample.mass); % [N/(m/s)] Rotational Stiffness and Damping:sample.K(1:3) = sample.mass .* (2*pi * args.freq(1:3)).^2; % [N/m] -sample.C(1:3) = 0.1 * sqrt(sample.K(1:3)*sample.mass); % [N/(m/s)] +sample.K(1:3) = sample.mass .* (2*pi * args.freq(1:3)).^2; % [N/m] +sample.C(1:3) = 0.1 * sqrt(sample.K(1:3)*sample.mass); % [N/(m/s)]-sample.K(4:6) = sample.inertia .* (2*pi * args.freq(4:6)).^2; % [N/m] -sample.C(4:6) = 0.1 * sqrt(sample.K(4:6).*sample.inertia); % [N/(m/s)] +sample.K(4:6) = sample.inertia .* (2*pi * args.freq(4:6)).^2; % [N/m] +sample.C(4:6) = 0.1 * sqrt(sample.K(4:6).*sample.inertia); % [N/(m/s)]
if args.Foffset && ~strcmp(args.type, 'none') && ~strcmp(args.type, 'rigid') && ~strcmp(args.type, 'init') - load('mat/Foffset.mat', 'Fsm'); - sample.Deq = -Fsm'./sample.K; -else +if args.Foffset && ~strcmp(args.type, 'none') && ~strcmp(args.type, 'rigid') && ~strcmp(args.type, 'init') + load('mat/Foffset.mat', 'Fsm'); + sample.Deq = -Fsm'./sample.K; +else sample.Deq = zeros(6,1); -end +end
The sample
structure is saved.
save('./mat/stages.mat', 'sample', '-append'); +save('./mat/stages.mat', 'sample', '-append');
sample
structure is saved.
function [] = initializeController(args) +function [] = initializeController(args)
arguments - args.type char {mustBeMember(args.type,{'open-loop', 'iff', 'dvf', 'hac-dvf', 'ref-track-L', 'ref-track-iff-L', 'cascade-hac-lac', 'hac-iff', 'stabilizing'})} = 'open-loop' -end + args.type char {mustBeMember(args.type,{'open-loop', 'iff', 'dvf', 'hac-dvf', 'ref-track-L', 'ref-track-iff-L', 'cascade-hac-lac', 'hac-iff', 'stabilizing'})} = 'open-loop' +end
First, we initialize the controller
structure.
controller
structure.
switch args.type - case 'open-loop' +switch args.type + case 'open-loop' controller.type = 1; - controller.name = 'Open-Loop'; - case 'dvf' + controller.name = 'Open-Loop'; + case 'dvf' controller.type = 2; - controller.name = 'Decentralized Direct Velocity Feedback'; - case 'iff' + controller.name = 'Decentralized Direct Velocity Feedback'; + case 'iff' controller.type = 3; - controller.name = 'Decentralized Integral Force Feedback'; - case 'hac-dvf' + controller.name = 'Decentralized Integral Force Feedback'; + case 'hac-dvf' controller.type = 4; - controller.name = 'HAC-DVF'; - case 'ref-track-L' + controller.name = 'HAC-DVF'; + case 'ref-track-L' controller.type = 5; - controller.name = 'Reference Tracking in the frame of the legs'; - case 'ref-track-iff-L' + controller.name = 'Reference Tracking in the frame of the legs'; + case 'ref-track-iff-L' controller.type = 6; - controller.name = 'Reference Tracking in the frame of the legs + IFF'; - case 'cascade-hac-lac' + controller.name = 'Reference Tracking in the frame of the legs + IFF'; + case 'cascade-hac-lac' controller.type = 7; - controller.name = 'Cascade Control + HAC-LAC'; - case 'hac-iff' + controller.name = 'Cascade Control + HAC-LAC'; + case 'hac-iff' controller.type = 8; - controller.name = 'HAC-IFF'; - case 'stabilizing' + controller.name = 'HAC-IFF'; + case 'stabilizing' controller.type = 9; - controller.name = 'Stabilizing Controller'; -end + controller.name = 'Stabilizing Controller'; +end
The controller
structure is saved.
save('./mat/controller.mat', 'controller'); +save('./mat/controller.mat', 'controller');
controller
structure is saved.
function [ref] = initializeReferences(args) +function [ref] = initializeReferences(args)
arguments - % Sampling Frequency [s] - args.Ts (1,1) double {mustBeNumeric, mustBePositive} = 1e-3 - % Maximum simulation time [s] + % Sampling Frequency [s] + args.Ts (1,1) double {mustBeNumeric, mustBePositive} = 1e-3 + % Maximum simulation time [s] args.Tmax (1,1) double {mustBeNumeric, mustBePositive} = 100 - % Either "constant" / "triangular" / "sinusoidal" - args.Dy_type char {mustBeMember(args.Dy_type,{'constant', 'triangular', 'sinusoidal'})} = 'constant' - % Amplitude of the displacement [m] + % Either "constant" / "triangular" / "sinusoidal" + args.Dy_type char {mustBeMember(args.Dy_type,{'constant', 'triangular', 'sinusoidal'})} = 'constant' + % Amplitude of the displacement [m] args.Dy_amplitude (1,1) double {mustBeNumeric} = 0 - % Period of the displacement [s] + % Period of the displacement [s] args.Dy_period (1,1) double {mustBeNumeric, mustBePositive} = 1 - % Either "constant" / "triangular" / "sinusoidal" - args.Ry_type char {mustBeMember(args.Ry_type,{'constant', 'triangular', 'sinusoidal'})} = 'constant' - % Amplitude [rad] + % Either "constant" / "triangular" / "sinusoidal" + args.Ry_type char {mustBeMember(args.Ry_type,{'constant', 'triangular', 'sinusoidal'})} = 'constant' + % Amplitude [rad] args.Ry_amplitude (1,1) double {mustBeNumeric} = 0 - % Period of the displacement [s] + % Period of the displacement [s] args.Ry_period (1,1) double {mustBeNumeric, mustBePositive} = 1 - % Either "constant" / "rotating" - args.Rz_type char {mustBeMember(args.Rz_type,{'constant', 'rotating', 'rotating-not-filtered'})} = 'constant' - % Initial angle [rad] + % Either "constant" / "rotating" + args.Rz_type char {mustBeMember(args.Rz_type,{'constant', 'rotating', 'rotating-not-filtered'})} = 'constant' + % Initial angle [rad] args.Rz_amplitude (1,1) double {mustBeNumeric} = 0 - % Period of the rotating [s] + % Period of the rotating [s] args.Rz_period (1,1) double {mustBeNumeric, mustBePositive} = 1 - % For now, only constant is implemented - args.Dh_type char {mustBeMember(args.Dh_type,{'constant'})} = 'constant' - % Initial position [m,m,m,rad,rad,rad] of the top platform (Pitch-Roll-Yaw Euler angles) + % For now, only constant is implemented + args.Dh_type char {mustBeMember(args.Dh_type,{'constant'})} = 'constant' + % Initial position [m,m,m,rad,rad,rad] of the top platform (Pitch-Roll-Yaw Euler angles) args.Dh_pos (6,1) double {mustBeNumeric} = zeros(6, 1), ... - % For now, only constant is implemented - args.Rm_type char {mustBeMember(args.Rm_type,{'constant'})} = 'constant' - % Initial position of the two masses - args.Rm_pos (2,1) double {mustBeNumeric} = [0; pi] - % For now, only constant is implemented - args.Dn_type char {mustBeMember(args.Dn_type,{'constant'})} = 'constant' - % Initial position [m,m,m,rad,rad,rad] of the top platform + % For now, only constant is implemented + args.Rm_type char {mustBeMember(args.Rm_type,{'constant'})} = 'constant' + % Initial position of the two masses + args.Rm_pos (2,1) double {mustBeNumeric} = [0; pi] + % For now, only constant is implemented + args.Dn_type char {mustBeMember(args.Dn_type,{'constant'})} = 'constant' + % Initial position [m,m,m,rad,rad,rad] of the top platform args.Dn_pos (6,1) double {mustBeNumeric} = zeros(6,1) -end +end
%% Set Sampling Time +%% Set Sampling Time Ts = args.Ts; Tmax = args.Tmax; -%% Low Pass Filter to filter out the references -s = zpk('s'); -w0 = 2*pi*10; +%% Low Pass Filter to filter out the references +s = zpk('s'); +w0 = 2*pi*10; xi = 1; -H_lpf = 1/(1 + 2*xi/w0*s + s^2/w0^2); +H_lpf = 1/(1 + 2*xi/w0*s + s^2/w0^2);
%% Translation stage - Dy -t = 0:Ts:Tmax; % Time Vector [s] +%% Translation stage - Dy +t = 0:Ts:Tmax; % Time Vector [s] Dy = zeros(length(t), 1); Dyd = zeros(length(t), 1); Dydd = zeros(length(t), 1); -switch args.Dy_type - case 'constant' - Dy(:) = args.Dy_amplitude; - Dyd(:) = 0; - Dydd(:) = 0; - case 'triangular' - % This is done to unsure that we start with no displacement - Dy_raw = args.Dy_amplitude*sawtooth(2*pi*t/args.Dy_period,1/2); - i0 = find(t>=args.Dy_period/4,1); - Dy(1:end-i0+1) = Dy_raw(i0:end); - Dy(end-i0+2:end) = Dy_raw(end); % we fix the last value +switch args.Dy_type + case 'constant' + Dy(:) = args.Dy_amplitude; + Dyd(:) = 0; + Dydd(:) = 0; + case 'triangular' + % This is done to unsure that we start with no displacement + Dy_raw = args.Dy_amplitude*sawtooth(2*pi*t/args.Dy_period,1/2); + i0 = find(t>=args.Dy_period/4,1); + Dy(1:end-i0+1) = Dy_raw(i0:end); + Dy(end-i0+2:end) = Dy_raw(end); % we fix the last value - % The signal is filtered out + % The signal is filtered out Dy = lsim(H_lpf, Dy, t); - Dyd = lsim(H_lpf*s, Dy, t); - Dydd = lsim(H_lpf*s^2, Dy, t); - case 'sinusoidal' - Dy(:) = args.Dy_amplitude*sin(2*pi/args.Dy_period*t); - Dyd = args.Dy_amplitude*2*pi/args.Dy_period*cos(2*pi/args.Dy_period*t); - Dydd = -args.Dy_amplitude*(2*pi/args.Dy_period)^2*sin(2*pi/args.Dy_period*t); - otherwise - warning('Dy_type is not set correctly'); -end + Dyd = lsim(H_lpf*s, Dy, t); + Dydd = lsim(H_lpf*s^2, Dy, t); + case 'sinusoidal' + Dy(:) = args.Dy_amplitude*sin(2*pi/args.Dy_period*t); + Dyd = args.Dy_amplitude*2*pi/args.Dy_period*cos(2*pi/args.Dy_period*t); + Dydd = -args.Dy_amplitude*(2*pi/args.Dy_period)^2*sin(2*pi/args.Dy_period*t); + otherwise + warning('Dy_type is not set correctly'); +end -Dy = struct('time', t, 'signals', struct('values', Dy), 'deriv', Dyd, 'dderiv', Dydd); +Dy = struct('time', t, 'signals', struct('values', Dy), 'deriv', Dyd, 'dderiv', Dydd);
%% Tilt Stage - Ry -t = 0:Ts:Tmax; % Time Vector [s] +%% Tilt Stage - Ry +t = 0:Ts:Tmax; % Time Vector [s] Ry = zeros(length(t), 1); Ryd = zeros(length(t), 1); Rydd = zeros(length(t), 1); -switch args.Ry_type - case 'constant' - Ry(:) = args.Ry_amplitude; - Ryd(:) = 0; - Rydd(:) = 0; - case 'triangular' - Ry_raw = args.Ry_amplitude*sawtooth(2*pi*t/args.Ry_period,1/2); - i0 = find(t>=args.Ry_period/4,1); - Ry(1:end-i0+1) = Ry_raw(i0:end); - Ry(end-i0+2:end) = Ry_raw(end); % we fix the last value +switch args.Ry_type + case 'constant' + Ry(:) = args.Ry_amplitude; + Ryd(:) = 0; + Rydd(:) = 0; + case 'triangular' + Ry_raw = args.Ry_amplitude*sawtooth(2*pi*t/args.Ry_period,1/2); + i0 = find(t>=args.Ry_period/4,1); + Ry(1:end-i0+1) = Ry_raw(i0:end); + Ry(end-i0+2:end) = Ry_raw(end); % we fix the last value - % The signal is filtered out + % The signal is filtered out Ry = lsim(H_lpf, Ry, t); - Ryd = lsim(H_lpf*s, Ry, t); - Rydd = lsim(H_lpf*s^2, Ry, t); - case 'sinusoidal' - Ry(:) = args.Ry_amplitude*sin(2*pi/args.Ry_period*t); + Ryd = lsim(H_lpf*s, Ry, t); + Rydd = lsim(H_lpf*s^2, Ry, t); + case 'sinusoidal' + Ry(:) = args.Ry_amplitude*sin(2*pi/args.Ry_period*t); - Ryd = args.Ry_amplitude*2*pi/args.Ry_period*cos(2*pi/args.Ry_period*t); - Rydd = -args.Ry_amplitude*(2*pi/args.Ry_period)^2*sin(2*pi/args.Ry_period*t); - otherwise - warning('Ry_type is not set correctly'); -end + Ryd = args.Ry_amplitude*2*pi/args.Ry_period*cos(2*pi/args.Ry_period*t); + Rydd = -args.Ry_amplitude*(2*pi/args.Ry_period)^2*sin(2*pi/args.Ry_period*t); + otherwise + warning('Ry_type is not set correctly'); +end -Ry = struct('time', t, 'signals', struct('values', Ry), 'deriv', Ryd, 'dderiv', Rydd); +Ry = struct('time', t, 'signals', struct('values', Ry), 'deriv', Ryd, 'dderiv', Rydd);
%% Spindle - Rz -t = 0:Ts:Tmax; % Time Vector [s] +%% Spindle - Rz +t = 0:Ts:Tmax; % Time Vector [s] Rz = zeros(length(t), 1); Rzd = zeros(length(t), 1); Rzdd = zeros(length(t), 1); -switch args.Rz_type - case 'constant' - Rz(:) = args.Rz_amplitude; - Rzd(:) = 0; - Rzdd(:) = 0; - case 'rotating-not-filtered' - Rz(:) = 2*pi/args.Rz_period*t; +switch args.Rz_type + case 'constant' + Rz(:) = args.Rz_amplitude; + Rzd(:) = 0; + Rzdd(:) = 0; + case 'rotating-not-filtered' + Rz(:) = 2*pi/args.Rz_period*t; - % The signal is filtered out - Rz(:) = 2*pi/args.Rz_period*t; - Rzd(:) = 2*pi/args.Rz_period; - Rzdd(:) = 0; + % The signal is filtered out + Rz(:) = 2*pi/args.Rz_period*t; + Rzd(:) = 2*pi/args.Rz_period; + Rzdd(:) = 0; - % We add the angle offset - Rz = Rz + args.Rz_amplitude; + % We add the angle offset + Rz = Rz + args.Rz_amplitude; - case 'rotating' - Rz(:) = 2*pi/args.Rz_period*t; + case 'rotating' + Rz(:) = 2*pi/args.Rz_period*t; - % The signal is filtered out + % The signal is filtered out Rz = lsim(H_lpf, Rz, t); - Rzd = lsim(H_lpf*s, Rz, t); - Rzdd = lsim(H_lpf*s^2, Rz, t); + Rzd = lsim(H_lpf*s, Rz, t); + Rzdd = lsim(H_lpf*s^2, Rz, t); - % We add the angle offset - Rz = Rz + args.Rz_amplitude; - otherwise - warning('Rz_type is not set correctly'); -end + % We add the angle offset + Rz = Rz + args.Rz_amplitude; + otherwise + warning('Rz_type is not set correctly'); +end -Rz = struct('time', t, 'signals', struct('values', Rz), 'deriv', Rzd, 'dderiv', Rzdd); +Rz = struct('time', t, 'signals', struct('values', Rz), 'deriv', Rzd, 'dderiv', Rzdd);
%% Micro-Hexapod +%% Micro-Hexapod t = [0, Ts]; Dh = zeros(length(t), 6); Dhl = zeros(length(t), 6); -switch args.Dh_type - case 'constant' +switch args.Dh_type + case 'constant' Dh = [args.Dh_pos, args.Dh_pos]; - load('mat/stages.mat', 'micro_hexapod'); + load('mat/stages.mat', 'micro_hexapod'); AP = [args.Dh_pos(1) ; args.Dh_pos(2) ; args.Dh_pos(3)]; @@ -2466,24 +2473,24 @@ switch args.Dh_type ty = args.Dh_pos(5); tz = args.Dh_pos(6); - ARB = [cos(tz) -sin(tz) 0; + ARB = [cos(tz) -sin(tz) 0; sin(tz) cos(tz) 0; - 0 0 1]*... + 0 0 1]*... [ cos(ty) 0 sin(ty); 0 1 0; - -sin(ty) 0 cos(ty)]*... + -sin(ty) 0 cos(ty)]*... [1 0 0; - 0 cos(tx) -sin(tx); + 0 cos(tx) -sin(tx); 0 sin(tx) cos(tx)]; - [~, Dhl] = inverseKinematics(micro_hexapod, 'AP', AP, 'ARB', ARB); + [~, Dhl] = inverseKinematics(micro_hexapod, 'AP', AP, 'ARB', ARB); Dhl = [Dhl, Dhl]; - otherwise - warning('Dh_type is not set correctly'); -end + otherwise + warning('Dh_type is not set correctly'); +end -Dh = struct('time', t, 'signals', struct('values', Dh)); -Dhl = struct('time', t, 'signals', struct('values', Dhl)); +Dh = struct('time', t, 'signals', struct('values', Dh)); +Dhl = struct('time', t, 'signals', struct('values', Dhl));
%% Axis Compensation - Rm +%% Axis Compensation - Rm t = [0, Ts]; Rm = [args.Rm_pos, args.Rm_pos]; -Rm = struct('time', t, 'signals', struct('values', Rm)); +Rm = struct('time', t, 'signals', struct('values', Rm));
%% Nano-Hexapod +%% Nano-Hexapod t = [0, Ts]; Dn = zeros(length(t), 6); -switch args.Dn_type - case 'constant' +switch args.Dn_type + case 'constant' Dn = [args.Dn_pos, args.Dn_pos]; - load('mat/stages.mat', 'nano_hexapod'); + load('mat/stages.mat', 'nano_hexapod'); AP = [args.Dn_pos(1) ; args.Dn_pos(2) ; args.Dn_pos(3)]; @@ -2523,36 +2530,36 @@ switch args.Dn_type ty = args.Dn_pos(5); tz = args.Dn_pos(6); - ARB = [cos(tz) -sin(tz) 0; + ARB = [cos(tz) -sin(tz) 0; sin(tz) cos(tz) 0; - 0 0 1]*... + 0 0 1]*... [ cos(ty) 0 sin(ty); 0 1 0; - -sin(ty) 0 cos(ty)]*... + -sin(ty) 0 cos(ty)]*... [1 0 0; - 0 cos(tx) -sin(tx); + 0 cos(tx) -sin(tx); 0 sin(tx) cos(tx)]; - [~, Dnl] = inverseKinematics(nano_hexapod, 'AP', AP, 'ARB', ARB); + [~, Dnl] = inverseKinematics(nano_hexapod, 'AP', AP, 'ARB', ARB); Dnl = [Dnl, Dnl]; - otherwise - warning('Dn_type is not set correctly'); -end + otherwise + warning('Dn_type is not set correctly'); +end -Dn = struct('time', t, 'signals', struct('values', Dn)); -Dnl = struct('time', t, 'signals', struct('values', Dnl)); +Dn = struct('time', t, 'signals', struct('values', Dn)); +Dnl = struct('time', t, 'signals', struct('values', Dnl));
%% Save - save('./mat/nass_references.mat', 'Dy', 'Ry', 'Rz', 'Dh', 'Dhl', 'Rm', 'Dn', 'Dnl', 'args', 'Ts'); -end +%% Save + save('./mat/nass_references.mat', 'Dy', 'Ry', 'Rz', 'Dh', 'Dhl', 'Rm', 'Dn', 'Dnl', 'args', 'Ts'); +end
function [] = initializeDisturbances(args) -% initializeDisturbances - Initialize the disturbances -% -% Syntax: [] = initializeDisturbances(args) -% -% Inputs: -% - args - +function [] = initializeDisturbances(args) +% initializeDisturbances - Initialize the disturbances +% +% Syntax: [] = initializeDisturbances(args) +% +% Inputs: +% - args -
arguments - % Global parameter to enable or disable the disturbances - args.enable logical {mustBeNumericOrLogical} = true - % Ground Motion - X direction - args.Dwx logical {mustBeNumericOrLogical} = true - % Ground Motion - Y direction - args.Dwy logical {mustBeNumericOrLogical} = true - % Ground Motion - Z direction - args.Dwz logical {mustBeNumericOrLogical} = true - % Translation Stage - X direction - args.Fty_x logical {mustBeNumericOrLogical} = true - % Translation Stage - Z direction - args.Fty_z logical {mustBeNumericOrLogical} = true - % Spindle - Z direction - args.Frz_z logical {mustBeNumericOrLogical} = true -end + % Global parameter to enable or disable the disturbances + args.enable logical {mustBeNumericOrLogical} = true + % Ground Motion - X direction + args.Dwx logical {mustBeNumericOrLogical} = true + % Ground Motion - Y direction + args.Dwy logical {mustBeNumericOrLogical} = true + % Ground Motion - Z direction + args.Dwz logical {mustBeNumericOrLogical} = true + % Translation Stage - X direction + args.Fty_x logical {mustBeNumericOrLogical} = true + % Translation Stage - Z direction + args.Fty_z logical {mustBeNumericOrLogical} = true + % Spindle - Z direction + args.Frz_z logical {mustBeNumericOrLogical} = true +end
load('./mat/dist_psd.mat', 'dist_f'); +load('./mat/dist_psd.mat', 'dist_f');
Fs = 2*dist_f.f(end); % Sampling Frequency of data is twice the maximum frequency of the PSD vector [Hz] -N = 2*length(dist_f.f); % Number of Samples match the one of the wanted PSD -T0 = N/Fs; % Signal Duration [s] -df = 1/T0; % Frequency resolution of the DFT [Hz] - % Also equal to (dist_f.f(2)-dist_f.f(1)) -t = linspace(0, T0, N+1)'; % Time Vector [s] -Ts = 1/Fs; % Sampling Time [s] +Fs = 2*dist_f.f(end); % Sampling Frequency of data is twice the maximum frequency of the PSD vector [Hz] +N = 2*length(dist_f.f); % Number of Samples match the one of the wanted PSD +T0 = N/Fs; % Signal Duration [s] +df = 1/T0; % Frequency resolution of the DFT [Hz] + % Also equal to (dist_f.f(2)-dist_f.f(1)) +t = linspace(0, T0, N+1)'; % Time Vector [s] +Ts = 1/Fs; % Sampling Time [s]
phi = dist_f.psd_gm; -C = zeros(N/2,1); -for i = 1:N/2 - C(i) = sqrt(phi(i)*df); -end +C = zeros(N/2,1); +for i = 1:N/2 + C(i) = sqrt(phi(i)*df); +end
if args.Dwx && args.enable - rng(111); - theta = 2*pi*rand(N/2,1); % Generate random phase [rad] - Cx = [0 ; C.*complex(cos(theta),sin(theta))]; - Cx = [Cx; flipud(conj(Cx(2:end)))];; - Dwx = N/sqrt(2)*ifft(Cx); % Ground Motion - x direction [m] -else +if args.Dwx && args.enable + rng(111); + theta = 2*pi*rand(N/2,1); % Generate random phase [rad] + Cx = [0 ; C.*complex(cos(theta),sin(theta))]; + Cx = [Cx; flipud(conj(Cx(2:end)))];; + Dwx = N/sqrt(2)*ifft(Cx); % Ground Motion - x direction [m] +else Dwx = zeros(length(t), 1); -end +end
if args.Dwy && args.enable - rng(112); - theta = 2*pi*rand(N/2,1); % Generate random phase [rad] - Cx = [0 ; C.*complex(cos(theta),sin(theta))]; - Cx = [Cx; flipud(conj(Cx(2:end)))];; - Dwy = N/sqrt(2)*ifft(Cx); % Ground Motion - y direction [m] -else +if args.Dwy && args.enable + rng(112); + theta = 2*pi*rand(N/2,1); % Generate random phase [rad] + Cx = [0 ; C.*complex(cos(theta),sin(theta))]; + Cx = [Cx; flipud(conj(Cx(2:end)))];; + Dwy = N/sqrt(2)*ifft(Cx); % Ground Motion - y direction [m] +else Dwy = zeros(length(t), 1); -end +end
if args.Dwy && args.enable - rng(113); - theta = 2*pi*rand(N/2,1); % Generate random phase [rad] - Cx = [0 ; C.*complex(cos(theta),sin(theta))]; - Cx = [Cx; flipud(conj(Cx(2:end)))];; - Dwz = N/sqrt(2)*ifft(Cx); % Ground Motion - z direction [m] -else +if args.Dwy && args.enable + rng(113); + theta = 2*pi*rand(N/2,1); % Generate random phase [rad] + Cx = [0 ; C.*complex(cos(theta),sin(theta))]; + Cx = [Cx; flipud(conj(Cx(2:end)))];; + Dwz = N/sqrt(2)*ifft(Cx); % Ground Motion - z direction [m] +else Dwz = zeros(length(t), 1); -end +end
if args.Fty_x && args.enable - phi = dist_f.psd_ty; % TODO - we take here the vertical direction which is wrong but approximate - C = zeros(N/2,1); - for i = 1:N/2 - C(i) = sqrt(phi(i)*df); - end - rng(121); - theta = 2*pi*rand(N/2,1); % Generate random phase [rad] - Cx = [0 ; C.*complex(cos(theta),sin(theta))]; - Cx = [Cx; flipud(conj(Cx(2:end)))];; - u = N/sqrt(2)*ifft(Cx); % Disturbance Force Ty x [N] +if args.Fty_x && args.enable + phi = dist_f.psd_ty; % TODO - we take here the vertical direction which is wrong but approximate + C = zeros(N/2,1); + for i = 1:N/2 + C(i) = sqrt(phi(i)*df); + end + rng(121); + theta = 2*pi*rand(N/2,1); % Generate random phase [rad] + Cx = [0 ; C.*complex(cos(theta),sin(theta))]; + Cx = [Cx; flipud(conj(Cx(2:end)))];; + u = N/sqrt(2)*ifft(Cx); % Disturbance Force Ty x [N] Fty_x = u; -else +else Fty_x = zeros(length(t), 1); -end +end
if args.Fty_z && args.enable +if args.Fty_z && args.enable phi = dist_f.psd_ty; - C = zeros(N/2,1); - for i = 1:N/2 - C(i) = sqrt(phi(i)*df); - end - rng(122); - theta = 2*pi*rand(N/2,1); % Generate random phase [rad] - Cx = [0 ; C.*complex(cos(theta),sin(theta))]; - Cx = [Cx; flipud(conj(Cx(2:end)))];; - u = N/sqrt(2)*ifft(Cx); % Disturbance Force Ty z [N] + C = zeros(N/2,1); + for i = 1:N/2 + C(i) = sqrt(phi(i)*df); + end + rng(122); + theta = 2*pi*rand(N/2,1); % Generate random phase [rad] + Cx = [0 ; C.*complex(cos(theta),sin(theta))]; + Cx = [Cx; flipud(conj(Cx(2:end)))];; + u = N/sqrt(2)*ifft(Cx); % Disturbance Force Ty z [N] Fty_z = u; -else +else Fty_z = zeros(length(t), 1); -end +end
if args.Frz_z && args.enable +if args.Frz_z && args.enable phi = dist_f.psd_rz; - C = zeros(N/2,1); - for i = 1:N/2 - C(i) = sqrt(phi(i)*df); - end - rng(131); - theta = 2*pi*rand(N/2,1); % Generate random phase [rad] - Cx = [0 ; C.*complex(cos(theta),sin(theta))]; - Cx = [Cx; flipud(conj(Cx(2:end)))];; - u = N/sqrt(2)*ifft(Cx); % Disturbance Force Rz z [N] + C = zeros(N/2,1); + for i = 1:N/2 + C(i) = sqrt(phi(i)*df); + end + rng(131); + theta = 2*pi*rand(N/2,1); % Generate random phase [rad] + Cx = [0 ; C.*complex(cos(theta),sin(theta))]; + Cx = [Cx; flipud(conj(Cx(2:end)))];; + u = N/sqrt(2)*ifft(Cx); % Disturbance Force Rz z [N] Frz_z = u; -else +else Frz_z = zeros(length(t), 1); -end +end
Dwx = Dwx - Dwx(1); -Dwy = Dwy - Dwy(1); -Dwz = Dwz - Dwz(1); -Fty_x = Fty_x - Fty_x(1); -Fty_z = Fty_z - Fty_z(1); -Frz_z = Frz_z - Frz_z(1); +Dwx = Dwx - Dwx(1); +Dwy = Dwy - Dwy(1); +Dwz = Dwz - Dwz(1); +Fty_x = Fty_x - Fty_x(1); +Fty_z = Fty_z - Fty_z(1); +Frz_z = Frz_z - Frz_z(1);
save('./mat/nass_disturbances.mat', 'Dwx', 'Dwy', 'Dwz', 'Fty_x', 'Fty_z', 'Frz_z', 'Fd', 'Ts', 't', 'args'); +save('./mat/nass_disturbances.mat', 'Dwx', 'Dwy', 'Dwz', 'Fty_x', 'Fty_z', 'Frz_z', 'Fd', 'Ts', 't', 'args');
function [] = initializePosError(args) -% initializePosError - Initialize the position errors -% -% Syntax: [] = initializePosError(args) -% -% Inputs: -% - args - +function [] = initializePosError(args) +% initializePosError - Initialize the position errors +% +% Syntax: [] = initializePosError(args) +% +% Inputs: +% - args -
arguments - args.error logical {mustBeNumericOrLogical} = false - args.Dy (1,1) double {mustBeNumeric} = 0 % [m] - args.Ry (1,1) double {mustBeNumeric} = 0 % [m] - args.Rz (1,1) double {mustBeNumeric} = 0 % [m] -end + args.error logical {mustBeNumericOrLogical} = false + args.Dy (1,1) double {mustBeNumeric} = 0 % [m] + args.Ry (1,1) double {mustBeNumeric} = 0 % [m] + args.Rz (1,1) double {mustBeNumeric} = 0 % [m] +end
First, we initialize the pos_error
structure.
pos_error
structure.
if args.error +if args.error pos_error.type = 1; -else +else pos_error.type = 0; -end +end
save('./mat/pos_error.mat', 'pos_error'); +save('./mat/pos_error.mat', 'pos_error');
function [geophone] = initializeZAxisGeophone(args) +function [geophone] = initializeZAxisGeophone(args) arguments - args.mass (1,1) double {mustBeNumeric, mustBePositive} = 1e-3 % [kg] - args.freq (1,1) double {mustBeNumeric, mustBePositive} = 1 % [Hz] - end + args.mass (1,1) double {mustBeNumeric, mustBePositive} = 1e-3 % [kg] + args.freq (1,1) double {mustBeNumeric, mustBePositive} = 1 % [Hz] + end - %% + %% geophone.m = args.mass; - %% The Stiffness is set to have the damping resonance frequency - geophone.k = geophone.m * (2*pi*args.freq)^2; + %% The Stiffness is set to have the damping resonance frequency + geophone.k = geophone.m * (2*pi*args.freq)^2; - %% We set the damping value to have critical damping - geophone.c = 2*sqrt(geophone.m * geophone.k); + %% We set the damping value to have critical damping + geophone.c = 2*sqrt(geophone.m * geophone.k); - %% Save - save('./mat/geophone_z_axis.mat', 'geophone'); -end + %% Save + save('./mat/geophone_z_axis.mat', 'geophone'); +end
function [accelerometer] = initializeZAxisAccelerometer(args) +function [accelerometer] = initializeZAxisAccelerometer(args) arguments - args.mass (1,1) double {mustBeNumeric, mustBePositive} = 1e-3 % [kg] - args.freq (1,1) double {mustBeNumeric, mustBePositive} = 5e3 % [Hz] - end + args.mass (1,1) double {mustBeNumeric, mustBePositive} = 1e-3 % [kg] + args.freq (1,1) double {mustBeNumeric, mustBePositive} = 5e3 % [Hz] + end - %% + %% accelerometer.m = args.mass; - %% The Stiffness is set to have the damping resonance frequency - accelerometer.k = accelerometer.m * (2*pi*args.freq)^2; + %% The Stiffness is set to have the damping resonance frequency + accelerometer.k = accelerometer.m * (2*pi*args.freq)^2; - %% We set the damping value to have critical damping - accelerometer.c = 2*sqrt(accelerometer.m * accelerometer.k); + %% We set the damping value to have critical damping + accelerometer.c = 2*sqrt(accelerometer.m * accelerometer.k); - %% Gain correction of the accelerometer to have a unity gain until the resonance - accelerometer.gain = -accelerometer.k/accelerometer.m; + %% Gain correction of the accelerometer to have a unity gain until the resonance + accelerometer.gain = -accelerometer.k/accelerometer.m; - %% Save - save('./mat/accelerometer_z_axis.mat', 'accelerometer'); -end + %% Save + save('./mat/accelerometer_z_axis.mat', 'accelerometer'); +end
Created: 2020-07-31 ven. 17:58
+Created: 2020-11-03 mar. 09:45
initializeStewartPlatform
: Initialize the Stewart Platform structure
initializeFramesPositions
: Initialize the positions of frames {A}, {B}, {F} and {M}
generateGeneralConfiguration
: Generate a Very General Configuration
computeJointsPose
: Compute the Pose of the Joints
stewart
structure elementsstewart
structure elementsstewart
structurestewart
structureinitializeStewartPose
: Determine the initial stroke in each leg to have the wanted pose
initializeCylindricalPlatforms
: Initialize the geometry of the Fixed and Mobile Platforms
initializeCylindricalStruts
: Define the inertia of cylindrical struts
initializeStrutDynamics
: Add Stiffness and Damping properties of each strut
initializeAmplifiedStrutDynamics
: Add Stiffness and Damping properties of each strut for an amplified piezoelectric actuator
+initializeJointDynamics
: Add Stiffness and Damping properties for spherical joints
-initializeJointDynamics
: Add Stiffness and Damping properties for spherical joints
-
initializeInertialSensor
: Initialize the inertial sensor in each strut
+initializeInertialSensor
: Initialize the inertial sensor in each strut
displayArchitecture
: 3D plot of the Stewart platform architecture
+displayArchitecture
: 3D plot of the Stewart platform architecture
stewart
structure elementsstewart
structure elementsdescribeStewartPlatform
: Display some text describing the current defined Stewart Platform
+describeStewartPlatform
: Display some text describing the current defined Stewart Platform
generateCubicConfiguration
: Generate a Cubic Configuration
+generateCubicConfiguration
: Generate a Cubic Configuration
stewart
structure elementsstewart
structure elementsstewart
structurestewart
structurecomputeJacobian
: Compute the Jacobian Matrix
+computeJacobian
: Compute the Jacobian Matrix
inverseKinematics
: Compute Inverse Kinematics
+inverseKinematics
: Compute Inverse Kinematics
forwardKinematicsApprox
: Compute the Approximate Forward Kinematics
+forwardKinematicsApprox
: Compute the Approximate Forward Kinematics
function [stewart] = initializeStewartPlatform() -% initializeStewartPlatform - Initialize the stewart structure -% -% Syntax: [stewart] = initializeStewartPlatform(args) -% -% Outputs: -% - stewart - A structure with the following sub-structures: -% - platform_F - -% - platform_M - -% - joints_F - -% - joints_M - -% - struts_F - -% - struts_M - -% - actuators - -% - geometry - -% - properties - +function [stewart] = initializeStewartPlatform() +% initializeStewartPlatform - Initialize the stewart structure +% +% Syntax: [stewart] = initializeStewartPlatform(args) +% +% Outputs: +% - stewart - A structure with the following sub-structures: +% - platform_F - +% - platform_M - +% - joints_F - +% - joints_M - +% - struts_F - +% - struts_M - +% - actuators - +% - geometry - +% - properties -