diff --git a/docs/bibliography.html b/docs/bibliography.html index cf434e8..e3df8d0 100644 --- a/docs/bibliography.html +++ b/docs/bibliography.html @@ -3,17 +3,13 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + Stewart Platform - Bibliography - - - - - - + +
@@ -26,12 +22,12 @@

Table of Contents

@@ -50,8 +46,8 @@ Things to add:
  • (Zheng et al. 2018)
  • -
    -

    1 Books

    +
    +

    1 Books

    @@ -92,8 +88,8 @@ Things to add: -
    -

    2 Thesis

    +
    +

    2 Thesis

    @@ -134,8 +130,8 @@ Things to add: -
    -

    3 Articles - Reviews

    +
    +

    3 Articles - Reviews

    @@ -181,8 +177,8 @@ Things to add: -
    -

    4 Articles - Design Related

    +
    +

    4 Articles - Design Related

    @@ -258,8 +254,8 @@ Things to add: -
    -

    5 Articles - Control Related

    +
    +

    5 Articles - Control Related

    @@ -1273,8 +1269,8 @@ Things to add: -
    -

    6 Articles - Other architectures

    +
    +

    6 Articles - Other architectures

    @@ -1418,7 +1414,7 @@ Things to add:

    Author: Dehaeze Thomas

    -

    Created: 2020-08-05 mer. 13:27

    +

    Created: 2021-01-08 ven. 15:30

    diff --git a/docs/control-active-damping.html b/docs/control-active-damping.html index 2f02753..8c85d19 100644 --- a/docs/control-active-damping.html +++ b/docs/control-active-damping.html @@ -3,25 +3,30 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - +Stewart Platform - Decentralized Active Damping - - - - - - - - + + + +
    @@ -34,35 +39,35 @@

    Table of Contents

    @@ -73,19 +78,19 @@ The following decentralized active damping techniques are briefly studied:

      -
    • Inertial Control (proportional feedback of the absolute velocity): Section 1
    • -
    • Integral Force Feedback: Section 2
    • -
    • Direct feedback of the relative velocity of each strut: Section 3
    • +
    • Inertial Control (proportional feedback of the absolute velocity): Section 1
    • +
    • Integral Force Feedback: Section 2
    • +
    • Direct feedback of the relative velocity of each strut: Section 3
    -
    -

    1 Inertial Control

    +
    +

    1 Inertial Control

    - +

    -
    +

    The Matlab script corresponding to this section is accessible here.

    @@ -97,56 +102,56 @@ To run the script, open the Simulink Project, and type run active_damping_
    -
    -

    1.1 Identification of the Dynamics

    +
    +

    1.1 Identification of the Dynamics

    -
    stewart = initializeStewartPlatform();
    -stewart = initializeFramesPositions(stewart, 'H', 90e-3, 'MO_B', 45e-3);
    -stewart = generateGeneralConfiguration(stewart);
    -stewart = computeJointsPose(stewart);
    -stewart = initializeStrutDynamics(stewart);
    -stewart = initializeJointDynamics(stewart, 'type_F', 'universal_p', 'type_M', 'spherical_p');
    -stewart = initializeCylindricalPlatforms(stewart);
    -stewart = initializeCylindricalStruts(stewart);
    -stewart = computeJacobian(stewart);
    -stewart = initializeStewartPose(stewart);
    -stewart = initializeInertialSensor(stewart, 'type', 'accelerometer', 'freq', 5e3);
    +
      stewart = initializeStewartPlatform();
    +  stewart = initializeFramesPositions(stewart, 'H', 90e-3, 'MO_B', 45e-3);
    +  stewart = generateGeneralConfiguration(stewart);
    +  stewart = computeJointsPose(stewart);
    +  stewart = initializeStrutDynamics(stewart);
    +  stewart = initializeJointDynamics(stewart, 'type_F', 'universal_p', 'type_M', 'spherical_p');
    +  stewart = initializeCylindricalPlatforms(stewart);
    +  stewart = initializeCylindricalStruts(stewart);
    +  stewart = computeJacobian(stewart);
    +  stewart = initializeStewartPose(stewart);
    +  stewart = initializeInertialSensor(stewart, 'type', 'accelerometer', 'freq', 5e3);
     
    -
    ground = initializeGround('type', 'rigid', 'rot_point', stewart.platform_F.FO_A);
    -payload = initializePayload('type', 'none');
    -controller = initializeController('type', 'open-loop');
    +
      ground = initializeGround('type', 'rigid', 'rot_point', stewart.platform_F.FO_A);
    +  payload = initializePayload('type', 'none');
    +  controller = initializeController('type', 'open-loop');
     
    -
    %% Options for Linearized
    -options = linearizeOptions;
    -options.SampleTime = 0;
    +
      %% Options for Linearized
    +  options = linearizeOptions;
    +  options.SampleTime = 0;
     
    -%% Name of the Simulink File
    -mdl = 'stewart_platform_model';
    +  %% Name of the Simulink File
    +  mdl = 'stewart_platform_model';
     
    -%% Input/Output definition
    -clear io; io_i = 1;
    -io(io_i) = linio([mdl, '/Controller'],        1, 'openinput');  io_i = io_i + 1; % Actuator Force Inputs [N]
    -io(io_i) = linio([mdl, '/Stewart Platform'],  1, 'openoutput', [], 'Vm'); io_i = io_i + 1; % Absolute velocity of each leg [m/s]
    +  %% Input/Output definition
    +  clear io; io_i = 1;
    +  io(io_i) = linio([mdl, '/Controller'],        1, 'openinput');  io_i = io_i + 1; % Actuator Force Inputs [N]
    +  io(io_i) = linio([mdl, '/Stewart Platform'],  1, 'openoutput', [], 'Vm'); io_i = io_i + 1; % Absolute velocity of each leg [m/s]
     
    -%% Run the linearization
    -G = linearize(mdl, io, options);
    -G.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    -G.OutputName = {'Vm1', 'Vm2', 'Vm3', 'Vm4', 'Vm5', 'Vm6'};
    +  %% Run the linearization
    +  G = linearize(mdl, io, options);
    +  G.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    +  G.OutputName = {'Vm1', 'Vm2', 'Vm3', 'Vm4', 'Vm5', 'Vm6'};
     

    -The transfer function from actuator forces to force sensors is shown in Figure 1. +The transfer function from actuator forces to force sensors is shown in Figure 1.

    -
    +

    inertial_plant_coupling.png

    Figure 1: Transfer function from the Actuator force \(F_{i}\) to the absolute velocity of the same leg \(v_{m,i}\) and to the absolute velocity of the other legs \(v_{m,j}\) with \(i \neq j\) in grey (png, pdf)

    @@ -154,17 +159,17 @@ The transfer function from actuator forces to force sensors is shown in Figure <
    -
    -

    1.2 Effect of the Flexible Joint stiffness and Actuator amplification on the Dynamics

    +
    +

    1.2 Effect of the Flexible Joint stiffness and Actuator amplification on the Dynamics

    We add some stiffness and damping in the flexible joints and we re-identify the dynamics.

    -
    stewart = initializeJointDynamics(stewart, 'type_F', 'universal', 'type_M', 'spherical');
    -Gf = linearize(mdl, io, options);
    -Gf.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    -Gf.OutputName = {'Vm1', 'Vm2', 'Vm3', 'Vm4', 'Vm5', 'Vm6'};
    +
      stewart = initializeJointDynamics(stewart, 'type_F', 'universal', 'type_M', 'spherical');
    +  Gf = linearize(mdl, io, options);
    +  Gf.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    +  Gf.OutputName = {'Vm1', 'Vm2', 'Vm3', 'Vm4', 'Vm5', 'Vm6'};
     
    @@ -172,18 +177,18 @@ Gf.OutputName = {'Vm1', 'Vm2', 'Vm3', 'Vm4', 'Vm5', 'Vm6'}; We now use the amplified actuators and re-identify the dynamics

    -
    stewart = initializeAmplifiedStrutDynamics(stewart);
    -Ga = linearize(mdl, io, options);
    -Ga.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    -Ga.OutputName = {'Vm1', 'Vm2', 'Vm3', 'Vm4', 'Vm5', 'Vm6'};
    +
      stewart = initializeAmplifiedStrutDynamics(stewart);
    +  Ga = linearize(mdl, io, options);
    +  Ga.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    +  Ga.OutputName = {'Vm1', 'Vm2', 'Vm3', 'Vm4', 'Vm5', 'Vm6'};
     

    -The new dynamics from force actuator to force sensor is shown in Figure 2. +The new dynamics from force actuator to force sensor is shown in Figure 2.

    -
    +

    inertial_plant_flexible_joint_decentralized.png

    Figure 2: Transfer function from the Actuator force \(F_{i}\) to the absolute velocity sensor \(v_{m,i}\) (png, pdf)

    @@ -191,8 +196,8 @@ The new dynamics from force actuator to force sensor is shown in Figure
    -
    -

    1.3 Obtained Damping

    +
    +

    1.3 Obtained Damping

    The control is a performed in a decentralized manner. @@ -206,10 +211,10 @@ The \(6 \times 6\) control is a diagonal matrix with pure proportional action on

    -The root locus is shown in figure 3. +The root locus is shown in figure 3.

    -
    +

    root_locus_inertial_rot_stiffness.png

    Figure 3: Root Locus plot with Decentralized Inertial Control when considering the stiffness of flexible joints (png, pdf)

    @@ -217,10 +222,10 @@ The root locus is shown in figure 3.
    -
    -

    1.4 Conclusion

    +
    +

    1.4 Conclusion

    -
    +

    We do not have guaranteed stability with Inertial control. This is because of the flexibility inside the internal sensor.

    @@ -230,14 +235,14 @@ We do not have guaranteed stability with Inertial control. This is because of th
    -
    -

    2 Integral Force Feedback

    +
    +

    2 Integral Force Feedback

    - +

    -
    +

    The Matlab script corresponding to this section is accessible here.

    @@ -249,31 +254,31 @@ To run the script, open the Simulink Project, and type run active_damping_
    -
    -

    2.1 Identification of the Dynamics with perfect Joints

    +
    +

    2.1 Identification of the Dynamics with perfect Joints

    We first initialize the Stewart platform without joint stiffness.

    -
    stewart = initializeStewartPlatform();
    -stewart = initializeFramesPositions(stewart, 'H', 90e-3, 'MO_B', 45e-3);
    -stewart = generateGeneralConfiguration(stewart);
    -stewart = computeJointsPose(stewart);
    -stewart = initializeStrutDynamics(stewart);
    -stewart = initializeJointDynamics(stewart, 'type_F', 'universal_p', 'type_M', 'spherical_p');
    -stewart = initializeCylindricalPlatforms(stewart);
    -stewart = initializeCylindricalStruts(stewart);
    -stewart = computeJacobian(stewart);
    -stewart = initializeStewartPose(stewart);
    -stewart = initializeInertialSensor(stewart, 'type', 'none');
    +
      stewart = initializeStewartPlatform();
    +  stewart = initializeFramesPositions(stewart, 'H', 90e-3, 'MO_B', 45e-3);
    +  stewart = generateGeneralConfiguration(stewart);
    +  stewart = computeJointsPose(stewart);
    +  stewart = initializeStrutDynamics(stewart);
    +  stewart = initializeJointDynamics(stewart, 'type_F', 'universal_p', 'type_M', 'spherical_p');
    +  stewart = initializeCylindricalPlatforms(stewart);
    +  stewart = initializeCylindricalStruts(stewart);
    +  stewart = computeJacobian(stewart);
    +  stewart = initializeStewartPose(stewart);
    +  stewart = initializeInertialSensor(stewart, 'type', 'none');
     
    -
    ground = initializeGround('type', 'rigid', 'rot_point', stewart.platform_F.FO_A);
    -payload = initializePayload('type', 'none');
    -controller = initializeController('type', 'open-loop');
    +
      ground = initializeGround('type', 'rigid', 'rot_point', stewart.platform_F.FO_A);
    +  payload = initializePayload('type', 'none');
    +  controller = initializeController('type', 'open-loop');
     
    @@ -281,26 +286,26 @@ controller = initializeController('type', 'open-loop'); And we identify the dynamics from force actuators to force sensors.

    -
    %% Name of the Simulink File
    -mdl = 'stewart_platform_model';
    +
      %% Name of the Simulink File
    +  mdl = 'stewart_platform_model';
     
    -%% Input/Output definition
    -clear io; io_i = 1;
    -io(io_i) = linio([mdl, '/Controller'],        1, 'openinput');  io_i = io_i + 1; % Actuator Force Inputs [N]
    -io(io_i) = linio([mdl, '/Stewart Platform'],  1, 'openoutput', [], 'Taum'); io_i = io_i + 1; % Force Sensor Outputs [N]
    +  %% Input/Output definition
    +  clear io; io_i = 1;
    +  io(io_i) = linio([mdl, '/Controller'],        1, 'openinput');  io_i = io_i + 1; % Actuator Force Inputs [N]
    +  io(io_i) = linio([mdl, '/Stewart Platform'],  1, 'openoutput', [], 'Taum'); io_i = io_i + 1; % Force Sensor Outputs [N]
     
    -%% Run the linearization
    -G = linearize(mdl, io);
    -G.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    -G.OutputName = {'Fm1', 'Fm2', 'Fm3', 'Fm4', 'Fm5', 'Fm6'};
    +  %% Run the linearization
    +  G = linearize(mdl, io);
    +  G.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    +  G.OutputName = {'Fm1', 'Fm2', 'Fm3', 'Fm4', 'Fm5', 'Fm6'};
     

    -The transfer function from actuator forces to force sensors is shown in Figure 4. +The transfer function from actuator forces to force sensors is shown in Figure 4.

    -
    +

    iff_plant_coupling.png

    Figure 4: Transfer function from the Actuator force \(F_{i}\) to the Force sensor of the same leg \(F_{m,i}\) and to the force sensor of the other legs \(F_{m,j}\) with \(i \neq j\) in grey (png, pdf)

    @@ -308,17 +313,17 @@ The transfer function from actuator forces to force sensors is shown in Figure <
    -
    -

    2.2 Effect of the Flexible Joint stiffness and Actuator amplification on the Dynamics

    +
    +

    2.2 Effect of the Flexible Joint stiffness and Actuator amplification on the Dynamics

    We add some stiffness and damping in the flexible joints and we re-identify the dynamics.

    -
    stewart = initializeJointDynamics(stewart, 'type_F', 'universal', 'type_M', 'spherical');
    -Gf = linearize(mdl, io);
    -Gf.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    -Gf.OutputName = {'Fm1', 'Fm2', 'Fm3', 'Fm4', 'Fm5', 'Fm6'};
    +
      stewart = initializeJointDynamics(stewart, 'type_F', 'universal', 'type_M', 'spherical');
    +  Gf = linearize(mdl, io);
    +  Gf.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    +  Gf.OutputName = {'Fm1', 'Fm2', 'Fm3', 'Fm4', 'Fm5', 'Fm6'};
     
    @@ -326,18 +331,18 @@ Gf.OutputName = {'Fm1', 'Fm2', 'Fm3', 'Fm4', 'Fm5', 'Fm6'}; We now use the amplified actuators and re-identify the dynamics

    -
    stewart = initializeAmplifiedStrutDynamics(stewart);
    -Ga = linearize(mdl, io);
    -Ga.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    -Ga.OutputName = {'Fm1', 'Fm2', 'Fm3', 'Fm4', 'Fm5', 'Fm6'};
    +
      stewart = initializeAmplifiedStrutDynamics(stewart);
    +  Ga = linearize(mdl, io);
    +  Ga.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    +  Ga.OutputName = {'Fm1', 'Fm2', 'Fm3', 'Fm4', 'Fm5', 'Fm6'};
     

    -The new dynamics from force actuator to force sensor is shown in Figure 5. +The new dynamics from force actuator to force sensor is shown in Figure 5.

    -
    +

    iff_plant_flexible_joint_decentralized.png

    Figure 5: Transfer function from the Actuator force \(F_{i}\) to the force sensor \(F_{m,i}\) (png, pdf)

    @@ -345,8 +350,8 @@ The new dynamics from force actuator to force sensor is shown in Figure
    -
    -

    2.3 Obtained Damping

    +
    +

    2.3 Obtained Damping

    The control is a performed in a decentralized manner. @@ -360,17 +365,17 @@ The \(6 \times 6\) control is a diagonal matrix with pure integration action on

    -The root locus is shown in figure 6 and the obtained pole damping function of the control gain is shown in figure 7. +The root locus is shown in figure 6 and the obtained pole damping function of the control gain is shown in figure 7.

    -
    +

    root_locus_iff_rot_stiffness.png

    Figure 6: Root Locus plot with Decentralized Integral Force Feedback when considering the stiffness of flexible joints (png, pdf)

    -
    +

    pole_damping_gain_iff_rot_stiffness.png

    Figure 7: Damping of the poles with respect to the gain of the Decentralized Integral Force Feedback when considering the stiffness of flexible joints (png, pdf)

    @@ -378,10 +383,10 @@ The root locus is shown in figure 6 and the obtained p
    -
    -

    2.4 Conclusion

    +
    +

    2.4 Conclusion

    -
    +

    The joint stiffness has a huge impact on the attainable active damping performance when using force sensors. Thus, if Integral Force Feedback is to be used in a Stewart platform with flexible joints, the rotational stiffness of the joints should be minimized. @@ -392,14 +397,14 @@ Thus, if Integral Force Feedback is to be used in a Stewart platform with flexib

    -
    -

    3 Direct Velocity Feedback

    +
    +

    3 Direct Velocity Feedback

    - +

    -
    +

    The Matlab script corresponding to this section is accessible here.

    @@ -411,31 +416,31 @@ To run the script, open the Simulink Project, and type run active_damping_
    -
    -

    3.1 Identification of the Dynamics with perfect Joints

    +
    +

    3.1 Identification of the Dynamics with perfect Joints

    We first initialize the Stewart platform without joint stiffness.

    -
    stewart = initializeStewartPlatform();
    -stewart = initializeFramesPositions(stewart, 'H', 90e-3, 'MO_B', 45e-3);
    -stewart = generateGeneralConfiguration(stewart);
    -stewart = computeJointsPose(stewart);
    -stewart = initializeStrutDynamics(stewart);
    -stewart = initializeJointDynamics(stewart, 'type_F', 'universal_p', 'type_M', 'spherical_p');
    -stewart = initializeCylindricalPlatforms(stewart);
    -stewart = initializeCylindricalStruts(stewart);
    -stewart = computeJacobian(stewart);
    -stewart = initializeStewartPose(stewart);
    -stewart = initializeInertialSensor(stewart, 'type', 'none');
    +
      stewart = initializeStewartPlatform();
    +  stewart = initializeFramesPositions(stewart, 'H', 90e-3, 'MO_B', 45e-3);
    +  stewart = generateGeneralConfiguration(stewart);
    +  stewart = computeJointsPose(stewart);
    +  stewart = initializeStrutDynamics(stewart);
    +  stewart = initializeJointDynamics(stewart, 'type_F', 'universal_p', 'type_M', 'spherical_p');
    +  stewart = initializeCylindricalPlatforms(stewart);
    +  stewart = initializeCylindricalStruts(stewart);
    +  stewart = computeJacobian(stewart);
    +  stewart = initializeStewartPose(stewart);
    +  stewart = initializeInertialSensor(stewart, 'type', 'none');
     
    -
    ground = initializeGround('type', 'rigid', 'rot_point', stewart.platform_F.FO_A);
    -payload = initializePayload('type', 'none');
    -controller = initializeController('type', 'open-loop');
    +
      ground = initializeGround('type', 'rigid', 'rot_point', stewart.platform_F.FO_A);
    +  payload = initializePayload('type', 'none');
    +  controller = initializeController('type', 'open-loop');
     
    @@ -443,30 +448,30 @@ controller = initializeController('type', 'open-loop'); And we identify the dynamics from force actuators to force sensors.

    -
    %% Options for Linearized
    -options = linearizeOptions;
    -options.SampleTime = 0;
    +
      %% Options for Linearized
    +  options = linearizeOptions;
    +  options.SampleTime = 0;
     
    -%% Name of the Simulink File
    -mdl = 'stewart_platform_model';
    +  %% Name of the Simulink File
    +  mdl = 'stewart_platform_model';
     
    -%% Input/Output definition
    -clear io; io_i = 1;
    -io(io_i) = linio([mdl, '/Controller'],        1, 'openinput');  io_i = io_i + 1; % Actuator Force Inputs [N]
    -io(io_i) = linio([mdl, '/Stewart Platform'],  1, 'openoutput', [], 'dLm'); io_i = io_i + 1; % Relative Displacement Outputs [m]
    +  %% Input/Output definition
    +  clear io; io_i = 1;
    +  io(io_i) = linio([mdl, '/Controller'],        1, 'openinput');  io_i = io_i + 1; % Actuator Force Inputs [N]
    +  io(io_i) = linio([mdl, '/Stewart Platform'],  1, 'openoutput', [], 'dLm'); io_i = io_i + 1; % Relative Displacement Outputs [m]
     
    -%% Run the linearization
    -G = linearize(mdl, io, options);
    -G.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    -G.OutputName = {'Dm1', 'Dm2', 'Dm3', 'Dm4', 'Dm5', 'Dm6'};
    +  %% Run the linearization
    +  G = linearize(mdl, io, options);
    +  G.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    +  G.OutputName = {'Dm1', 'Dm2', 'Dm3', 'Dm4', 'Dm5', 'Dm6'};
     

    -The transfer function from actuator forces to relative motion sensors is shown in Figure 8. +The transfer function from actuator forces to relative motion sensors is shown in Figure 8.

    -
    +

    dvf_plant_coupling.png

    Figure 8: Transfer function from the Actuator force \(F_{i}\) to the Relative Motion Sensor \(D_{m,j}\) with \(i \neq j\) (png, pdf)

    @@ -475,17 +480,17 @@ The transfer function from actuator forces to relative motion sensors is shown i
    -
    -

    3.2 Effect of the Flexible Joint stiffness and Actuator amplification on the Dynamics

    +
    +

    3.2 Effect of the Flexible Joint stiffness and Actuator amplification on the Dynamics

    We add some stiffness and damping in the flexible joints and we re-identify the dynamics.

    -
    stewart = initializeJointDynamics(stewart, 'type_F', 'universal', 'type_M', 'spherical');
    -Gf = linearize(mdl, io, options);
    -Gf.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    -Gf.OutputName = {'Dm1', 'Dm2', 'Dm3', 'Dm4', 'Dm5', 'Dm6'};
    +
      stewart = initializeJointDynamics(stewart, 'type_F', 'universal', 'type_M', 'spherical');
    +  Gf = linearize(mdl, io, options);
    +  Gf.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    +  Gf.OutputName = {'Dm1', 'Dm2', 'Dm3', 'Dm4', 'Dm5', 'Dm6'};
     
    @@ -493,18 +498,18 @@ Gf.OutputName = {'Dm1', 'Dm2', 'Dm3', 'Dm4', 'Dm5', 'Dm6'}; We now use the amplified actuators and re-identify the dynamics

    -
    stewart = initializeAmplifiedStrutDynamics(stewart);
    -Ga = linearize(mdl, io, options);
    -Ga.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    -Ga.OutputName = {'Dm1', 'Dm2', 'Dm3', 'Dm4', 'Dm5', 'Dm6'};
    +
      stewart = initializeAmplifiedStrutDynamics(stewart);
    +  Ga = linearize(mdl, io, options);
    +  Ga.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    +  Ga.OutputName = {'Dm1', 'Dm2', 'Dm3', 'Dm4', 'Dm5', 'Dm6'};
     

    -The new dynamics from force actuator to relative motion sensor is shown in Figure 9. +The new dynamics from force actuator to relative motion sensor is shown in Figure 9.

    -
    +

    dvf_plant_flexible_joint_decentralized.png

    Figure 9: Transfer function from the Actuator force \(F_{i}\) to the relative displacement sensor \(D_{m,i}\) (png, pdf)

    @@ -512,8 +517,8 @@ The new dynamics from force actuator to relative motion sensor is shown in Figur
    -
    -

    3.3 Obtained Damping

    +
    +

    3.3 Obtained Damping

    The control is a performed in a decentralized manner. @@ -527,10 +532,10 @@ The \(6 \times 6\) control is a diagonal matrix with pure derivative action on t

    -The root locus is shown in figure 10. +The root locus is shown in figure 10.

    -
    +

    root_locus_dvf_rot_stiffness.png

    Figure 10: Root Locus plot with Direct Velocity Feedback when considering the Stiffness of flexible joints (png, pdf)

    @@ -538,10 +543,10 @@ The root locus is shown in figure 10.
    -
    -

    3.4 Conclusion

    +
    +

    3.4 Conclusion

    -
    +

    Joint stiffness does increase the resonance frequencies of the system but does not change the attainable damping when using relative motion sensors.

    @@ -551,28 +556,28 @@ Joint stiffness does increase the resonance frequencies of the system but does n
    -
    -

    4 Compliance and Transmissibility Comparison

    +
    +

    4 Compliance and Transmissibility Comparison

    -
    -

    4.1 Initialization

    +
    +

    4.1 Initialization

    We first initialize the Stewart platform without joint stiffness.

    -
    stewart = initializeStewartPlatform();
    -stewart = initializeFramesPositions(stewart, 'H', 90e-3, 'MO_B', 45e-3);
    -stewart = generateGeneralConfiguration(stewart);
    -stewart = computeJointsPose(stewart);
    -stewart = initializeStrutDynamics(stewart);
    -stewart = initializeJointDynamics(stewart, 'type_F', 'universal_p', 'type_M', 'spherical_p');
    -stewart = initializeCylindricalPlatforms(stewart);
    -stewart = initializeCylindricalStruts(stewart);
    -stewart = computeJacobian(stewart);
    -stewart = initializeStewartPose(stewart);
    -stewart = initializeInertialSensor(stewart, 'type', 'none');
    +
      stewart = initializeStewartPlatform();
    +  stewart = initializeFramesPositions(stewart, 'H', 90e-3, 'MO_B', 45e-3);
    +  stewart = generateGeneralConfiguration(stewart);
    +  stewart = computeJointsPose(stewart);
    +  stewart = initializeStrutDynamics(stewart);
    +  stewart = initializeJointDynamics(stewart, 'type_F', 'universal_p', 'type_M', 'spherical_p');
    +  stewart = initializeCylindricalPlatforms(stewart);
    +  stewart = initializeCylindricalStruts(stewart);
    +  stewart = computeJacobian(stewart);
    +  stewart = initializeStewartPose(stewart);
    +  stewart = initializeInertialSensor(stewart, 'type', 'none');
     
    @@ -580,24 +585,24 @@ stewart = initializeInertialSensor(stewart, 'type', 'none'); The rotation point of the ground is located at the origin of frame \(\{A\}\).

    -
    ground = initializeGround('type', 'rigid', 'rot_point', stewart.platform_F.FO_A);
    -payload = initializePayload('type', 'none');
    -controller = initializeController('type', 'open-loop');
    +
      ground = initializeGround('type', 'rigid', 'rot_point', stewart.platform_F.FO_A);
    +  payload = initializePayload('type', 'none');
    +  controller = initializeController('type', 'open-loop');
     
    -
    -

    4.2 Identification

    +
    +

    4.2 Identification

    Let’s first identify the transmissibility and compliance in the open-loop case.

    -
    controller = initializeController('type', 'open-loop');
    -[T_ol, T_norm_ol, freqs] = computeTransmissibility();
    -[C_ol, C_norm_ol, freqs] = computeCompliance();
    +
      controller = initializeController('type', 'open-loop');
    +  [T_ol, T_norm_ol, freqs] = computeTransmissibility();
    +  [C_ol, C_norm_ol, freqs] = computeCompliance();
     
    @@ -605,11 +610,11 @@ Let’s first identify the transmissibility and compliance in the open-loop Now, let’s identify the transmissibility and compliance for the Integral Force Feedback architecture.

    -
    controller = initializeController('type', 'iff');
    -K_iff = (1e4/s)*eye(6);
    +
      controller = initializeController('type', 'iff');
    +  K_iff = (1e4/s)*eye(6);
     
    -[T_iff, T_norm_iff, ~] = computeTransmissibility();
    -[C_iff, C_norm_iff, ~] = computeCompliance();
    +  [T_iff, T_norm_iff, ~] = computeTransmissibility();
    +  [C_iff, C_norm_iff, ~] = computeCompliance();
     
    @@ -617,35 +622,35 @@ K_iff = (1e4/s)*eye(6); And for the Direct Velocity Feedback.

    -
    controller = initializeController('type', 'dvf');
    -K_dvf = 1e4*s/(1+s/2/pi/5000)*eye(6);
    +
      controller = initializeController('type', 'dvf');
    +  K_dvf = 1e4*s/(1+s/2/pi/5000)*eye(6);
     
    -[T_dvf, T_norm_dvf, ~] = computeTransmissibility();
    -[C_dvf, C_norm_dvf, ~] = computeCompliance();
    +  [T_dvf, T_norm_dvf, ~] = computeTransmissibility();
    +  [C_dvf, C_norm_dvf, ~] = computeCompliance();
     
    -
    -

    4.3 Results

    +
    +

    4.3 Results

    -
    +

    transmissibility_iff_dvf.png

    Figure 11: Obtained transmissibility for Open-Loop Control (Blue), Integral Force Feedback (Red) and Direct Velocity Feedback (Yellow) (png, pdf)

    -
    +

    compliance_iff_dvf.png

    Figure 12: Obtained compliance for Open-Loop Control (Blue), Integral Force Feedback (Red) and Direct Velocity Feedback (Yellow) (png, pdf)

    -
    +

    frobenius_norm_T_C_iff_dvf.png

    Figure 13: Frobenius norm of the Transmissibility and Compliance Matrices (png, pdf)

    @@ -656,7 +661,7 @@ K_dvf = 1e4*s/(1+s/2/pi/5000)*eye(6);

    Author: Dehaeze Thomas

    -

    Created: 2020-08-05 mer. 13:27

    +

    Created: 2021-01-08 ven. 15:30

    diff --git a/docs/control-tracking.html b/docs/control-tracking.html index 5f8ea6a..dae92a1 100644 --- a/docs/control-tracking.html +++ b/docs/control-tracking.html @@ -3,25 +3,30 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + Stewart Platform - Tracking Control - - - - - - - - + + + +
    @@ -34,79 +39,79 @@

    Table of Contents

    @@ -116,34 +121,34 @@ Let’s suppose the control objective is to position \(\bm{\mathcal{X}}\) of

    -In order to compute the pose error \(\bm{\epsilon}_\mathcal{X}\) from the actual pose \(\bm{\mathcal{X}}\) and the reference position \(\bm{r}_\mathcal{X}\), some computation is required and explained in section 5. +In order to compute the pose error \(\bm{\epsilon}_\mathcal{X}\) from the actual pose \(\bm{\mathcal{X}}\) and the reference position \(\bm{r}_\mathcal{X}\), some computation is required and explained in section 5.

    Depending of the measured quantity, different control architectures can be used:

      -
    • If the struts length \(\bm{\mathcal{L}}\) is measured, a decentralized control architecture can be used (Section 1)
    • -
    • If the pose of the mobile platform \(\bm{\mathcal{X}}\) is directly measured, a centralized control architecture can be used (Section 2)
    • -
    • If both \(\bm{\mathcal{L}}\) and \(\bm{\mathcal{X}}\) are measured, we can use an hybrid control architecture (Section 3)
    • +
    • If the struts length \(\bm{\mathcal{L}}\) is measured, a decentralized control architecture can be used (Section 1)
    • +
    • If the pose of the mobile platform \(\bm{\mathcal{X}}\) is directly measured, a centralized control architecture can be used (Section 2)
    • +
    • If both \(\bm{\mathcal{L}}\) and \(\bm{\mathcal{X}}\) are measured, we can use an hybrid control architecture (Section 3)

    -The control configuration are compare in section 4. +The control configuration are compare in section 4.

    -
    -

    1 Decentralized Control Architecture using Strut Length

    +
    +

    1 Decentralized Control Architecture using Strut Length

    - +

    -
    -

    1.1 Control Schematic

    +
    +

    1.1 Control Schematic

    -The control architecture is shown in Figure 1. +The control architecture is shown in Figure 1.

    @@ -155,7 +160,7 @@ Then, a diagonal (decentralized) controller \(\bm{K}_\mathcal{L}\) is used such

    -
    +

    decentralized_reference_tracking_L.png

    Figure 1: Decentralized control for reference tracking

    @@ -163,67 +168,67 @@ Then, a diagonal (decentralized) controller \(\bm{K}_\mathcal{L}\) is used such
    -
    -

    1.2 Initialize the Stewart platform

    +
    +

    1.2 Initialize the Stewart platform

    -
    % Stewart Platform
    -stewart = initializeStewartPlatform();
    -stewart = initializeFramesPositions(stewart, 'H', 90e-3, 'MO_B', 45e-3);
    -stewart = generateGeneralConfiguration(stewart);
    -stewart = computeJointsPose(stewart);
    -stewart = initializeStrutDynamics(stewart);
    -stewart = initializeJointDynamics(stewart, 'type_F', 'universal_p', 'type_M', 'spherical_p');
    -stewart = initializeCylindricalPlatforms(stewart);
    -stewart = initializeCylindricalStruts(stewart);
    -stewart = computeJacobian(stewart);
    -stewart = initializeStewartPose(stewart);
    -stewart = initializeInertialSensor(stewart, 'type', 'accelerometer', 'freq', 5e3);
    -
    -% Ground and Payload
    -ground = initializeGround('type', 'rigid');
    -payload = initializePayload('type', 'none');
    -
    -% Controller
    -controller = initializeController('type', 'open-loop');
    -
    -% Disturbances and References
    -disturbances = initializeDisturbances();
    -references = initializeReferences(stewart);
    +
        % Stewart Platform
    +    stewart = initializeStewartPlatform();
    +    stewart = initializeFramesPositions(stewart, 'H', 90e-3, 'MO_B', 45e-3);
    +    stewart = generateGeneralConfiguration(stewart);
    +    stewart = computeJointsPose(stewart);
    +    stewart = initializeStrutDynamics(stewart);
    +    stewart = initializeJointDynamics(stewart, 'type_F', 'universal_p', 'type_M', 'spherical_p');
    +    stewart = initializeCylindricalPlatforms(stewart);
    +    stewart = initializeCylindricalStruts(stewart);
    +    stewart = computeJacobian(stewart);
    +    stewart = initializeStewartPose(stewart);
    +    stewart = initializeInertialSensor(stewart, 'type', 'accelerometer', 'freq', 5e3);
    +  
    +    % Ground and Payload
    +    ground = initializeGround('type', 'rigid');
    +    payload = initializePayload('type', 'none');
    +  
    +    % Controller
    +    controller = initializeController('type', 'open-loop');
    +  
    +    % Disturbances and References
    +    disturbances = initializeDisturbances();
    +    references = initializeReferences(stewart);
     
    -
    -

    1.3 Identification of the plant

    +
    +

    1.3 Identification of the plant

    Let’s identify the transfer function from \(\bm{\tau}\) to \(\bm{\mathcal{L}}\).

    -
    %% Name of the Simulink File
    -mdl = 'stewart_platform_model';
    +
      %% Name of the Simulink File
    +  mdl = 'stewart_platform_model';
     
    -%% Input/Output definition
    -clear io; io_i = 1;
    -io(io_i) = linio([mdl, '/Controller'],        1, 'openinput');  io_i = io_i + 1; % Actuator Force Inputs [N]
    -io(io_i) = linio([mdl, '/Stewart Platform'],  1, 'openoutput', [], 'dLm'); io_i = io_i + 1; % Relative Displacement Outputs [m]
    +  %% Input/Output definition
    +  clear io; io_i = 1;
    +  io(io_i) = linio([mdl, '/Controller'],        1, 'openinput');  io_i = io_i + 1; % Actuator Force Inputs [N]
    +  io(io_i) = linio([mdl, '/Stewart Platform'],  1, 'openoutput', [], 'dLm'); io_i = io_i + 1; % Relative Displacement Outputs [m]
     
    -%% Run the linearization
    -G = linearize(mdl, io);
    -G.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    -G.OutputName = {'L1', 'L2', 'L3', 'L4', 'L5', 'L6'};
    +  %% Run the linearization
    +  G = linearize(mdl, io);
    +  G.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    +  G.OutputName = {'L1', 'L2', 'L3', 'L4', 'L5', 'L6'};
     
    -
    -

    1.4 Plant Analysis

    +
    +

    1.4 Plant Analysis

    -The diagonal and off-diagonal terms of the plant are shown in Figure 2. +The diagonal and off-diagonal terms of the plant are shown in Figure 2.

    @@ -232,7 +237,7 @@ We see that the plant is decoupled at low frequency which indicate that decentra

    -
    +

    plant_decentralized_L.png

    Figure 2: Obtain Diagonal and off diagonal dynamics (png, pdf)

    @@ -240,8 +245,8 @@ We see that the plant is decoupled at low frequency which indicate that decentra
    -
    -

    1.5 Controller Design

    +
    +

    1.5 Controller Design

    The controller consists of: @@ -252,17 +257,17 @@ The controller consists of:

    -The obtained loop gains corresponding to the diagonal elements are shown in Figure 3. +The obtained loop gains corresponding to the diagonal elements are shown in Figure 3.

    -
    wc = 2*pi*30;
    -Kl = diag(1./diag(abs(freqresp(G, wc)))) * wc/s * 1/(1 + s/3/wc);
    +
      wc = 2*pi*30;
    +  Kl = diag(1./diag(abs(freqresp(G, wc)))) * wc/s * 1/(1 + s/3/wc);
     
    -
    +

    loop_gain_decentralized_L.png

    Figure 3: Loop Gain of the diagonal elements (png, pdf)

    @@ -270,99 +275,99 @@ Kl = diag(1./diag(abs(freqresp(G, wc)))) * wc/s * 1/(1 + s/3/wc);
    -
    -

    1.6 Simulation

    +
    +

    1.6 Simulation

    Let’s define some reference path to follow.

    -
    t = [0:1e-4:10];
    -
    -r = zeros(6, length(t));
    -
    -r(1, :) = 1e-3.*t.*sin(2*pi*t);
    -r(2, :) = 1e-3.*t.*cos(2*pi*t);
    -r(3, :) = 1e-3.*t;
    -
    -references = initializeReferences(stewart, 't', t, 'r', r);
    +
        t = [0:1e-4:10];
    +  
    +    r = zeros(6, length(t));
    +  
    +    r(1, :) = 1e-3.*t.*sin(2*pi*t);
    +    r(2, :) = 1e-3.*t.*cos(2*pi*t);
    +    r(3, :) = 1e-3.*t;
    +  
    +    references = initializeReferences(stewart, 't', t, 'r', r);
     

    -The reference path is shown in Figure 4. +The reference path is shown in Figure 4.

    -
    figure;
    -plot3(squeeze(references.r.Data(1,1,:)), squeeze(references.r.Data(2,1,:)), squeeze(references.r.Data(3,1,:)));
    -xlabel('X [m]');
    -ylabel('Y [m]');
    -zlabel('Z [m]');
    +
      figure;
    +  plot3(squeeze(references.r.Data(1,1,:)), squeeze(references.r.Data(2,1,:)), squeeze(references.r.Data(3,1,:)));
    +  xlabel('X [m]');
    +  ylabel('Y [m]');
    +  zlabel('Z [m]');
     
    -
    +

    tracking_control_reference_path.png

    Figure 4: Reference path used for Tracking control (png, pdf)

    -
    controller = initializeController('type', 'ref-track-L');
    +
      controller = initializeController('type', 'ref-track-L');
     
    -
    set_param('stewart_platform_model', 'StopTime', '10')
    -sim('stewart_platform_model');
    -simout_D = simout;
    +
      set_param('stewart_platform_model', 'StopTime', '10')
    +  sim('stewart_platform_model');
    +  simout_D = simout;
     
    -
    save('./mat/control_tracking.mat', 'simout_D', '-append');
    +
      save('./mat/control_tracking.mat', 'simout_D', '-append');
     
    -
    -

    1.7 Results

    +
    +

    1.7 Results

    -The reference path and the position of the mobile platform are shown in Figure 5. +The reference path and the position of the mobile platform are shown in Figure 5.

    -
    figure;
    -hold on;
    -plot3(simout_D.x.Xr.Data(:, 1), simout_D.x.Xr.Data(:, 2), simout_D.x.Xr.Data(:, 3), 'k-');
    -plot3(squeeze(references.r.Data(1,1,:)), squeeze(references.r.Data(2,1,:)), squeeze(references.r.Data(3,1,:)), '--');
    -hold off;
    -xlabel('X [m]'); ylabel('Y [m]'); zlabel('Z [m]');
    -view([1,1,1])
    -zlim([0, inf]);
    +
      figure;
    +  hold on;
    +  plot3(simout_D.x.Xr.Data(:, 1), simout_D.x.Xr.Data(:, 2), simout_D.x.Xr.Data(:, 3), 'k-');
    +  plot3(squeeze(references.r.Data(1,1,:)), squeeze(references.r.Data(2,1,:)), squeeze(references.r.Data(3,1,:)), '--');
    +  hold off;
    +  xlabel('X [m]'); ylabel('Y [m]'); zlabel('Z [m]');
    +  view([1,1,1])
    +  zlim([0, inf]);
     
    -
    +

    decentralized_control_3d_pos.png

    Figure 5: Reference path and Obtained Position (png, pdf)

    -
    +

    decentralized_control_Ex.png

    Figure 6: Position error \(\bm{\epsilon}_\mathcal{X}\) (png, pdf)

    -
    +

    decentralized_control_El.png

    Figure 7: Position error \(\bm{\epsilon}_\mathcal{L}\) (png, pdf)

    @@ -370,8 +375,8 @@ zlim([0, inf]);
    -
    -

    1.8 Conclusion

    +
    +

    1.8 Conclusion

    Such control architecture is easy to implement and give good results. @@ -385,18 +390,18 @@ However, as \(\mathcal{X}\) is not directly measured, it is possible that import

    -
    -

    2 Centralized Control Architecture using Pose Measurement

    +
    +

    2 Centralized Control Architecture using Pose Measurement

    - +

    -
    -

    2.1 Control Schematic

    +
    +

    2.1 Control Schematic

    -The centralized controller takes the position error \(\bm{\epsilon}_\mathcal{X}\) as an inputs and generate actuator forces \(\bm{\tau}\) (see Figure 8). +The centralized controller takes the position error \(\bm{\epsilon}_\mathcal{X}\) as an inputs and generate actuator forces \(\bm{\tau}\) (see Figure 8). The signals are:

      @@ -407,7 +412,7 @@ The signals are:
    -
    +

    centralized_reference_tracking.png

    Figure 8: Centralized Controller

    @@ -418,89 +423,89 @@ Instead of designing a full MIMO controller \(K\), we first try to make the plan

    -We can think of two ways to make the plant more diagonal that are described in sections 2.4 and 2.5. +We can think of two ways to make the plant more diagonal that are described in sections 2.4 and 2.5.

    -
    +

    -Note here that the subtraction shown in Figure 8 is not a real subtraction. -It is indeed a more complex computation explained in section 5. +Note here that the subtraction shown in Figure 8 is not a real subtraction. +It is indeed a more complex computation explained in section 5.

    -
    -

    2.2 Initialize the Stewart platform

    +
    +

    2.2 Initialize the Stewart platform

    -
    % Stewart Platform
    -stewart = initializeStewartPlatform();
    -stewart = initializeFramesPositions(stewart, 'H', 90e-3, 'MO_B', 45e-3);
    -stewart = generateGeneralConfiguration(stewart);
    -stewart = computeJointsPose(stewart);
    -stewart = initializeStrutDynamics(stewart);
    -stewart = initializeJointDynamics(stewart, 'type_F', 'universal_p', 'type_M', 'spherical_p');
    -stewart = initializeCylindricalPlatforms(stewart);
    -stewart = initializeCylindricalStruts(stewart);
    -stewart = computeJacobian(stewart);
    -stewart = initializeStewartPose(stewart);
    -stewart = initializeInertialSensor(stewart, 'type', 'accelerometer', 'freq', 5e3);
    -
    -% Ground and Payload
    -ground = initializeGround('type', 'rigid');
    -payload = initializePayload('type', 'none');
    -
    -% Controller
    -controller = initializeController('type', 'open-loop');
    -
    -% Disturbances and References
    -disturbances = initializeDisturbances();
    -references = initializeReferences(stewart);
    +
        % Stewart Platform
    +    stewart = initializeStewartPlatform();
    +    stewart = initializeFramesPositions(stewart, 'H', 90e-3, 'MO_B', 45e-3);
    +    stewart = generateGeneralConfiguration(stewart);
    +    stewart = computeJointsPose(stewart);
    +    stewart = initializeStrutDynamics(stewart);
    +    stewart = initializeJointDynamics(stewart, 'type_F', 'universal_p', 'type_M', 'spherical_p');
    +    stewart = initializeCylindricalPlatforms(stewart);
    +    stewart = initializeCylindricalStruts(stewart);
    +    stewart = computeJacobian(stewart);
    +    stewart = initializeStewartPose(stewart);
    +    stewart = initializeInertialSensor(stewart, 'type', 'accelerometer', 'freq', 5e3);
    +  
    +    % Ground and Payload
    +    ground = initializeGround('type', 'rigid');
    +    payload = initializePayload('type', 'none');
    +  
    +    % Controller
    +    controller = initializeController('type', 'open-loop');
    +  
    +    % Disturbances and References
    +    disturbances = initializeDisturbances();
    +    references = initializeReferences(stewart);
     
    -
    -

    2.3 Identification of the plant

    +
    +

    2.3 Identification of the plant

    Let’s identify the transfer function from \(\bm{\tau}\) to \(\bm{\mathcal{X}}\).

    -
    %% Name of the Simulink File
    -mdl = 'stewart_platform_model';
    +
      %% Name of the Simulink File
    +  mdl = 'stewart_platform_model';
     
    -%% Input/Output definition
    -clear io; io_i = 1;
    -io(io_i) = linio([mdl, '/Controller'],        1, 'openinput');  io_i = io_i + 1; % Actuator Force Inputs [N]
    -io(io_i) = linio([mdl, '/Relative Motion Sensor'],  1, 'openoutput'); io_i = io_i + 1; % Relative Displacement Outputs [m]
    +  %% Input/Output definition
    +  clear io; io_i = 1;
    +  io(io_i) = linio([mdl, '/Controller'],        1, 'openinput');  io_i = io_i + 1; % Actuator Force Inputs [N]
    +  io(io_i) = linio([mdl, '/Relative Motion Sensor'],  1, 'openoutput'); io_i = io_i + 1; % Relative Displacement Outputs [m]
     
    -%% Run the linearization
    -G = linearize(mdl, io);
    -G.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    -G.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
    +  %% Run the linearization
    +  G = linearize(mdl, io);
    +  G.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    +  G.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
     
    -
    -

    2.4 Diagonal Control - Leg’s Frame

    +
    +

    2.4 Diagonal Control - Leg’s Frame

    - +

    -
    -

    2.4.1 Control Architecture

    +
    +

    2.4.1 Control Architecture

    The pose error \(\bm{\epsilon}_\mathcal{X}\) is first converted in the frame of the leg by using the Jacobian matrix. Then a diagonal controller \(\bm{K}_\mathcal{L}\) is designed. -The final implemented controller is \(\bm{K} = \bm{K}_\mathcal{L} \cdot \bm{J}\) as shown in Figure 9 +The final implemented controller is \(\bm{K} = \bm{K}_\mathcal{L} \cdot \bm{J}\) as shown in Figure 9

    @@ -508,7 +513,7 @@ Note here that the transformation from the pose error \(\bm{\epsilon}_\mathcal{X

    -
    +

    centralized_reference_tracking_L.png

    Figure 9: Controller in the frame of the legs

    @@ -516,27 +521,27 @@ Note here that the transformation from the pose error \(\bm{\epsilon}_\mathcal{X
    -
    -

    2.4.2 Plant Analysis

    +
    +

    2.4.2 Plant Analysis

    -We now multiply the plant by the Jacobian matrix as shown in Figure 9 to obtain a more diagonal plant. +We now multiply the plant by the Jacobian matrix as shown in Figure 9 to obtain a more diagonal plant.

    -
    Gl = stewart.kinematics.J*G;
    -Gl.OutputName  = {'D1', 'D2', 'D3', 'D4', 'D5', 'D6'};
    +
      Gl = stewart.kinematics.J*G;
    +  Gl.OutputName  = {'D1', 'D2', 'D3', 'D4', 'D5', 'D6'};
     

    -The bode plot of the plant is shown in Figure 10. +The bode plot of the plant is shown in Figure 10. We can see that the diagonal elements are identical. This will simplify the design of the controller as all the elements of the diagonal controller can be made identical.

    -
    +

    plant_centralized_L.png

    Figure 10: Diagonal and off-diagonal elements of the plant \(\bm{J}\bm{G}\) (png, pdf)

    @@ -557,8 +562,8 @@ Thus \(J \cdot G(\omega = 0) = J \cdot \frac{\delta\bm{\mathcal{X}}}{\delta\bm{\
    -
    -

    2.4.3 Controller Design

    +
    +

    2.4.3 Controller Design

    The controller consists of: @@ -569,17 +574,17 @@ The controller consists of:

    -The obtained loop gains corresponding to the diagonal elements are shown in Figure 11. +The obtained loop gains corresponding to the diagonal elements are shown in Figure 11.

    -
    wc = 2*pi*30;
    -Kl = diag(1./diag(abs(freqresp(Gl, wc)))) * wc/s * 1/(1 + s/3/wc);
    +
      wc = 2*pi*30;
    +  Kl = diag(1./diag(abs(freqresp(Gl, wc)))) * wc/s * 1/(1 + s/3/wc);
     
    -
    +

    loop_gain_centralized_L.png

    Figure 11: Loop Gain of the diagonal elements (png, pdf)

    @@ -589,33 +594,33 @@ Kl = diag(1./diag(abs(freqresp(Gl, wc)))) * wc/s * 1/(1 + s/3/wc); The controller \(\bm{K} = \bm{K}_\mathcal{L} \bm{J}\) is computed.

    -
    K = Kl*stewart.kinematics.J;
    +
      K = Kl*stewart.kinematics.J;
     
    -
    -

    2.4.4 Simulation

    +
    +

    2.4.4 Simulation

    We specify the reference path to follow.

    -
    t = [0:1e-4:10];
    -
    -r = zeros(6, length(t));
    -
    -r(1, :) = 1e-3.*t.*sin(2*pi*t);
    -r(2, :) = 1e-3.*t.*cos(2*pi*t);
    -r(3, :) = 1e-3.*t;
    -
    -references = initializeReferences(stewart, 't', t, 'r', r);
    +
        t = [0:1e-4:10];
    +  
    +    r = zeros(6, length(t));
    +  
    +    r(1, :) = 1e-3.*t.*sin(2*pi*t);
    +    r(2, :) = 1e-3.*t.*cos(2*pi*t);
    +    r(3, :) = 1e-3.*t;
    +  
    +    references = initializeReferences(stewart, 't', t, 'r', r);
     
    -
    controller = initializeController('type', 'ref-track-X');
    +
      controller = initializeController('type', 'ref-track-X');
     
    @@ -623,28 +628,28 @@ references = initializeReferences(stewart, 't', t, 'r', r); We run the simulation and we save the results.

    -
    set_param('stewart_platform_model', 'StopTime', '10')
    -sim('stewart_platform_model')
    -simout_L = simout;
    -save('./mat/control_tracking.mat', 'simout_L', '-append');
    +
      set_param('stewart_platform_model', 'StopTime', '10')
    +  sim('stewart_platform_model')
    +  simout_L = simout;
    +  save('./mat/control_tracking.mat', 'simout_L', '-append');
     
    -
    -

    2.5 Diagonal Control - Cartesian Frame

    +
    +

    2.5 Diagonal Control - Cartesian Frame

    - +

    -
    -

    2.5.1 Control Architecture

    +
    +

    2.5.1 Control Architecture

    -A diagonal controller \(\bm{K}_\mathcal{X}\) take the pose error \(\bm{\epsilon}_\mathcal{X}\) and generate cartesian forces \(\bm{\mathcal{F}}\) that are then converted to actuators forces using the Jacobian as shown in Figure e 12. +A diagonal controller \(\bm{K}_\mathcal{X}\) take the pose error \(\bm{\epsilon}_\mathcal{X}\) and generate cartesian forces \(\bm{\mathcal{F}}\) that are then converted to actuators forces using the Jacobian as shown in Figure e 12.

    @@ -652,7 +657,7 @@ The final implemented controller is \(\bm{K} = \bm{J}^{-T} \cdot \bm{K}_\mathcal

    -
    +

    centralized_reference_tracking_X.png

    Figure 12: Controller in the cartesian frame

    @@ -660,21 +665,21 @@ The final implemented controller is \(\bm{K} = \bm{J}^{-T} \cdot \bm{K}_\mathcal
    -
    -

    2.5.2 Plant Analysis

    +
    +

    2.5.2 Plant Analysis

    -We now multiply the plant by the Jacobian matrix as shown in Figure 12 to obtain a more diagonal plant. +We now multiply the plant by the Jacobian matrix as shown in Figure 12 to obtain a more diagonal plant.

    -
    Gx = G*inv(stewart.kinematics.J');
    -Gx.InputName  = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'};
    +
      Gx = G*inv(stewart.kinematics.J');
    +  Gx.InputName  = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'};
     
    -
    +

    plant_centralized_X.png

    Figure 13: Diagonal and off-diagonal elements of the plant \(\bm{G} \bm{J}^{-T}\) (png, pdf)

    @@ -776,8 +781,8 @@ This control architecture can also give a dynamically decoupled plant if the Cen
    -
    -

    2.5.3 Controller Design

    +
    +

    2.5.3 Controller Design

    The controller consists of: @@ -788,17 +793,17 @@ The controller consists of:

    -The obtained loop gains corresponding to the diagonal elements are shown in Figure 14. +The obtained loop gains corresponding to the diagonal elements are shown in Figure 14.

    -
    wc = 2*pi*30;
    -Kx = diag(1./diag(abs(freqresp(Gx, wc)))) * wc/s * 1/(1 + s/3/wc);
    +
      wc = 2*pi*30;
    +  Kx = diag(1./diag(abs(freqresp(Gx, wc)))) * wc/s * 1/(1 + s/3/wc);
     
    -
    +

    loop_gain_centralized_X.png

    Figure 14: Loop Gain of the diagonal elements (png, pdf)

    @@ -808,33 +813,33 @@ Kx = diag(1./diag(abs(freqresp(Gx, wc)))) * wc/s * 1/(1 + s/3/wc); The controller \(\bm{K} = \bm{J}^{-T} \bm{K}_\mathcal{X}\) is computed.

    -
    K = inv(stewart.kinematics.J')*Kx;
    +
      K = inv(stewart.kinematics.J')*Kx;
     
    -
    -

    2.5.4 Simulation

    +
    +

    2.5.4 Simulation

    We specify the reference path to follow.

    -
    t = [0:1e-4:10];
    -
    -r = zeros(6, length(t));
    -
    -r(1, :) = 1e-3.*t.*sin(2*pi*t);
    -r(2, :) = 1e-3.*t.*cos(2*pi*t);
    -r(3, :) = 1e-3.*t;
    -
    -references = initializeReferences(stewart, 't', t, 'r', r);
    +
        t = [0:1e-4:10];
    +  
    +    r = zeros(6, length(t));
    +  
    +    r(1, :) = 1e-3.*t.*sin(2*pi*t);
    +    r(2, :) = 1e-3.*t.*cos(2*pi*t);
    +    r(3, :) = 1e-3.*t;
    +  
    +    references = initializeReferences(stewart, 't', t, 'r', r);
     
    -
    controller = initializeController('type', 'ref-track-X');
    +
      controller = initializeController('type', 'ref-track-X');
     
    @@ -842,25 +847,25 @@ references = initializeReferences(stewart, 't', t, 'r', r); We run the simulation and we save the results.

    -
    set_param('stewart_platform_model', 'StopTime', '10')
    -sim('stewart_platform_model')
    -simout_X = simout;
    -save('./mat/control_tracking.mat', 'simout_X', '-append');
    +
      set_param('stewart_platform_model', 'StopTime', '10')
    +  sim('stewart_platform_model')
    +  simout_X = simout;
    +  save('./mat/control_tracking.mat', 'simout_X', '-append');
     
    -
    -

    2.6 Diagonal Control - Steady State Decoupling

    +
    +

    2.6 Diagonal Control - Steady State Decoupling

    - +

    -
    -

    2.6.1 Control Architecture

    +
    +

    2.6.1 Control Architecture

    The plant \(\bm{G}\) is pre-multiply by \(\bm{G}^{-1}(\omega = 0)\) such that the “shaped plant” \(\bm{G}_0 = \bm{G} \bm{G}^{-1}(\omega = 0)\) is diagonal at low frequency. @@ -871,11 +876,11 @@ Then a diagonal controller \(\bm{K}_0\) is designed.

    -The control architecture is shown in Figure 15. +The control architecture is shown in Figure 15.

    -
    +

    centralized_reference_tracking_S.png

    Figure 15: Static Decoupling of the Plant

    @@ -883,21 +888,21 @@ The control architecture is shown in Figure 15.
    -
    -

    2.6.2 Plant Analysis

    +
    +

    2.6.2 Plant Analysis

    The plant is pre-multiplied by \(\bm{G}^{-1}(\omega = 0)\). -The diagonal and off-diagonal elements of the shaped plant are shown in Figure 16. +The diagonal and off-diagonal elements of the shaped plant are shown in Figure 16.

    -
    G0 = G*inv(freqresp(G, 0));
    +
      G0 = G*inv(freqresp(G, 0));
     
    -
    +

    plant_centralized_SD.png

    Figure 16: Diagonal and off-diagonal elements of the plant \(\bm{G} \bm{G}^{-1}(\omega = 0)\) (png, pdf)

    @@ -905,8 +910,8 @@ The diagonal and off-diagonal elements of the shaped plant are shown in Figure <
    -
    -

    2.6.3 Controller Design

    +
    +

    2.6.3 Controller Design

    We have that: @@ -921,21 +926,21 @@ And because:

  • the controller equal to a \(\bm{K}_0(s) = k(s) \bm{I}_6\)
  • -We have that \(\bm{K}_0(s)\) commutes with \(\bm{G}^{-1}(\omega = 0)\) and thus the overall controller \(\bm{K}\) is the same as the one obtain in section 2.4. +We have that \(\bm{K}_0(s)\) commutes with \(\bm{G}^{-1}(\omega = 0)\) and thus the overall controller \(\bm{K}\) is the same as the one obtain in section 2.4.

    -
    -

    2.7 Comparison

    +
    +

    2.7 Comparison

    -
    -

    2.7.1 Obtained MIMO Controllers

    +
    +

    2.7.1 Obtained MIMO Controllers

    -
    +

    centralized_control_comp_K.png

    Figure 17: Comparison of the MIMO controller \(\bm{K}\) for both centralized architectures (png, pdf)

    @@ -943,15 +948,15 @@ We have that \(\bm{K}_0(s)\) commutes with \(\bm{G}^{-1}(\omega = 0)\) and thus
    -
    -

    2.7.2 Simulation Results

    +
    +

    2.7.2 Simulation Results

    -The position error \(\bm{\epsilon}_\mathcal{X}\) for both centralized architecture are shown in Figure 18. +The position error \(\bm{\epsilon}_\mathcal{X}\) for both centralized architecture are shown in Figure 18.

    -Based on Figure 18, we can see that: +Based on Figure 18, we can see that:

    • There is some tracking error \(\epsilon_x\)
    • @@ -963,7 +968,7 @@ This error is much lower when using the diagonal control in the frame of the leg
    -
    +

    centralized_control_comp_Ex.png

    Figure 18: Comparison of the position error \(\bm{\epsilon}_\mathcal{X}\) for both centralized controllers (png, pdf)

    @@ -972,18 +977,18 @@ This error is much lower when using the diagonal control in the frame of the leg
    -
    -

    2.8 Conclusion

    +
    +

    2.8 Conclusion

    Both control architecture gives similar results even tough the control in the Leg’s frame gives slightly better results.

    -The main differences between the control architectures used in sections 2.4 and 2.5 are summarized in Table 1. +The main differences between the control architectures used in sections 2.4 and 2.5 are summarized in Table 1.

    -
    +
    @@ -1049,18 +1054,18 @@ Thus, this method should be quite robust against parameter variation (e.g. the p -
    -

    3 Hybrid Control Architecture - HAC-LAC with relative DVF

    +
    +

    3 Hybrid Control Architecture - HAC-LAC with relative DVF

    - +

    -
    -

    3.1 Control Schematic

    +
    +

    3.1 Control Schematic

    -Let’s consider the control schematic shown in Figure 19. +Let’s consider the control schematic shown in Figure 19.

    @@ -1090,7 +1095,7 @@ This second loop is responsible for the reference tracking.

    -
    +

    hybrid_reference_tracking.png

    Figure 19: Hybrid Control Architecture

    @@ -1098,75 +1103,75 @@ This second loop is responsible for the reference tracking.
    -
    -

    3.2 Initialize the Stewart platform

    +
    +

    3.2 Initialize the Stewart platform

    -
    % Stewart Platform
    -stewart = initializeStewartPlatform();
    -stewart = initializeFramesPositions(stewart, 'H', 90e-3, 'MO_B', 45e-3);
    -stewart = generateGeneralConfiguration(stewart);
    -stewart = computeJointsPose(stewart);
    -stewart = initializeStrutDynamics(stewart);
    -stewart = initializeJointDynamics(stewart, 'type_F', 'universal_p', 'type_M', 'spherical_p');
    -stewart = initializeCylindricalPlatforms(stewart);
    -stewart = initializeCylindricalStruts(stewart);
    -stewart = computeJacobian(stewart);
    -stewart = initializeStewartPose(stewart);
    -stewart = initializeInertialSensor(stewart, 'type', 'accelerometer', 'freq', 5e3);
    -
    -% Ground and Payload
    -ground = initializeGround('type', 'rigid');
    -payload = initializePayload('type', 'none');
    -
    -% Controller
    -controller = initializeController('type', 'open-loop');
    -
    -% Disturbances and References
    -disturbances = initializeDisturbances();
    -references = initializeReferences(stewart);
    +
        % Stewart Platform
    +    stewart = initializeStewartPlatform();
    +    stewart = initializeFramesPositions(stewart, 'H', 90e-3, 'MO_B', 45e-3);
    +    stewart = generateGeneralConfiguration(stewart);
    +    stewart = computeJointsPose(stewart);
    +    stewart = initializeStrutDynamics(stewart);
    +    stewart = initializeJointDynamics(stewart, 'type_F', 'universal_p', 'type_M', 'spherical_p');
    +    stewart = initializeCylindricalPlatforms(stewart);
    +    stewart = initializeCylindricalStruts(stewart);
    +    stewart = computeJacobian(stewart);
    +    stewart = initializeStewartPose(stewart);
    +    stewart = initializeInertialSensor(stewart, 'type', 'accelerometer', 'freq', 5e3);
    +  
    +    % Ground and Payload
    +    ground = initializeGround('type', 'rigid');
    +    payload = initializePayload('type', 'none');
    +  
    +    % Controller
    +    controller = initializeController('type', 'open-loop');
    +  
    +    % Disturbances and References
    +    disturbances = initializeDisturbances();
    +    references = initializeReferences(stewart);
     
    -
    -

    3.3 First Control Loop - \(\bm{K}_\mathcal{L}\)

    +
    +

    3.3 First Control Loop - \(\bm{K}_\mathcal{L}\)

    -
    -

    3.3.1 Identification

    +
    +

    3.3.1 Identification

    Let’s identify the transfer function from \(\bm{\tau}\) to \(\bm{L}\).

    -
    %% Name of the Simulink File
    -mdl = 'stewart_platform_model';
    +
      %% Name of the Simulink File
    +  mdl = 'stewart_platform_model';
     
    -%% Input/Output definition
    -clear io; io_i = 1;
    -io(io_i) = linio([mdl, '/Controller'],        1, 'openinput');  io_i = io_i + 1; % Actuator Force Inputs [N]
    -io(io_i) = linio([mdl, '/Stewart Platform'],  1, 'openoutput', [], 'dLm'); io_i = io_i + 1; % Relative Displacement Outputs [m]
    +  %% Input/Output definition
    +  clear io; io_i = 1;
    +  io(io_i) = linio([mdl, '/Controller'],        1, 'openinput');  io_i = io_i + 1; % Actuator Force Inputs [N]
    +  io(io_i) = linio([mdl, '/Stewart Platform'],  1, 'openoutput', [], 'dLm'); io_i = io_i + 1; % Relative Displacement Outputs [m]
     
    -%% Run the linearization
    -Gl = linearize(mdl, io);
    -Gl.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    -Gl.OutputName = {'L1', 'L2', 'L3', 'L4', 'L5', 'L6'};
    +  %% Run the linearization
    +  Gl = linearize(mdl, io);
    +  Gl.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    +  Gl.OutputName = {'L1', 'L2', 'L3', 'L4', 'L5', 'L6'};
     
    -
    -

    3.3.2 Obtained Plant

    +
    +

    3.3.2 Obtained Plant

    -The obtained plant is shown in Figure 20. +The obtained plant is shown in Figure 20.

    -
    +

    hybrid_control_Kl_plant.png

    Figure 20: Diagonal and off-diagonal elements of the plant for the design of \(\bm{K}_\mathcal{L}\) (png, pdf)

    @@ -1174,8 +1179,8 @@ The obtained plant is shown in Figure 20.
    -
    -

    3.3.3 Controller Design

    +
    +

    3.3.3 Controller Design

    We apply a decentralized (diagonal) direct velocity feedback. @@ -1185,16 +1190,16 @@ The gain of the controller is chosen such that the resonances are critically dam

    -The obtain loop gain is shown in Figure 21. +The obtain loop gain is shown in Figure 21.

    -
    Kl = 1e4 * s / (1 + s/2/pi/1e4) * eye(6);
    +
      Kl = 1e4 * s / (1 + s/2/pi/1e4) * eye(6);
     
    -
    +

    hybrid_control_Kl_loop_gain.png

    Figure 21: Obtain Loop Gain for the DVF control loop (png, pdf)

    @@ -1203,55 +1208,55 @@ The obtain loop gain is shown in Figure 21.
    -
    -

    3.4 Second Control Loop - \(\bm{K}_\mathcal{X}\)

    +
    +

    3.4 Second Control Loop - \(\bm{K}_\mathcal{X}\)

    -
    -

    3.4.1 Identification

    +
    +

    3.4.1 Identification

    -
    Kx = tf(zeros(6));
    +
      Kx = tf(zeros(6));
     
    -controller = initializeController('type', 'ref-track-hac-dvf');
    +  controller = initializeController('type', 'ref-track-hac-dvf');
     
    -
    %% Name of the Simulink File
    -mdl = 'stewart_platform_model';
    +
      %% Name of the Simulink File
    +  mdl = 'stewart_platform_model';
     
    -%% Input/Output definition
    -clear io; io_i = 1;
    -io(io_i) = linio([mdl, '/Controller'],              1, 'input');  io_i = io_i + 1; % Actuator Force Inputs [N]
    -io(io_i) = linio([mdl, '/Relative Motion Sensor'],  1, 'openoutput'); io_i = io_i + 1; % Relative Displacement Outputs [m]
    +  %% Input/Output definition
    +  clear io; io_i = 1;
    +  io(io_i) = linio([mdl, '/Controller'],              1, 'input');  io_i = io_i + 1; % Actuator Force Inputs [N]
    +  io(io_i) = linio([mdl, '/Relative Motion Sensor'],  1, 'openoutput'); io_i = io_i + 1; % Relative Displacement Outputs [m]
     
    -%% Run the linearization
    -G = linearize(mdl, io);
    -G.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    -G.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
    +  %% Run the linearization
    +  G = linearize(mdl, io);
    +  G.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    +  G.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
     
    -
    -

    3.4.2 Obtained Plant

    +
    +

    3.4.2 Obtained Plant

    We use the Jacobian matrix to apply forces in the cartesian frame.

    -
    Gx = G*inv(stewart.kinematics.J');
    -Gx.InputName  = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'};
    +
      Gx = G*inv(stewart.kinematics.J');
    +  Gx.InputName  = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'};
     

    -The obtained plant is shown in Figure 22. +The obtained plant is shown in Figure 22.

    -
    +

    hybrid_control_Kx_plant.png

    Figure 22: Diagonal and Off-diagonal elements of the plant for the design of \(\bm{K}_\mathcal{L}\) (png, pdf)

    @@ -1259,8 +1264,8 @@ The obtained plant is shown in Figure 22.
    -
    -

    3.4.3 Controller Design

    +
    +

    3.4.3 Controller Design

    The controller consists of: @@ -1273,19 +1278,19 @@ The controller consists of:

    -
    wc = 2*pi*200; % Bandwidth Bandwidth [rad/s]
    +
      wc = 2*pi*200; % Bandwidth Bandwidth [rad/s]
     
    -h = 3; % Lead parameter
    +  h = 3; % Lead parameter
     
    -Kx = (1/h) * (1 + s/wc*h)/(1 + s/wc/h) * wc/s * ((s/wc*2 + 1)/(s/wc*2)) * (1/(1 + s/wc/3));
    +  Kx = (1/h) * (1 + s/wc*h)/(1 + s/wc/h) * wc/s * ((s/wc*2 + 1)/(s/wc*2)) * (1/(1 + s/wc/3));
     
    -% Normalization of the gain of have a loop gain of 1 at frequency wc
    -Kx = Kx.*diag(1./diag(abs(freqresp(Gx*Kx, wc))));
    +  % Normalization of the gain of have a loop gain of 1 at frequency wc
    +  Kx = Kx.*diag(1./diag(abs(freqresp(Gx*Kx, wc))));
     
    -
    +

    hybrid_control_Kx_loop_gain.png

    Figure 23: Obtained Loop Gain for the controller \(\bm{K}_\mathcal{X}\) (png, pdf)

    @@ -1295,29 +1300,29 @@ Kx = Kx.*diag(1./diag(abs(freqresp(Gx*Kx, wc)))); Then we include the Jacobian in the controller matrix.

    -
    Kx = inv(stewart.kinematics.J')*Kx;
    +
      Kx = inv(stewart.kinematics.J')*Kx;
     
    -
    -

    3.5 Simulations

    +
    +

    3.5 Simulations

    We specify the reference path to follow.

    -
    t = [0:1e-4:10];
    -
    -r = zeros(6, length(t));
    -
    -r(1, :) = 1e-3.*t.*sin(2*pi*t);
    -r(2, :) = 1e-3.*t.*cos(2*pi*t);
    -r(3, :) = 1e-3.*t;
    -
    -references = initializeReferences(stewart, 't', t, 'r', r);
    +
        t = [0:1e-4:10];
    +  
    +    r = zeros(6, length(t));
    +  
    +    r(1, :) = 1e-3.*t.*sin(2*pi*t);
    +    r(2, :) = 1e-3.*t.*cos(2*pi*t);
    +    r(3, :) = 1e-3.*t;
    +  
    +    references = initializeReferences(stewart, 't', t, 'r', r);
     
    @@ -1325,19 +1330,19 @@ references = initializeReferences(stewart, 't', t, 'r', r); We run the simulation and we save the results.

    -
    set_param('stewart_platform_model', 'StopTime', '10')
    -sim('stewart_platform_model')
    -simout_H = simout;
    -save('./mat/control_tracking.mat', 'simout_H', '-append');
    +
      set_param('stewart_platform_model', 'StopTime', '10')
    +  sim('stewart_platform_model')
    +  simout_H = simout;
    +  save('./mat/control_tracking.mat', 'simout_H', '-append');
     

    -The obtained position error is shown in Figure 24. +The obtained position error is shown in Figure 24.

    -
    +

    hybrid_control_Ex.png

    Figure 24: Obtained position error \(\bm{\epsilon}_\mathcal{X}\) (png, pdf)

    @@ -1345,28 +1350,28 @@ The obtained position error is shown in Figure 24.
    -
    -

    3.6 Conclusion

    +
    +

    3.6 Conclusion

    -
    -

    4 Comparison of all the methods

    +
    +

    4 Comparison of all the methods

    - +

    -Let’s load the simulation results and compare them in Figure 25. +Let’s load the simulation results and compare them in Figure 25.

    -
    load('./mat/control_tracking.mat', 'simout_D', 'simout_L', 'simout_X', 'simout_H');
    +
      load('./mat/control_tracking.mat', 'simout_D', 'simout_L', 'simout_X', 'simout_H');
     
    -
    +

    reference_tracking_performance_comparison.png

    Figure 25: Comparison of the position errors for all the Control architecture used (png, pdf)

    @@ -1374,11 +1379,11 @@ Let’s load the simulation results and compare them in Figure -

    5 Compute the pose error of the Stewart Platform

    +
    +

    5 Compute the pose error of the Stewart Platform

    - +

    @@ -1398,12 +1403,12 @@ The center of the frame if \(O_W\) Reference Position with respect to fixed frame {W}: \({}^WT_R\)

    -
    Dxr = 0;
    -Dyr = 0;
    -Dzr = 0.1;
    -Rxr = pi;
    -Ryr = 0;
    -Rzr = 0;
    +
      Dxr = 0;
    +  Dyr = 0;
    +  Dzr = 0.1;
    +  Rxr = pi;
    +  Ryr = 0;
    +  Rzr = 0;
     
    @@ -1411,12 +1416,12 @@ Rzr = 0; Measured Position with respect to fixed frame {W}: \({}^WT_M\)

    -
    Dxm = 0;
    -Dym = 0;
    -Dzm = 0;
    -Rxm = pi;
    -Rym = 0;
    -Rzm = 0;
    +
      Dxm = 0;
    +  Dym = 0;
    +  Dzm = 0;
    +  Rxm = pi;
    +  Rym = 0;
    +  Rzm = 0;
     
    @@ -1425,19 +1430,19 @@ We measure the position and orientation (pose) of the element represented by the Thus we can compute the Homogeneous transformation matrix \({}^WT_M\).

    -
    %% Measured Pose
    -WTm = zeros(4,4);
    +
        %% Measured Pose
    +    WTm = zeros(4,4);
     
    -WTm(1:3, 1:3) = [cos(Rzm) -sin(Rzm) 0;
    -     sin(Rzm)  cos(Rzm) 0;
    -     0        0         1] * ...
    -    [cos(Rym)  0        sin(Rym);
    -     0        1        0;
    -     -sin(Rym)  0        cos(Rym)] * ...
    -    [1        0        0;
    -     0        cos(Rxm) -sin(Rxm);
    -     0        sin(Rxm)  cos(Rxm)];
    -WTm(1:4, 4) = [Dxm ; Dym ; Dzm; 1];
    +    WTm(1:3, 1:3) = [cos(Rzm) -sin(Rzm) 0;
    +         sin(Rzm)  cos(Rzm) 0;
    +         0        0         1] * ...
    +        [cos(Rym)  0        sin(Rym);
    +         0        1        0;
    +         -sin(Rym)  0        cos(Rym)] * ...
    +        [1        0        0;
    +         0        cos(Rxm) -sin(Rxm);
    +         0        sin(Rxm)  cos(Rxm)];
    +    WTm(1:4, 4) = [Dxm ; Dym ; Dzm; 1];
     
    @@ -1445,19 +1450,19 @@ WTm(1:4, 4) = [Dxm ; Dym ; Dzm; 1]; We can also compute the Homogeneous transformation matrix \({}^WT_R\) corresponding to the transformation required to go from fixed frame \(\{W\}\) to the wanted frame \(\{R\}\).

    -
    %% Reference Pose
    -WTr = zeros(4,4);
    +
        %% Reference Pose
    +    WTr = zeros(4,4);
     
    -WTr(1:3, 1:3) = [cos(Rzr) -sin(Rzr) 0;
    -     sin(Rzr)  cos(Rzr) 0;
    -     0        0         1] * ...
    -    [cos(Ryr)  0        sin(Ryr);
    -     0        1        0;
    -     -sin(Ryr)  0        cos(Ryr)] * ...
    -    [1        0        0;
    -     0        cos(Rxr) -sin(Rxr);
    -     0        sin(Rxr)  cos(Rxr)];
    -WTr(1:4, 4) = [Dxr ; Dyr ; Dzr; 1];
    +    WTr(1:3, 1:3) = [cos(Rzr) -sin(Rzr) 0;
    +         sin(Rzr)  cos(Rzr) 0;
    +         0        0         1] * ...
    +        [cos(Ryr)  0        sin(Ryr);
    +         0        1        0;
    +         -sin(Ryr)  0        cos(Ryr)] * ...
    +        [1        0        0;
    +         0        cos(Rxr) -sin(Rxr);
    +         0        sin(Rxr)  cos(Rxr)];
    +    WTr(1:4, 4) = [Dxr ; Dyr ; Dzr; 1];
     
    @@ -1465,8 +1470,8 @@ WTr(1:4, 4) = [Dxr ; Dyr ; Dzr; 1]; We can also compute \({}^WT_V\).

    -
    WTv = eye(4);
    -WTv(1:3, 4) = WTm(1:3, 4);
    +
      WTv = eye(4);
    +  WTv(1:3, 4) = WTm(1:3, 4);
     
    @@ -1477,8 +1482,8 @@ This homogeneous transformation can be computed from the previously computed mat

    -
    %% Wanted pose expressed in a frame corresponding to the actual measured pose
    -MTr = [WTm(1:3,1:3)', -WTm(1:3,1:3)'*WTm(1:3,4) ; 0 0 0 1]*WTr;
    +
        %% Wanted pose expressed in a frame corresponding to the actual measured pose
    +    MTr = [WTm(1:3,1:3)', -WTm(1:3,1:3)'*WTm(1:3,4) ; 0 0 0 1]*WTr;
     
    @@ -1487,22 +1492,22 @@ Now we want to express \({}^VT_R\): \[ {}^VT_R = ({{}^WT_V}^{-1}) {}^WT_R \]

    -
    %% Wanted pose expressed in a frame coincident with the actual position but with no rotation
    -VTr = [WTv(1:3,1:3)', -WTv(1:3,1:3)'*WTv(1:3,4) ; 0 0 0 1] * WTr;
    +
        %% Wanted pose expressed in a frame coincident with the actual position but with no rotation
    +    VTr = [WTv(1:3,1:3)', -WTv(1:3,1:3)'*WTv(1:3,4) ; 0 0 0 1] * WTr;
     
    -
    %% Extract Translations and Rotations from the Homogeneous Matrix
    -T = MTr;
    -Edx = T(1, 4);
    -Edy = T(2, 4);
    -Edz = T(3, 4);
    +
        %% Extract Translations and Rotations from the Homogeneous Matrix
    +    T = MTr;
    +    Edx = T(1, 4);
    +    Edy = T(2, 4);
    +    Edz = T(3, 4);
     
    -% The angles obtained are u-v-w Euler angles (rotations in the moving frame)
    -Ery = atan2( T(1, 3),          sqrt(T(1, 1)^2 + T(1, 2)^2));
    -Erx = atan2(-T(2, 3)/cos(Ery), T(3, 3)/cos(Ery));
    -Erz = atan2(-T(1, 2)/cos(Ery), T(1, 1)/cos(Ery));
    +    % The angles obtained are u-v-w Euler angles (rotations in the moving frame)
    +    Ery = atan2( T(1, 3),          sqrt(T(1, 1)^2 + T(1, 2)^2));
    +    Erx = atan2(-T(2, 3)/cos(Ery), T(3, 3)/cos(Ery));
    +    Erz = atan2(-T(1, 2)/cos(Ery), T(1, 1)/cos(Ery));
     
    @@ -1510,7 +1515,7 @@ Erz = atan2(-T(1, 2)/cos(Ery), T(1, 1)/cos(Ery));

    Author: Dehaeze Thomas

    -

    Created: 2020-08-05 mer. 13:27

    +

    Created: 2021-01-08 ven. 15:30

    diff --git a/docs/control-vibration-isolation.html b/docs/control-vibration-isolation.html index b791573..f299bd2 100644 --- a/docs/control-vibration-isolation.html +++ b/docs/control-vibration-isolation.html @@ -3,25 +3,30 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + Stewart Platform - Vibration Isolation - - - - - - - - + + + +
    @@ -34,79 +39,79 @@

    Table of Contents

    -
    -

    1 HAC-LAC (Cascade) Control - Integral Control

    +
    +

    1 HAC-LAC (Cascade) Control - Integral Control

    -
    -

    1.1 Introduction

    +
    +

    1.1 Introduction

    In this section, we wish to study the use of the High Authority Control - Low Authority Control (HAC-LAC) architecture on the Stewart platform.

    -The control architectures are shown in Figures 1 and 2. +The control architectures are shown in Figures 1 and 2.

    @@ -135,7 +140,7 @@ First, the LAC loop is closed (the LAC control is described +

    control_arch_hac_iff.png

    Figure 1: HAC-LAC architecture with IFF

    @@ -143,7 +148,7 @@ First, the LAC loop is closed (the LAC control is described
    +

    control_arch_hac_dvf.png

    Figure 2: HAC-LAC architecture with DVF

    @@ -151,24 +156,24 @@ First, the LAC loop is closed (the LAC control is described
    -

    1.2 Initialization

    +
    +

    1.2 Initialization

    We first initialize the Stewart platform.

    -
    stewart = initializeStewartPlatform();
    -stewart = initializeFramesPositions(stewart, 'H', 90e-3, 'MO_B', 45e-3);
    -stewart = generateGeneralConfiguration(stewart);
    -stewart = computeJointsPose(stewart);
    -stewart = initializeStrutDynamics(stewart);
    -stewart = initializeJointDynamics(stewart, 'type_F', 'universal', 'type_M', 'spherical');
    -stewart = initializeCylindricalPlatforms(stewart);
    -stewart = initializeCylindricalStruts(stewart);
    -stewart = computeJacobian(stewart);
    -stewart = initializeStewartPose(stewart);
    -stewart = initializeInertialSensor(stewart, 'type', 'none');
    +
      stewart = initializeStewartPlatform();
    +  stewart = initializeFramesPositions(stewart, 'H', 90e-3, 'MO_B', 45e-3);
    +  stewart = generateGeneralConfiguration(stewart);
    +  stewart = computeJointsPose(stewart);
    +  stewart = initializeStrutDynamics(stewart);
    +  stewart = initializeJointDynamics(stewart, 'type_F', 'universal', 'type_M', 'spherical');
    +  stewart = initializeCylindricalPlatforms(stewart);
    +  stewart = initializeCylindricalStruts(stewart);
    +  stewart = computeJacobian(stewart);
    +  stewart = initializeStewartPose(stewart);
    +  stewart = initializeInertialSensor(stewart, 'type', 'none');
     
    @@ -176,15 +181,15 @@ stewart = initializeInertialSensor(stewart, 'type', 'none'); The rotation point of the ground is located at the origin of frame \(\{A\}\).

    -
    ground = initializeGround('type', 'rigid', 'rot_point', stewart.platform_F.FO_A);
    -payload = initializePayload('type', 'none');
    +
      ground = initializeGround('type', 'rigid', 'rot_point', stewart.platform_F.FO_A);
    +  payload = initializePayload('type', 'none');
     
    -
    -

    1.3 Identification

    +
    +

    1.3 Identification

    We identify the transfer function from the actuator forces \(\bm{\tau}\) to the absolute displacement of the mobile platform \(\bm{\mathcal{X}}\) in three different cases: @@ -196,103 +201,103 @@ We identify the transfer function from the actuator forces \(\bm{\tau}\) to the

    -
    -

    1.3.1 HAC - Without LAC

    +
    +

    1.3.1 HAC - Without LAC

    -
    controller = initializeController('type', 'open-loop');
    +
      controller = initializeController('type', 'open-loop');
     
    -
    %% Name of the Simulink File
    -mdl = 'stewart_platform_model';
    +
      %% Name of the Simulink File
    +  mdl = 'stewart_platform_model';
     
    -%% Input/Output definition
    -clear io; io_i = 1;
    -io(io_i) = linio([mdl, '/Controller'],              1, 'input');      io_i = io_i + 1; % Actuator Force Inputs [N]
    -io(io_i) = linio([mdl, '/Absolute Motion Sensor'],  1, 'openoutput'); io_i = io_i + 1; % Absolute Sensor [m, rad]
    +  %% Input/Output definition
    +  clear io; io_i = 1;
    +  io(io_i) = linio([mdl, '/Controller'],              1, 'input');      io_i = io_i + 1; % Actuator Force Inputs [N]
    +  io(io_i) = linio([mdl, '/Absolute Motion Sensor'],  1, 'openoutput'); io_i = io_i + 1; % Absolute Sensor [m, rad]
     
    -%% Run the linearization
    -G_ol = linearize(mdl, io);
    -G_ol.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    -G_ol.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
    +  %% Run the linearization
    +  G_ol = linearize(mdl, io);
    +  G_ol.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    +  G_ol.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
     
    -
    -

    1.3.2 HAC - IFF

    +
    +

    1.3.2 HAC - IFF

    -
    controller = initializeController('type', 'iff');
    -K_iff = -(1e4/s)*eye(6);
    +
      controller = initializeController('type', 'iff');
    +  K_iff = -(1e4/s)*eye(6);
     
    -
    %% Name of the Simulink File
    -mdl = 'stewart_platform_model';
    +
      %% Name of the Simulink File
    +  mdl = 'stewart_platform_model';
     
    -%% Input/Output definition
    -clear io; io_i = 1;
    -io(io_i) = linio([mdl, '/Controller'],              1, 'input');      io_i = io_i + 1; % Actuator Force Inputs [N]
    -io(io_i) = linio([mdl, '/Absolute Motion Sensor'],  1, 'openoutput'); io_i = io_i + 1; % Absolute Sensor [m, rad]
    +  %% Input/Output definition
    +  clear io; io_i = 1;
    +  io(io_i) = linio([mdl, '/Controller'],              1, 'input');      io_i = io_i + 1; % Actuator Force Inputs [N]
    +  io(io_i) = linio([mdl, '/Absolute Motion Sensor'],  1, 'openoutput'); io_i = io_i + 1; % Absolute Sensor [m, rad]
     
    -%% Run the linearization
    -G_iff = linearize(mdl, io);
    -G_iff.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    -G_iff.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
    +  %% Run the linearization
    +  G_iff = linearize(mdl, io);
    +  G_iff.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    +  G_iff.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
     
    -
    -

    1.3.3 HAC - DVF

    +
    +

    1.3.3 HAC - DVF

    -
    controller = initializeController('type', 'dvf');
    -K_dvf = -1e4*s/(1+s/2/pi/5000)*eye(6);
    +
      controller = initializeController('type', 'dvf');
    +  K_dvf = -1e4*s/(1+s/2/pi/5000)*eye(6);
     
    -
    %% Name of the Simulink File
    -mdl = 'stewart_platform_model';
    +
      %% Name of the Simulink File
    +  mdl = 'stewart_platform_model';
     
    -%% Input/Output definition
    -clear io; io_i = 1;
    -io(io_i) = linio([mdl, '/Controller'],              1, 'input');      io_i = io_i + 1; % Actuator Force Inputs [N]
    -io(io_i) = linio([mdl, '/Absolute Motion Sensor'],  1, 'openoutput'); io_i = io_i + 1; % Absolute Sensor [m, rad]
    +  %% Input/Output definition
    +  clear io; io_i = 1;
    +  io(io_i) = linio([mdl, '/Controller'],              1, 'input');      io_i = io_i + 1; % Actuator Force Inputs [N]
    +  io(io_i) = linio([mdl, '/Absolute Motion Sensor'],  1, 'openoutput'); io_i = io_i + 1; % Absolute Sensor [m, rad]
     
    -%% Run the linearization
    -G_dvf = linearize(mdl, io);
    -G_dvf.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    -G_dvf.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
    +  %% Run the linearization
    +  G_dvf = linearize(mdl, io);
    +  G_dvf.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    +  G_dvf.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
     
    -
    -

    1.4 Control Architecture

    +
    +

    1.4 Control Architecture

    We use the Jacobian to express the actuator forces in the cartesian frame, and thus we obtain the transfer functions from \(\bm{\mathcal{F}}\) to \(\bm{\mathcal{X}}\).

    -
    Gc_ol = minreal(G_ol)/stewart.kinematics.J';
    -Gc_ol.InputName = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'};
    +
      Gc_ol = minreal(G_ol)/stewart.kinematics.J';
    +  Gc_ol.InputName = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'};
     
    -Gc_iff = minreal(G_iff)/stewart.kinematics.J';
    -Gc_iff.InputName = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'};
    +  Gc_iff = minreal(G_iff)/stewart.kinematics.J';
    +  Gc_iff.InputName = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'};
     
    -Gc_dvf = minreal(G_dvf)/stewart.kinematics.J';
    -Gc_dvf.InputName = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'};
    +  Gc_dvf = minreal(G_dvf)/stewart.kinematics.J';
    +  Gc_dvf.InputName = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'};
     
    @@ -302,11 +307,11 @@ We then design a controller based on the transfer functions from \(\bm{\mathcal{
    -
    -

    1.5 6x6 Plant Comparison

    +
    +

    1.5 6x6 Plant Comparison

    -
    +

    hac_lac_coupling_jacobian.png

    Figure 3: Norm of the transfer functions from \(\bm{\mathcal{F}}\) to \(\bm{\mathcal{X}}\) (png, pdf)

    @@ -314,15 +319,15 @@ We then design a controller based on the transfer functions from \(\bm{\mathcal{
    -
    -

    1.6 HAC - DVF

    +
    +

    1.6 HAC - DVF

    -
    -

    1.6.1 Plant

    +
    +

    1.6.1 Plant

    -
    +

    hac_lac_plant_dvf.png

    Figure 4: Diagonal elements of the plant for HAC control when DVF is previously applied (png, pdf)

    @@ -330,8 +335,8 @@ We then design a controller based on the transfer functions from \(\bm{\mathcal{
    -
    -

    1.6.2 Controller Design

    +
    +

    1.6.2 Controller Design

    We design a diagonal controller with equal bandwidth for the 6 terms. @@ -339,17 +344,17 @@ The controller is a pure integrator with a small lead near the crossover.

    -
    wc = 2*pi*300; % Wanted Bandwidth [rad/s]
    +
      wc = 2*pi*300; % Wanted Bandwidth [rad/s]
     
    -h = 1.2;
    -H_lead = 1/h*(1 + s/(wc/h))/(1 + s/(wc*h));
    +  h = 1.2;
    +  H_lead = 1/h*(1 + s/(wc/h))/(1 + s/(wc*h));
     
    -Kd_dvf = diag(1./abs(diag(freqresp(1/s*Gc_dvf, wc)))) .* H_lead .* 1/s;
    +  Kd_dvf = diag(1./abs(diag(freqresp(1/s*Gc_dvf, wc)))) .* H_lead .* 1/s;
     
    -
    +

    hac_lac_loop_gain_dvf.png

    Figure 5: Diagonal elements of the Loop Gain for the HAC control (png, pdf)

    @@ -360,42 +365,42 @@ Kd_dvf = diag(1./abs(diag(freqresp(1/s*Gc_dvf, wc)))) .* H_lead .* 1/s; Finally, we pre-multiply the diagonal controller by \(\bm{J}^{-T}\) prior implementation.

    -
    K_hac_dvf = inv(stewart.kinematics.J')*Kd_dvf;
    +
      K_hac_dvf = inv(stewart.kinematics.J')*Kd_dvf;
     
    -
    -

    1.6.3 Obtained Performance

    +
    +

    1.6.3 Obtained Performance

    We identify the transmissibility and compliance of the system.

    -
    controller = initializeController('type', 'open-loop');
    -[T_ol, T_norm_ol, freqs] = computeTransmissibility();
    -[C_ol, C_norm_ol, ~] = computeCompliance();
    +
      controller = initializeController('type', 'open-loop');
    +  [T_ol, T_norm_ol, freqs] = computeTransmissibility();
    +  [C_ol, C_norm_ol, ~] = computeCompliance();
     
    -
    controller = initializeController('type', 'dvf');
    -[T_dvf, T_norm_dvf, ~] = computeTransmissibility();
    -[C_dvf, C_norm_dvf, ~] = computeCompliance();
    +
      controller = initializeController('type', 'dvf');
    +  [T_dvf, T_norm_dvf, ~] = computeTransmissibility();
    +  [C_dvf, C_norm_dvf, ~] = computeCompliance();
     
    -
    controller = initializeController('type', 'hac-dvf');
    -[T_hac_dvf, T_norm_hac_dvf, ~] = computeTransmissibility();
    -[C_hac_dvf, C_norm_hac_dvf, ~] = computeCompliance();
    +
      controller = initializeController('type', 'hac-dvf');
    +  [T_hac_dvf, T_norm_hac_dvf, ~] = computeTransmissibility();
    +  [C_hac_dvf, C_norm_hac_dvf, ~] = computeCompliance();
     
    -
    +

    hac_lac_C_T_dvf.png

    Figure 6: Obtained Compliance and Transmissibility (png, pdf)

    @@ -404,15 +409,15 @@ We identify the transmissibility and compliance of the system.
    -
    -

    1.7 HAC - IFF

    +
    +

    1.7 HAC - IFF

    -
    -

    1.7.1 Plant

    +
    +

    1.7.1 Plant

    -
    +

    hac_lac_plant_iff.png

    Figure 7: Diagonal elements of the plant for HAC control when IFF is previously applied (png, pdf)

    @@ -420,8 +425,8 @@ We identify the transmissibility and compliance of the system.
    -
    -

    1.7.2 Controller Design

    +
    +

    1.7.2 Controller Design

    We design a diagonal controller with equal bandwidth for the 6 terms. @@ -429,17 +434,17 @@ The controller is a pure integrator with a small lead near the crossover.

    -
    wc = 2*pi*300; % Wanted Bandwidth [rad/s]
    +
      wc = 2*pi*300; % Wanted Bandwidth [rad/s]
     
    -h = 1.2;
    -H_lead = 1/h*(1 + s/(wc/h))/(1 + s/(wc*h));
    +  h = 1.2;
    +  H_lead = 1/h*(1 + s/(wc/h))/(1 + s/(wc*h));
     
    -Kd_iff = diag(1./abs(diag(freqresp(1/s*Gc_iff, wc)))) .* H_lead .* 1/s;
    +  Kd_iff = diag(1./abs(diag(freqresp(1/s*Gc_iff, wc)))) .* H_lead .* 1/s;
     
    -
    +

    hac_lac_loop_gain_iff.png

    Figure 8: Diagonal elements of the Loop Gain for the HAC control (png, pdf)

    @@ -450,42 +455,42 @@ Kd_iff = diag(1./abs(diag(freqresp(1/s*Gc_iff, wc)))) .* H_lead .* 1/s; Finally, we pre-multiply the diagonal controller by \(\bm{J}^{-T}\) prior implementation.

    -
    K_hac_iff = inv(stewart.kinematics.J')*Kd_iff;
    +
      K_hac_iff = inv(stewart.kinematics.J')*Kd_iff;
     
    -
    -

    1.7.3 Obtained Performance

    +
    +

    1.7.3 Obtained Performance

    We identify the transmissibility and compliance of the system.

    -
    controller = initializeController('type', 'open-loop');
    -[T_ol, T_norm_ol, freqs] = computeTransmissibility();
    -[C_ol, C_norm_ol, ~] = computeCompliance();
    +
      controller = initializeController('type', 'open-loop');
    +  [T_ol, T_norm_ol, freqs] = computeTransmissibility();
    +  [C_ol, C_norm_ol, ~] = computeCompliance();
     
    -
    controller = initializeController('type', 'iff');
    -[T_iff, T_norm_iff, ~] = computeTransmissibility();
    -[C_iff, C_norm_iff, ~] = computeCompliance();
    +
      controller = initializeController('type', 'iff');
    +  [T_iff, T_norm_iff, ~] = computeTransmissibility();
    +  [C_iff, C_norm_iff, ~] = computeCompliance();
     
    -
    controller = initializeController('type', 'hac-iff');
    -[T_hac_iff, T_norm_hac_iff, ~] = computeTransmissibility();
    -[C_hac_iff, C_norm_hac_iff, ~] = computeCompliance();
    +
      controller = initializeController('type', 'hac-iff');
    +  [T_hac_iff, T_norm_hac_iff, ~] = computeTransmissibility();
    +  [C_hac_iff, C_norm_hac_iff, ~] = computeCompliance();
     
    -
    +

    hac_lac_C_T_iff.png

    Figure 9: Obtained Compliance and Transmissibility (png, pdf)

    @@ -494,25 +499,25 @@ We identify the transmissibility and compliance of the system.
    -
    -

    1.8 Comparison

    +
    +

    1.8 Comparison

    -
    +

    hac_lac_C_full_comparison.png

    Figure 10: Comparison of the norm of the Compliance matrices for the HAC-LAC architecture (png, pdf)

    -
    +

    hac_lac_T_full_comparison.png

    Figure 11: Comparison of the norm of the Transmissibility matrices for the HAC-LAC architecture (png, pdf)

    -
    +

    hac_lac_C_T_comparison.png

    Figure 12: Comparison of the Frobenius norm of the Compliance and Transmissibility for the HAC-LAC architecture with both IFF and DVF (png, pdf)

    @@ -521,21 +526,21 @@ We identify the transmissibility and compliance of the system.
    -
    -

    2 MIMO Analysis

    +
    +

    2 MIMO Analysis

    -Let’s define the system as shown in figure 13. +Let’s define the system as shown in figure 13.

    -
    +

    general_control_names.png

    Figure 13: General Control Architecture

    -
    Table 1: Comparison of the two centralized control architectures
    +
    @@ -613,24 +618,24 @@ Let’s define the system as shown in figure 13.
    Table 1: Signals definition for the generalized plant
    -
    -

    2.1 Initialization

    +
    +

    2.1 Initialization

    We first initialize the Stewart platform.

    -
    stewart = initializeStewartPlatform();
    -stewart = initializeFramesPositions(stewart, 'H', 90e-3, 'MO_B', 45e-3);
    -stewart = generateGeneralConfiguration(stewart);
    -stewart = computeJointsPose(stewart);
    -stewart = initializeStrutDynamics(stewart);
    -stewart = initializeJointDynamics(stewart, 'type_F', 'universal', 'type_M', 'spherical');
    -stewart = initializeCylindricalPlatforms(stewart);
    -stewart = initializeCylindricalStruts(stewart);
    -stewart = computeJacobian(stewart);
    -stewart = initializeStewartPose(stewart);
    -stewart = initializeInertialSensor(stewart, 'type', 'none');
    +
      stewart = initializeStewartPlatform();
    +  stewart = initializeFramesPositions(stewart, 'H', 90e-3, 'MO_B', 45e-3);
    +  stewart = generateGeneralConfiguration(stewart);
    +  stewart = computeJointsPose(stewart);
    +  stewart = initializeStrutDynamics(stewart);
    +  stewart = initializeJointDynamics(stewart, 'type_F', 'universal', 'type_M', 'spherical');
    +  stewart = initializeCylindricalPlatforms(stewart);
    +  stewart = initializeCylindricalStruts(stewart);
    +  stewart = computeJacobian(stewart);
    +  stewart = initializeStewartPose(stewart);
    +  stewart = initializeInertialSensor(stewart, 'type', 'none');
     
    @@ -638,118 +643,118 @@ stewart = initializeInertialSensor(stewart, 'type', 'none'); The rotation point of the ground is located at the origin of frame \(\{A\}\).

    -
    ground = initializeGround('type', 'rigid', 'rot_point', stewart.platform_F.FO_A);
    -payload = initializePayload('type', 'none');
    +
      ground = initializeGround('type', 'rigid', 'rot_point', stewart.platform_F.FO_A);
    +  payload = initializePayload('type', 'none');
     
    -
    -

    2.2 Identification

    +
    +

    2.2 Identification

    -
    -

    2.2.1 HAC - Without LAC

    +
    +

    2.2.1 HAC - Without LAC

    -
    controller = initializeController('type', 'open-loop');
    +
      controller = initializeController('type', 'open-loop');
     
    -
    %% Name of the Simulink File
    -mdl = 'stewart_platform_model';
    +
      %% Name of the Simulink File
    +  mdl = 'stewart_platform_model';
     
    -%% Input/Output definition
    -clear io; io_i = 1;
    -io(io_i) = linio([mdl, '/Controller'],              1, 'input');      io_i = io_i + 1; % Actuator Force Inputs [N]
    -io(io_i) = linio([mdl, '/Absolute Motion Sensor'],  1, 'openoutput'); io_i = io_i + 1; % Absolute Sensor [m, rad]
    +  %% Input/Output definition
    +  clear io; io_i = 1;
    +  io(io_i) = linio([mdl, '/Controller'],              1, 'input');      io_i = io_i + 1; % Actuator Force Inputs [N]
    +  io(io_i) = linio([mdl, '/Absolute Motion Sensor'],  1, 'openoutput'); io_i = io_i + 1; % Absolute Sensor [m, rad]
     
    -%% Run the linearization
    -G_ol = linearize(mdl, io);
    -G_ol.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    -G_ol.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
    +  %% Run the linearization
    +  G_ol = linearize(mdl, io);
    +  G_ol.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    +  G_ol.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
     
    -
    -

    2.2.2 HAC - DVF

    +
    +

    2.2.2 HAC - DVF

    -
    controller = initializeController('type', 'dvf');
    -K_dvf = -1e4*s/(1+s/2/pi/5000)*eye(6);
    +
      controller = initializeController('type', 'dvf');
    +  K_dvf = -1e4*s/(1+s/2/pi/5000)*eye(6);
     
    -
    %% Name of the Simulink File
    -mdl = 'stewart_platform_model';
    +
      %% Name of the Simulink File
    +  mdl = 'stewart_platform_model';
     
    -%% Input/Output definition
    -clear io; io_i = 1;
    -io(io_i) = linio([mdl, '/Controller'],              1, 'input');      io_i = io_i + 1; % Actuator Force Inputs [N]
    -io(io_i) = linio([mdl, '/Absolute Motion Sensor'],  1, 'openoutput'); io_i = io_i + 1; % Absolute Sensor [m, rad]
    +  %% Input/Output definition
    +  clear io; io_i = 1;
    +  io(io_i) = linio([mdl, '/Controller'],              1, 'input');      io_i = io_i + 1; % Actuator Force Inputs [N]
    +  io(io_i) = linio([mdl, '/Absolute Motion Sensor'],  1, 'openoutput'); io_i = io_i + 1; % Absolute Sensor [m, rad]
     
    -%% Run the linearization
    -G_dvf = linearize(mdl, io);
    -G_dvf.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    -G_dvf.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
    +  %% Run the linearization
    +  G_dvf = linearize(mdl, io);
    +  G_dvf.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    +  G_dvf.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
     
    -
    -

    2.2.3 Cartesian Frame

    +
    +

    2.2.3 Cartesian Frame

    -
    Gc_ol = minreal(G_ol)/stewart.kinematics.J';
    -Gc_ol.InputName = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'};
    +
      Gc_ol = minreal(G_ol)/stewart.kinematics.J';
    +  Gc_ol.InputName = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'};
     
    -Gc_dvf = minreal(G_dvf)/stewart.kinematics.J';
    -Gc_dvf.InputName = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'};
    +  Gc_dvf = minreal(G_dvf)/stewart.kinematics.J';
    +  Gc_dvf.InputName = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'};
     
    -
    -

    2.3 Singular Value Decomposition

    +
    +

    2.3 Singular Value Decomposition

    -
    freqs = logspace(1, 4, 1000);
    +
      freqs = logspace(1, 4, 1000);
     
    -U_ol = zeros(6,6,length(freqs));
    -S_ol = zeros(6,length(freqs));
    -V_ol = zeros(6,6,length(freqs));
    +  U_ol = zeros(6,6,length(freqs));
    +  S_ol = zeros(6,length(freqs));
    +  V_ol = zeros(6,6,length(freqs));
     
    -U_dvf = zeros(6,6,length(freqs));
    -S_dvf = zeros(6,length(freqs));
    -V_dvf = zeros(6,6,length(freqs));
    +  U_dvf = zeros(6,6,length(freqs));
    +  S_dvf = zeros(6,length(freqs));
    +  V_dvf = zeros(6,6,length(freqs));
     
    -for i = 1:length(freqs)
    -  [U,S,V] = svd(freqresp(Gc_ol, freqs(i), 'Hz'));
    -  U_ol(:,:,i) = U;
    -  S_ol(:,i) = diag(S);
    -  V_ol(:,:,i) = V;
    +  for i = 1:length(freqs)
    +    [U,S,V] = svd(freqresp(Gc_ol, freqs(i), 'Hz'));
    +    U_ol(:,:,i) = U;
    +    S_ol(:,i) = diag(S);
    +    V_ol(:,:,i) = V;
     
    -  [U,S,V] = svd(freqresp(Gc_dvf, freqs(i), 'Hz'));
    -  U_dvf(:,:,i) = U;
    -  S_dvf(:,i) = diag(S);
    -  V_dvf(:,:,i) = V;
    -end
    +    [U,S,V] = svd(freqresp(Gc_dvf, freqs(i), 'Hz'));
    +    U_dvf(:,:,i) = U;
    +    S_dvf(:,i) = diag(S);
    +    V_dvf(:,:,i) = V;
    +  end
     
    -
    -

    3 Diagonal Control based on the damped plant

    +
    +

    3 Diagonal Control based on the damped plant

    From (Skogestad and Postlethwaite 2007), a simple approach to multivariable control is the following two-step procedure: @@ -774,24 +779,24 @@ There are mainly three different cases:

    -
    -

    3.1 Initialization

    +
    +

    3.1 Initialization

    We first initialize the Stewart platform.

    -
    stewart = initializeStewartPlatform();
    -stewart = initializeFramesPositions(stewart, 'H', 90e-3, 'MO_B', 45e-3);
    -stewart = generateGeneralConfiguration(stewart);
    -stewart = computeJointsPose(stewart);
    -stewart = initializeStrutDynamics(stewart);
    -stewart = initializeJointDynamics(stewart, 'type_F', 'universal', 'type_M', 'spherical');
    -stewart = initializeCylindricalPlatforms(stewart);
    -stewart = initializeCylindricalStruts(stewart);
    -stewart = computeJacobian(stewart);
    -stewart = initializeStewartPose(stewart);
    -stewart = initializeInertialSensor(stewart, 'type', 'none');
    +
      stewart = initializeStewartPlatform();
    +  stewart = initializeFramesPositions(stewart, 'H', 90e-3, 'MO_B', 45e-3);
    +  stewart = generateGeneralConfiguration(stewart);
    +  stewart = computeJointsPose(stewart);
    +  stewart = initializeStrutDynamics(stewart);
    +  stewart = initializeJointDynamics(stewart, 'type_F', 'universal', 'type_M', 'spherical');
    +  stewart = initializeCylindricalPlatforms(stewart);
    +  stewart = initializeCylindricalStruts(stewart);
    +  stewart = computeJacobian(stewart);
    +  stewart = initializeStewartPose(stewart);
    +  stewart = initializeInertialSensor(stewart, 'type', 'none');
     
    @@ -799,52 +804,52 @@ stewart = initializeInertialSensor(stewart, 'type', 'none'); The rotation point of the ground is located at the origin of frame \(\{A\}\).

    -
    ground = initializeGround('type', 'rigid', 'rot_point', stewart.platform_F.FO_A);
    -payload = initializePayload('type', 'none');
    +
      ground = initializeGround('type', 'rigid', 'rot_point', stewart.platform_F.FO_A);
    +  payload = initializePayload('type', 'none');
     
    -
    -

    3.2 Identification

    +
    +

    3.2 Identification

    -
    controller = initializeController('type', 'dvf');
    -K_dvf = -1e4*s/(1+s/2/pi/5000)*eye(6);
    +
      controller = initializeController('type', 'dvf');
    +  K_dvf = -1e4*s/(1+s/2/pi/5000)*eye(6);
     
    -
    %% Name of the Simulink File
    -mdl = 'stewart_platform_model';
    +
      %% Name of the Simulink File
    +  mdl = 'stewart_platform_model';
     
    -%% Input/Output definition
    -clear io; io_i = 1;
    -io(io_i) = linio([mdl, '/Controller'],              1, 'input');      io_i = io_i + 1; % Actuator Force Inputs [N]
    -io(io_i) = linio([mdl, '/Absolute Motion Sensor'],  1, 'openoutput'); io_i = io_i + 1; % Absolute Sensor [m, rad]
    +  %% Input/Output definition
    +  clear io; io_i = 1;
    +  io(io_i) = linio([mdl, '/Controller'],              1, 'input');      io_i = io_i + 1; % Actuator Force Inputs [N]
    +  io(io_i) = linio([mdl, '/Absolute Motion Sensor'],  1, 'openoutput'); io_i = io_i + 1; % Absolute Sensor [m, rad]
     
    -%% Run the linearization
    -G_dvf = linearize(mdl, io);
    -G_dvf.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    -G_dvf.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
    +  %% Run the linearization
    +  G_dvf = linearize(mdl, io);
    +  G_dvf.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    +  G_dvf.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
     
    -
    -

    3.3 Steady State Decoupling

    +
    +

    3.3 Steady State Decoupling

    -
    -

    3.3.1 Pre-Compensator Design

    +
    +

    3.3.1 Pre-Compensator Design

    We choose \(W_1 = G^{-1}(0)\).

    -
    W1 = inv(freqresp(G_dvf, 0));
    +
      W1 = inv(freqresp(G_dvf, 0));
     
    @@ -852,7 +857,7 @@ We choose \(W_1 = G^{-1}(0)\). The (static) decoupled plant is \(G_s(s) = G(s) W_1\).

    -
    Gs = G_dvf*W1;
    +
      Gs = G_dvf*W1;
     
    @@ -868,18 +873,18 @@ In the case of the Stewart platform, the pre-compensator for static decoupling i \end{align*}

    -The static decoupled plant is schematic shown in Figure 14 and the bode plots of its diagonal elements are shown in Figure 15. +The static decoupled plant is schematic shown in Figure 14 and the bode plots of its diagonal elements are shown in Figure 15.

    -
    +

    control_arch_static_decoupling.png

    Figure 14: Static Decoupling of the Stewart platform

    -
    +

    static_decoupling_diagonal_plant.png

    Figure 15: Bode plot of the diagonal elements of \(G_s(s)\) (png, pdf)

    @@ -887,34 +892,34 @@ The static decoupled plant is schematic shown in Figure 14
    -
    -

    3.3.2 Diagonal Control Design

    +
    +

    3.3.2 Diagonal Control Design

    We design a diagonal controller \(K_s(s)\) that consist of a pure integrator and a lead around the crossover.

    -
    wc = 2*pi*300; % Wanted Bandwidth [rad/s]
    +
      wc = 2*pi*300; % Wanted Bandwidth [rad/s]
     
    -h = 1.5;
    -H_lead = 1/h*(1 + s/(wc/h))/(1 + s/(wc*h));
    +  h = 1.5;
    +  H_lead = 1/h*(1 + s/(wc/h))/(1 + s/(wc*h));
     
    -Ks_dvf = diag(1./abs(diag(freqresp(1/s*Gs, wc)))) .* H_lead .* 1/s;
    +  Ks_dvf = diag(1./abs(diag(freqresp(1/s*Gs, wc)))) .* H_lead .* 1/s;
     

    -The overall controller is then \(K(s) = W_1 K_s(s)\) as shown in Figure 16. +The overall controller is then \(K(s) = W_1 K_s(s)\) as shown in Figure 16.

    -
    K_hac_dvf = W1 * Ks_dvf;
    +
      K_hac_dvf = W1 * Ks_dvf;
     
    -
    +

    control_arch_static_decoupling_K.png

    Figure 16: Controller including the static decoupling matrix

    @@ -922,24 +927,24 @@ The overall controller is then \(K(s) = W_1 K_s(s)\) as shown in Figure
    -
    -

    3.3.3 Results

    +
    +

    3.3.3 Results

    We identify the transmissibility and compliance of the Stewart platform under open-loop and closed-loop control.

    -
    controller = initializeController('type', 'open-loop');
    -[T_ol, T_norm_ol, freqs] = computeTransmissibility();
    -[C_ol, C_norm_ol, ~] = computeCompliance();
    +
      controller = initializeController('type', 'open-loop');
    +  [T_ol, T_norm_ol, freqs] = computeTransmissibility();
    +  [C_ol, C_norm_ol, ~] = computeCompliance();
     
    -
    controller = initializeController('type', 'hac-dvf');
    -[T_hac_dvf, T_norm_hac_dvf, ~] = computeTransmissibility();
    -[C_hac_dvf, C_norm_hac_dvf, ~] = computeCompliance();
    +
      controller = initializeController('type', 'hac-dvf');
    +  [T_hac_dvf, T_norm_hac_dvf, ~] = computeTransmissibility();
    +  [C_hac_dvf, C_norm_hac_dvf, ~] = computeCompliance();
     
    @@ -948,7 +953,7 @@ The results are shown in figure

    -
    +

    static_decoupling_C_T_frobenius_norm.png

    Figure 17: Frobenius norm of the Compliance and transmissibility matrices (png, pdf)

    @@ -957,8 +962,8 @@ The results are shown in figure
    -
    -

    3.4 Decoupling at Crossover

    +
    +

    3.4 Decoupling at Crossover

    • [ ] Find a method for real approximation of a complex matrix
    • @@ -967,28 +972,28 @@ The results are shown in figure
    -
    -

    4 Time Domain Simulation

    +
    +

    4 Time Domain Simulation

    -
    -

    4.1 Initialization

    +
    +

    4.1 Initialization

    We first initialize the Stewart platform.

    -
    stewart = initializeStewartPlatform();
    -stewart = initializeFramesPositions(stewart, 'H', 90e-3, 'MO_B', 45e-3);
    -stewart = generateGeneralConfiguration(stewart);
    -stewart = computeJointsPose(stewart);
    -stewart = initializeStrutDynamics(stewart);
    -stewart = initializeJointDynamics(stewart, 'type_F', 'universal', 'type_M', 'spherical');
    -stewart = initializeCylindricalPlatforms(stewart);
    -stewart = initializeCylindricalStruts(stewart);
    -stewart = computeJacobian(stewart);
    -stewart = initializeStewartPose(stewart);
    -stewart = initializeInertialSensor(stewart, 'type', 'none');
    +
      stewart = initializeStewartPlatform();
    +  stewart = initializeFramesPositions(stewart, 'H', 90e-3, 'MO_B', 45e-3);
    +  stewart = generateGeneralConfiguration(stewart);
    +  stewart = computeJointsPose(stewart);
    +  stewart = initializeStrutDynamics(stewart);
    +  stewart = initializeJointDynamics(stewart, 'type_F', 'universal', 'type_M', 'spherical');
    +  stewart = initializeCylindricalPlatforms(stewart);
    +  stewart = initializeCylindricalStruts(stewart);
    +  stewart = computeJacobian(stewart);
    +  stewart = initializeStewartPose(stewart);
    +  stewart = initializeInertialSensor(stewart, 'type', 'none');
     
    @@ -996,206 +1001,206 @@ stewart = initializeInertialSensor(stewart, 'type', 'none'); The rotation point of the ground is located at the origin of frame \(\{A\}\).

    -
    ground = initializeGround('type', 'rigid', 'rot_point', stewart.platform_F.FO_A);
    -payload = initializePayload('type', 'none');
    +
      ground = initializeGround('type', 'rigid', 'rot_point', stewart.platform_F.FO_A);
    +  payload = initializePayload('type', 'none');
     
    -
    load('./mat/motion_error_ol.mat', 'Eg')
    +
      load('./mat/motion_error_ol.mat', 'Eg')
     
    -
    -

    4.2 HAC IFF

    +
    +

    4.2 HAC IFF

    -
    controller = initializeController('type', 'iff');
    -K_iff = -(1e4/s)*eye(6);
    +
      controller = initializeController('type', 'iff');
    +  K_iff = -(1e4/s)*eye(6);
     
    -%% Name of the Simulink File
    -mdl = 'stewart_platform_model';
    +  %% Name of the Simulink File
    +  mdl = 'stewart_platform_model';
     
    -%% Input/Output definition
    -clear io; io_i = 1;
    -io(io_i) = linio([mdl, '/Controller'],              1, 'input');      io_i = io_i + 1; % Actuator Force Inputs [N]
    -io(io_i) = linio([mdl, '/Absolute Motion Sensor'],  1, 'openoutput'); io_i = io_i + 1; % Absolute Sensor [m, rad]
    +  %% Input/Output definition
    +  clear io; io_i = 1;
    +  io(io_i) = linio([mdl, '/Controller'],              1, 'input');      io_i = io_i + 1; % Actuator Force Inputs [N]
    +  io(io_i) = linio([mdl, '/Absolute Motion Sensor'],  1, 'openoutput'); io_i = io_i + 1; % Absolute Sensor [m, rad]
     
    -%% Run the linearization
    -G_iff = linearize(mdl, io);
    -G_iff.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    -G_iff.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
    +  %% Run the linearization
    +  G_iff = linearize(mdl, io);
    +  G_iff.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    +  G_iff.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
     
    -Gc_iff = minreal(G_iff)/stewart.kinematics.J';
    -Gc_iff.InputName = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'};
    +  Gc_iff = minreal(G_iff)/stewart.kinematics.J';
    +  Gc_iff.InputName = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'};
     
    -
    wc = 2*pi*100; % Wanted Bandwidth [rad/s]
    +
      wc = 2*pi*100; % Wanted Bandwidth [rad/s]
     
    -h = 1.2;
    -H_lead = 1/h*(1 + s/(wc/h))/(1 + s/(wc*h));
    +  h = 1.2;
    +  H_lead = 1/h*(1 + s/(wc/h))/(1 + s/(wc*h));
     
    -Kd_iff = diag(1./abs(diag(freqresp(1/s*Gc_iff, wc)))) .* H_lead .* 1/s;
    -K_hac_iff = inv(stewart.kinematics.J')*Kd_iff;
    +  Kd_iff = diag(1./abs(diag(freqresp(1/s*Gc_iff, wc)))) .* H_lead .* 1/s;
    +  K_hac_iff = inv(stewart.kinematics.J')*Kd_iff;
     
    -
    controller = initializeController('type', 'hac-iff');
    +
      controller = initializeController('type', 'hac-iff');
     
    -
    -

    4.3 HAC-DVF

    +
    +

    4.3 HAC-DVF

    -
    controller = initializeController('type', 'dvf');
    -K_dvf = -1e4*s/(1+s/2/pi/5000)*eye(6);
    +
      controller = initializeController('type', 'dvf');
    +  K_dvf = -1e4*s/(1+s/2/pi/5000)*eye(6);
     
    -%% Name of the Simulink File
    -mdl = 'stewart_platform_model';
    +  %% Name of the Simulink File
    +  mdl = 'stewart_platform_model';
     
    -%% Input/Output definition
    -clear io; io_i = 1;
    -io(io_i) = linio([mdl, '/Controller'],              1, 'input');      io_i = io_i + 1; % Actuator Force Inputs [N]
    -io(io_i) = linio([mdl, '/Absolute Motion Sensor'],  1, 'openoutput'); io_i = io_i + 1; % Absolute Sensor [m, rad]
    +  %% Input/Output definition
    +  clear io; io_i = 1;
    +  io(io_i) = linio([mdl, '/Controller'],              1, 'input');      io_i = io_i + 1; % Actuator Force Inputs [N]
    +  io(io_i) = linio([mdl, '/Absolute Motion Sensor'],  1, 'openoutput'); io_i = io_i + 1; % Absolute Sensor [m, rad]
     
    -%% Run the linearization
    -G_dvf = linearize(mdl, io);
    -G_dvf.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    -G_dvf.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
    +  %% Run the linearization
    +  G_dvf = linearize(mdl, io);
    +  G_dvf.InputName  = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'};
    +  G_dvf.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
     
    -Gc_dvf = minreal(G_dvf)/stewart.kinematics.J';
    -Gc_dvf.InputName = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'};
    +  Gc_dvf = minreal(G_dvf)/stewart.kinematics.J';
    +  Gc_dvf.InputName = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'};
     
    -
    wc = 2*pi*100; % Wanted Bandwidth [rad/s]
    +
      wc = 2*pi*100; % Wanted Bandwidth [rad/s]
     
    -h = 1.2;
    -H_lead = 1/h*(1 + s/(wc/h))/(1 + s/(wc*h));
    +  h = 1.2;
    +  H_lead = 1/h*(1 + s/(wc/h))/(1 + s/(wc*h));
     
    -Kd_dvf = diag(1./abs(diag(freqresp(1/s*Gc_dvf, wc)))) .* H_lead .* 1/s;
    +  Kd_dvf = diag(1./abs(diag(freqresp(1/s*Gc_dvf, wc)))) .* H_lead .* 1/s;
     
    -K_hac_dvf = inv(stewart.kinematics.J')*Kd_dvf;
    +  K_hac_dvf = inv(stewart.kinematics.J')*Kd_dvf;
     
    -
    controller = initializeController('type', 'hac-dvf');
    +
      controller = initializeController('type', 'hac-dvf');
     
    -
    -

    4.4 Results

    +
    +

    4.4 Results

    -
    figure;
    -subplot(1, 2, 1);
    -hold on;
    -plot(Eg.Time, Eg.Data(:, 1), 'DisplayName', 'X');
    -plot(Eg.Time, Eg.Data(:, 2), 'DisplayName', 'Y');
    -plot(Eg.Time, Eg.Data(:, 3), 'DisplayName', 'Z');
    -hold off;
    -xlabel('Time [s]');
    -ylabel('Position error [m]');
    -legend();
    +
      figure;
    +  subplot(1, 2, 1);
    +  hold on;
    +  plot(Eg.Time, Eg.Data(:, 1), 'DisplayName', 'X');
    +  plot(Eg.Time, Eg.Data(:, 2), 'DisplayName', 'Y');
    +  plot(Eg.Time, Eg.Data(:, 3), 'DisplayName', 'Z');
    +  hold off;
    +  xlabel('Time [s]');
    +  ylabel('Position error [m]');
    +  legend();
     
    -subplot(1, 2, 2);
    -hold on;
    -plot(simout.Xa.Time, simout.Xa.Data(:, 1));
    -plot(simout.Xa.Time, simout.Xa.Data(:, 2));
    -plot(simout.Xa.Time, simout.Xa.Data(:, 3));
    -hold off;
    -xlabel('Time [s]');
    -ylabel('Orientation error [rad]');
    +  subplot(1, 2, 2);
    +  hold on;
    +  plot(simout.Xa.Time, simout.Xa.Data(:, 1));
    +  plot(simout.Xa.Time, simout.Xa.Data(:, 2));
    +  plot(simout.Xa.Time, simout.Xa.Data(:, 3));
    +  hold off;
    +  xlabel('Time [s]');
    +  ylabel('Orientation error [rad]');
     
    -
    -

    5 Functions

    +
    +

    5 Functions

    -
    -

    5.1 initializeController: Initialize the Controller

    +
    +

    5.1 initializeController: Initialize the Controller

    - +

    -
    -

    Function description

    -
    +
    +

    Function description

    +
    -
    function [controller] = initializeController(args)
    -% initializeController - Initialize the Controller
    -%
    -% Syntax: [] = initializeController(args)
    -%
    -% Inputs:
    -%    - args - Can have the following fields:
    +
      function [controller] = initializeController(args)
    +  % initializeController - Initialize the Controller
    +  %
    +  % Syntax: [] = initializeController(args)
    +  %
    +  % Inputs:
    +  %    - args - Can have the following fields:
     
    -
    -

    Optional Parameters

    -
    +
    +

    Optional Parameters

    +
    -
    arguments
    -  args.type   char   {mustBeMember(args.type, {'open-loop', 'iff', 'dvf', 'hac-iff', 'hac-dvf', 'ref-track-L', 'ref-track-X', 'ref-track-hac-dvf'})} = 'open-loop'
    -end
    +
      arguments
    +    args.type   char   {mustBeMember(args.type, {'open-loop', 'iff', 'dvf', 'hac-iff', 'hac-dvf', 'ref-track-L', 'ref-track-X', 'ref-track-hac-dvf'})} = 'open-loop'
    +  end
     
    -
    -

    Structure initialization

    -
    +
    +

    Structure initialization

    +
    -
    controller = struct();
    +
      controller = struct();
     
    -
    -

    Add Type

    -
    +
    +

    Add Type

    +
    -
    switch args.type
    -  case 'open-loop'
    -    controller.type = 0;
    -  case 'iff'
    -    controller.type = 1;
    -  case 'dvf'
    -    controller.type = 2;
    -  case 'hac-iff'
    -    controller.type = 3;
    -  case 'hac-dvf'
    -    controller.type = 4;
    -  case 'ref-track-L'
    -    controller.type = 5;
    -  case 'ref-track-X'
    -    controller.type = 6;
    -  case 'ref-track-hac-dvf'
    -    controller.type = 7;
    -end
    +
      switch args.type
    +    case 'open-loop'
    +      controller.type = 0;
    +    case 'iff'
    +      controller.type = 1;
    +    case 'dvf'
    +      controller.type = 2;
    +    case 'hac-iff'
    +      controller.type = 3;
    +    case 'hac-dvf'
    +      controller.type = 4;
    +    case 'ref-track-L'
    +      controller.type = 5;
    +    case 'ref-track-X'
    +      controller.type = 6;
    +    case 'ref-track-hac-dvf'
    +      controller.type = 7;
    +  end
     
    @@ -1210,7 +1215,7 @@ end

    Author: Dehaeze Thomas

    -

    Created: 2020-08-05 mer. 13:27

    +

    Created: 2021-01-08 ven. 15:29

    diff --git a/docs/cubic-configuration.html b/docs/cubic-configuration.html index bac1f15..0676bd4 100644 --- a/docs/cubic-configuration.html +++ b/docs/cubic-configuration.html @@ -3,25 +3,30 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + Cubic configuration for the Stewart Platform - - - - - - - - + + + +
    @@ -34,53 +39,53 @@

    Table of Contents