-If all the struts have the same stiffness \(k\), then \(K = k J^T J\)
-
-
-
-\(K\) only depends of the geometry of the stewart platform: it depends on the Jacobian, that is on the orientations of the struts, position of the joints and choice of frame \(\{B\}\).
-
-
-
-\[ F = K X \]
-
-
-
-With \(F\) forces and torques applied to the moving platform at the origin of \(\{B\}\) and \(X\) the translations and rotations of \(\{B\}\) with respect to \(\{A\}\).
-
-
-
-\[ C = K^{-1} \]
-
-
-
-The compliance element \(C_{ij}\) is then the stiffness
-\[ X_i = C_{ij} F_j \]
-
-There is no coupling from \(F_i\) to \(X_j\) if \(J^{-1} G J^{-T}\) is diagonal.
-
-
-
-If \(G\) is diagonal (cubic configuration), then \(J^{-1} G J^{-T} = G J^{-1} J^{-T} = G (J^{T} J)^{-1} = G K^{-1}\)
-
-
-
-Thus, the system is uncoupled if \(G\) and \(K\) are diagonal.
-
-
-
+
+
9 Architecture Optimization
-
Bibliography
-
[preumont07_six_axis_singl_stage_activ]Preumont, Horodinca, Romanescu, de, Marneffe, Avraam, Deraemaeker, Bossens, & Abu Hanieh, A Six-Axis Single-Stage Active Vibration Isolator Based on Stewart Platform, Journal of Sound and Vibration, 300(3-5), 644-661 (2007). link. doi.
diff --git a/index.org b/index.org
index fa42ab1..8c1208a 100644
--- a/index.org
+++ b/index.org
@@ -22,90 +22,37 @@
:END:
* Introduction :ignore:
-The goal here is to
+The goal here is to provide a Matlab/Simscape Toolbox to study Stewart platforms.
-* Simscape Model of the Stewart Platform
-- [[file:simscape-model.org][Model of the Stewart Platform]]
-- [[file:identification.org][Identification of the Simscape Model]]
+* Simulink Project ([[file:simulink-project.org][link]])
-* Architecture Study
-- [[file:kinematic-study.org][Kinematic Study]]
-- [[file:stiffness-study.org][Stiffness Matrix Study]]
-- Jacobian Study
-- [[file:cubic-configuration.org][Cubic Architecture]]
+* Stewart Platform Architecture Definition ([[file:stewart-architecture.org][link]])
-* Motion Control
-- Active Damping
-- Inertial Control
-- Decentralized Control
-* Notes about Stewart platforms :noexport:
-** Jacobian
-*** Relation to platform parameters
-A Jacobian is defined by:
-- the orientations of the struts $\hat{s}_i$ expressed in a frame $\{A\}$ linked to the fixed platform.
-- the vectors from $O_B$ to $b_i$ expressed in the frame $\{A\}$
+* Simscape Model of the Stewart Platform ([[file:simscape-model.org][link]])
-Then, the choice of $O_B$ changes the Jacobian.
-*** Jacobian for displacement
-\[ \dot{q} = J \dot{X} \]
-With:
-- $q = [q_1\ q_2\ q_3\ q_4\ q_5\ q_6]$ vector of linear displacement of actuated joints
-- $X = [x\ y\ z\ \theta_x\ \theta_y\ \theta_z]$ position and orientation of $O_B$ expressed in the frame $\{A\}$
+* Kinematic Analysis ([[file:kinematic-study.org][link]])
+- Jacobian Analysis
+- Stiffness Analysis
+- Static Forces
-For very small displacements $\delta q$ and $\delta X$, we have $\delta q = J \delta X$.
+* Identification of the Stewart Dynamics ([[file:identification.org][link]])
+- Extraction of State Space models
+- Resonant Frequencies and Modal Damping
+- Mode Shapes
-*** Jacobian for forces
-\[ F = J^T \tau \]
-With:
-- $\tau = [\tau_1\ \tau_2\ \tau_3\ \tau_4\ \tau_5\ \tau_6]$ vector of actuator forces
-- $F = [f_x\ f_y\ f_z\ n_x\ n_y\ n_z]$ force and torque acting on point $O_B$
+* Active Damping ([[file:active-damping.org][link]])
+- Inertial Sensor
+- Force Sensor
+- Relative Motion Sensor
-** Stiffness matrix $K$
+* Control of the Stewart Platform ([[file:control-study.org][link]])
-\[ K = J^T \text{diag}(k_i) J \]
+* Cubic Configuration ([[file:cubic-configuration.org][link]])
-If all the struts have the same stiffness $k$, then $K = k J^T J$
+* Architecture Optimization
-$K$ only depends of the geometry of the stewart platform: it depends on the Jacobian, that is on the orientations of the struts, position of the joints and choice of frame $\{B\}$.
-
-\[ F = K X \]
-
-With $F$ forces and torques applied to the moving platform at the origin of $\{B\}$ and $X$ the translations and rotations of $\{B\}$ with respect to $\{A\}$.
-
-\[ C = K^{-1} \]
-
-The compliance element $C_{ij}$ is then the stiffness
-\[ X_i = C_{ij} F_j \]
-
-** Coupling
-What causes the coupling from $F_i$ to $X_i$ ?
-
-#+begin_src latex :file coupling.pdf :post pdf2svg(file=*this*, ext="png") :exports both
- \begin{tikzpicture}
- \node[block] (Jt) at (0, 0) {$J^{-T}$};
- \node[block, right= of Jt] (G) {$G$};
- \node[block, right= of G] (J) {$J^{-1}$};
-
- \draw[->] ($(Jt.west)+(-0.8, 0)$) -- (Jt.west) node[above left]{$F_i$};
- \draw[->] (Jt.east) -- (G.west) node[above left]{$\tau_i$};
- \draw[->] (G.east) -- (J.west) node[above left]{$q_i$};
- \draw[->] (J.east) -- ++(0.8, 0) node[above left]{$X_i$};
- \end{tikzpicture}
-#+end_src
-
-#+name: fig:block_diag_coupling
-#+caption: Block diagram to control an hexapod
-#+RESULTS:
-[[file:figs/coupling.png]]
-
-There is no coupling from $F_i$ to $X_j$ if $J^{-1} G J^{-T}$ is diagonal.
-
-If $G$ is diagonal (cubic configuration), then $J^{-1} G J^{-T} = G J^{-1} J^{-T} = G (J^{T} J)^{-1} = G K^{-1}$
-
-Thus, the system is uncoupled if $G$ and $K$ are diagonal.
-
-* Bibliography :ignore:
+* Bibliography :ignore:
bibliographystyle:unsrt
bibliography:ref.bib
diff --git a/readme.org b/readme.org
new file mode 100644
index 0000000..1ba8fa4
--- /dev/null
+++ b/readme.org
@@ -0,0 +1,12 @@
+#+TITLE: Stewart Platforms Toolbox
+:DRAWER:
+#+OPTIONS: toc:nil
+#+OPTIONS: html-postamble:nil
+
+#+HTML_HEAD:
+#+HTML_HEAD:
+#+HTML_HEAD:
+#+HTML_HEAD:
+#+HTML_HEAD:
+#+HTML_HEAD:
+:END:
diff --git a/simscape-model.html b/simscape-model.html
index 6bd34d8..c39f8ff 100644
--- a/simscape-model.html
+++ b/simscape-model.html
@@ -4,7 +4,7 @@
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
+
Stewart Platform - Simscape Model
@@ -246,31 +246,6 @@ for the JavaScript code in this tag.
}
/*]]>*///-->
-
-
@@ -279,944 +254,11 @@ for the JavaScript code in this tag.
HOME
-Stewart platforms are generated in multiple steps.
-
-
-
-We define 4 important frames:
-
-
-
\(\{F\}\): Frame fixed to the Fixed base and located at the center of its bottom surface.
-This is used to fix the Stewart platform to some support.
-
\(\{M\}\): Frame fixed to the Moving platform and located at the center of its top surface.
-This is used to place things on top of the Stewart platform.
-
\(\{A\}\): Frame fixed to the fixed base.
-It defined the center of rotation of the moving platform.
-
\(\{B\}\): Frame fixed to the moving platform.
-The motion of the moving platforms and forces applied to it are defined with respect to this frame \(\{B\}\).
-
-
-
-Then, we define the location of the spherical joints:
-
-
-
\(\bm{a}_{i}\) are the position of the spherical joints fixed to the fixed base
-
\(\bm{b}_{i}\) are the position of the spherical joints fixed to the moving platform
-
-
-
-We define the rest position of the Stewart platform:
-
-
-
For simplicity, we suppose that the fixed base and the moving platform are parallel and aligned with the vertical axis at their rest position.
-
Thus, to define the rest position of the Stewart platform, we just have to defined its total height \(H\).
-\(H\) corresponds to the distance from the bottom of the fixed base to the top of the moving platform.
-
-
-
-From \(\bm{a}_{i}\) and \(\bm{b}_{i}\), we can determine the length and orientation of each strut:
-
-
-
\(l_{i}\) is the length of the strut
-
\({}^{A}\hat{\bm{s}}_{i}\) is the unit vector align with the strut
-
-
-
-The position of the Spherical joints can be computed using various methods:
-
-
-
Cubic configuration
-
Circular configuration
-
Arbitrary position
-
These methods should be easily scriptable and corresponds to specific functions that returns \({}^{F}\bm{a}_{i}\) and \({}^{M}\bm{b}_{i}\).
-The input of these functions are the parameters corresponding to the wanted geometry.
-
-
-
-For Simscape, we need:
-
-
-
The position and orientation of each spherical joint fixed to the fixed base: \({}^{F}\bm{a}_{i}\) and \({}^{F}\bm{R}_{a_{i}}\)
-
The position and orientation of each spherical joint fixed to the moving platform: \({}^{M}\bm{b}_{i}\) and \({}^{M}\bm{R}_{b_{i}}\)
-
The rest length of each strut: \(l_{i}\)
-
The stiffness and damping of each actuator: \(k_{i}\) and \(c_{i}\)
-
The position of the frame \(\{A\}\) with respect to the frame \(\{F\}\): \({}^{F}\bm{O}_{A}\)
-
The position of the frame \(\{B\}\) with respect to the frame \(\{M\}\): \({}^{M}\bm{O}_{B}\)
-
-
-
-
-
1 Procedure
-
-
-The procedure to define the Stewart platform is the following:
-
-
-
Define the initial position of frames {A}, {B}, {F} and {M}.
-We do that using the initializeFramesPositions function.
-We have to specify the total height of the Stewart platform \(H\) and the position \({}^{M}O_{B}\) of {B} with respect to {M}.
-
Compute the positions of joints \({}^{F}a_{i}\) and \({}^{M}b_{i}\).
-We can do that using various methods depending on the wanted architecture:
-
-
generateCubicConfiguration permits to generate a cubic configuration
-
-
Compute the position and orientation of the joints with respect to the fixed base and the moving platform.
-This is done with the computeJointsPose function.
-
Define the dynamical properties of the Stewart platform.
-The output are the stiffness and damping of each strut \(k_{i}\) and \(c_{i}\).
-This can be done we simply choosing directly the stiffness and damping of each strut.
-The stiffness and damping of each actuator can also be determine from the wanted stiffness of the Stewart platform for instance.
-
Define the mass and inertia of each element of the Stewart platform.
-
-
-
-By following this procedure, we obtain a Matlab structure stewart that contains all the information for the Simscape model and for further analysis.
-
function[stewart] = initializeFramesPositions(args)
-% initializeFramesPositions - Initialize the positions of frames {A}, {B}, {F} and {M}
-%
-% Syntax: [stewart] = initializeFramesPositions(args)
-%
-% Inputs:
-% - args - Can have the following fields:
-% - H [1x1] - Total Height of the Stewart Platform (height from {F} to {M}) [m]
-% - MO_B [1x1] - Height of the frame {B} with respect to {M} [m]
-%
-% Outputs:
-% - stewart - A structure with the following fields:
-% - H [1x1] - Total Height of the Stewart Platform [m]
-% - FO_M [3x1] - Position of {M} with respect to {F} [m]
-% - MO_B [3x1] - Position of {B} with respect to {M} [m]
-% - FO_A [3x1] - Position of {A} with respect to {F} [m]
-
-
-
-
-
-
-
3.2 Documentation
-
-
-
-
-
-
Figure 1: Definition of the position of the frames
stewart.H = args.H; % Total Height of the Stewart Platform [m]
-
-stewart.FO_M = [0; 0; stewart.H]; % Position of {M} with respect to {F} [m]
-
-stewart.MO_B = [0; 0; args.MO_B]; % Position of {B} with respect to {M} [m]
-
-stewart.FO_A = stewart.MO_B + stewart.FO_M; % Position of {A} with respect to {F} [m]
-
-
-
-
-
-
-
-
4generateCubicConfiguration: Generate a Cubic Configuration
function[stewart] = generateCubicConfiguration(stewart, args)
-% generateCubicConfiguration - Generate a Cubic Configuration
-%
-% Syntax: [stewart] = generateCubicConfiguration(stewart, args)
-%
-% Inputs:
-% - stewart - A structure with the following fields
-% - H [1x1] - Total height of the platform [m]
-% - args - Can have the following fields:
-% - Hc [1x1] - Height of the "useful" part of the cube [m]
-% - FOc [1x1] - Height of the center of the cube with respect to {F} [m]
-% - FHa [1x1] - Height of the plane joining the points ai with respect to the frame {F} [m]
-% - MHb [1x1] - Height of the plane joining the points bi with respect to the frame {M} [m]
-%
-% Outputs:
-% - stewart - updated Stewart structure with the added fields:
-% - Fa [3x6] - Its i'th column is the position vector of joint ai with respect to {F}
-% - Mb [3x6] - Its i'th column is the position vector of joint bi with respect to {M}
-
-We define the useful points of the cube with respect to the Cube’s center.
-\({}^{C}C\) are the 6 vertices of the cubes expressed in a frame {C} which is
-located at the center of the cube and aligned with {F} and {M}.
-
-
-
-
sx = [ 2; -1; -1];
-sy = [ 0; 1; -1];
-sz = [ 1; 1; 1];
-
-R = [sx, sy, sz]./vecnorm([sx, sy, sz]);
-
-L = args.Hc*sqrt(3);
-
-Cc = R'*[[0;0;L],[L;0;L],[L;0;0],[L;L;0],[0;L;0],[0;L;L]] - [0;0;1.5*args.Hc];
-
-CCf = [Cc(:,1), Cc(:,3), Cc(:,3), Cc(:,5), Cc(:,5), Cc(:,1)]; % CCf(:,i) corresponds to the bottom cube's vertice corresponding to the i'th leg
-CCm = [Cc(:,2), Cc(:,2), Cc(:,4), Cc(:,4), Cc(:,6), Cc(:,6)]; % CCm(:,i) corresponds to the top cube's vertice corresponding to the i'th leg
-
-
-
-
-
-
-
4.5 Compute the pose
-
-
-We can compute the vector of each leg \({}^{C}\hat{\bm{s}}_{i}\) (unit vector from \({}^{C}C_{f}\) to \({}^{C}C_{m}\)).
-
-
-
CSi = (CCm - CCf)./vecnorm(CCm - CCf);
-
-
-
-
-We now which to compute the position of the joints \(a_{i}\) and \(b_{i}\).
-
function[stewart] = generateGeneralConfiguration(stewart, args)
-% generateGeneralConfiguration - Generate a Very General Configuration
-%
-% Syntax: [stewart] = generateGeneralConfiguration(stewart, args)
-%
-% Inputs:
-% - stewart - A structure with the following fields
-% - H [1x1] - Total height of the platform [m]
-% - args - Can have the following fields:
-% - FH [1x1] - Height of the position of the fixed joints with respect to the frame {F} [m]
-% - FR [1x1] - Radius of the position of the fixed joints in the X-Y [m]
-% - FTh [6x1] - Angles of the fixed joints in the X-Y plane with respect to the X axis [rad]
-% - MH [1x1] - Height of the position of the mobile joints with respect to the frame {M} [m]
-% - FR [1x1] - Radius of the position of the mobile joints in the X-Y [m]
-% - MTh [6x1] - Angles of the mobile joints in the X-Y plane with respect to the X axis [rad]
-%
-% Outputs:
-% - stewart - updated Stewart structure with the added fields:
-% - Fa [3x6] - Its i'th column is the position vector of joint ai with respect to {F}
-% - Mb [3x6] - Its i'th column is the position vector of joint bi with respect to {M}
-
-
-
-
-
-
-
5.2 Documentation
-
-
-Joints are positions on a circle centered with the Z axis of {F} and {M} and at a chosen distance from {F} and {M}.
-The radius of the circles can be chosen as well as the angles where the joints are located.
-
function[stewart] = computeJointsPose(stewart)
-% computeJointsPose -
-%
-% Syntax: [stewart] = computeJointsPose(stewart)
-%
-% Inputs:
-% - stewart - A structure with the following fields
-% - Fa [3x6] - Its i'th column is the position vector of joint ai with respect to {F}
-% - Mb [3x6] - Its i'th column is the position vector of joint bi with respect to {M}
-% - FO_A [3x1] - Position of {A} with respect to {F}
-% - MO_B [3x1] - Position of {B} with respect to {M}
-% - FO_M [3x1] - Position of {M} with respect to {F}
-%
-% Outputs:
-% - stewart - A structure with the following added fields
-% - Aa [3x6] - The i'th column is the position of ai with respect to {A}
-% - Ab [3x6] - The i'th column is the position of bi with respect to {A}
-% - Ba [3x6] - The i'th column is the position of ai with respect to {B}
-% - Bb [3x6] - The i'th column is the position of bi with respect to {B}
-% - l [6x1] - The i'th element is the initial length of strut i
-% - As [3x6] - The i'th column is the unit vector of strut i expressed in {A}
-% - Bs [3x6] - The i'th column is the unit vector of strut i expressed in {B}
-% - FRa [3x3x6] - The i'th 3x3 array is the rotation matrix to orientate the bottom of the i'th strut from {F}
-% - MRb [3x3x6] - The i'th 3x3 array is the rotation matrix to orientate the top of the i'th strut from {M}
-
function[stewart] = initializeStrutDynamics(stewart, args)
-% initializeStrutDynamics - Add Stiffness and Damping properties of each strut
-%
-% Syntax: [stewart] = initializeStrutDynamics(args)
-%
-% Inputs:
-% - args - Structure with the following fields:
-% - Ki [6x1] - Stiffness of each strut [N/m]
-% - Ci [6x1] - Damping of each strut [N/(m/s)]
-%
-% Outputs:
-% - stewart - updated Stewart structure with the added fields:
-% - Ki [6x1] - Stiffness of each strut [N/m]
-% - Ci [6x1] - Damping of each strut [N/(m/s)]
-
function[stewart] = computeJacobian(stewart)
-% computeJacobian -
-%
-% Syntax: [stewart] = computeJacobian(stewart)
-%
-% Inputs:
-% - stewart - With at least the following fields:
-% - As [3x6] - The 6 unit vectors for each strut expressed in {A}
-% - Ab [3x6] - The 6 position of the joints bi expressed in {A}
-%
-% Outputs:
-% - stewart - With the 3 added field:
-% - J [6x6] - The Jacobian Matrix
-% - K [6x6] - The Stiffness Matrix
-% - C [6x6] - The Compliance Matrix
-
function[Li, dLi] = inverseKinematics(stewart, args)
-% inverseKinematics - Compute the needed length of each strut to have the wanted position and orientation of {B} with respect to {A}
-%
-% Syntax: [stewart] = inverseKinematics(stewart)
-%
-% Inputs:
-% - stewart - A structure with the following fields
-% - Aa [3x6] - The positions ai expressed in {A}
-% - Bb [3x6] - The positions bi expressed in {B}
-% - args - Can have the following fields:
-% - AP [3x1] - The wanted position of {B} with respect to {A}
-% - ARB [3x3] - The rotation matrix that gives the wanted orientation of {B} with respect to {A}
-%
-% Outputs:
-% - Li [6x1] - The 6 needed length of the struts in [m] to have the wanted pose of {B} w.r.t. {A}
-% - dLi [6x1] - The 6 needed displacement of the struts from the initial position in [m] to have the wanted pose of {B} w.r.t. {A}
-
-For inverse kinematic analysis, it is assumed that the position \({}^A\bm{P}\) and orientation of the moving platform \({}^A\bm{R}_B\) are given and the problem is to obtain the joint variables, namely, \(\bm{L} = [l_1, l_2, \dots, l_6]^T\).
-
-
-
-From the geometry of the manipulator, the loop closure for each limb, \(i = 1, 2, \dots, 6\) can be written as
-
-If the position and orientation of the moving platform lie in the feasible workspace of the manipulator, one unique solution to the limb length is determined by the above equation.
-Otherwise, when the limbs’ lengths derived yield complex numbers, then the position or orientation of the moving platform is not reachable.
-
function[P, R] = forwardKinematicsApprox(stewart, args)
-% forwardKinematicsApprox - Computed the approximate pose of {B} with respect to {A} from the length of each strut and using
-% the Jacobian Matrix
-%
-% Syntax: [P, R] = forwardKinematicsApprox(stewart, args)
-%
-% Inputs:
-% - stewart - A structure with the following fields
-% - J [6x6] - The Jacobian Matrix
-% - args - Can have the following fields:
-% - dL [6x1] - Displacement of each strut [m]
-%
-% Outputs:
-% - P [3x1] - The estimated position of {B} with respect to {A}
-% - R [3x3] - The estimated rotation matrix that gives the orientation of {B} with respect to {A}
-
-From a small displacement of each strut \(d\bm{\mathcal{L}}\), we can compute the
-position and orientation of {B} with respect to {A} using the following formula:
-\[ d \bm{\mathcal{X}} = \bm{J}^{-1} d\bm{\mathcal{L}} \]
-
-
-
X = stewart.J\args.dL;
-
-
-
-
-The position vector corresponds to the first 3 elements.
-
-
-
P = X(1:3);
-
-
-
-
-The next 3 elements are the orientation of {B} with respect to {A} expressed
-using the screw axis.
-
-
-
theta = norm(X(4:6));
-s = X(4:6)/theta;
-
-
-
-
-We then compute the corresponding rotation matrix.
-
diff --git a/simscape-model.org b/simscape-model.org
index 30675e7..a1f2556 100644
--- a/simscape-model.org
+++ b/simscape-model.org
@@ -20,1596 +20,3 @@
#+PROPERTY: header-args:matlab+ :output-dir figs
:END:
-* Introduction :ignore:
-Stewart platforms are generated in multiple steps.
-
-We define 4 important *frames*:
-- $\{F\}$: Frame fixed to the *Fixed* base and located at the center of its bottom surface.
- This is used to fix the Stewart platform to some support.
-- $\{M\}$: Frame fixed to the *Moving* platform and located at the center of its top surface.
- This is used to place things on top of the Stewart platform.
-- $\{A\}$: Frame fixed to the fixed base.
- It defined the center of rotation of the moving platform.
-- $\{B\}$: Frame fixed to the moving platform.
- The motion of the moving platforms and forces applied to it are defined with respect to this frame $\{B\}$.
-
-Then, we define the *location of the spherical joints*:
-- $\bm{a}_{i}$ are the position of the spherical joints fixed to the fixed base
-- $\bm{b}_{i}$ are the position of the spherical joints fixed to the moving platform
-
-We define the *rest position* of the Stewart platform:
-- For simplicity, we suppose that the fixed base and the moving platform are parallel and aligned with the vertical axis at their rest position.
-- Thus, to define the rest position of the Stewart platform, we just have to defined its total height $H$.
- $H$ corresponds to the distance from the bottom of the fixed base to the top of the moving platform.
-
-From $\bm{a}_{i}$ and $\bm{b}_{i}$, we can determine the *length and orientation of each strut*:
-- $l_{i}$ is the length of the strut
-- ${}^{A}\hat{\bm{s}}_{i}$ is the unit vector align with the strut
-
-The position of the Spherical joints can be computed using various methods:
-- Cubic configuration
-- Circular configuration
-- Arbitrary position
-- These methods should be easily scriptable and corresponds to specific functions that returns ${}^{F}\bm{a}_{i}$ and ${}^{M}\bm{b}_{i}$.
- The input of these functions are the parameters corresponding to the wanted geometry.
-
-For Simscape, we need:
-- The position and orientation of each spherical joint fixed to the fixed base: ${}^{F}\bm{a}_{i}$ and ${}^{F}\bm{R}_{a_{i}}$
-- The position and orientation of each spherical joint fixed to the moving platform: ${}^{M}\bm{b}_{i}$ and ${}^{M}\bm{R}_{b_{i}}$
-- The rest length of each strut: $l_{i}$
-- The stiffness and damping of each actuator: $k_{i}$ and $c_{i}$
-- The position of the frame $\{A\}$ with respect to the frame $\{F\}$: ${}^{F}\bm{O}_{A}$
-- The position of the frame $\{B\}$ with respect to the frame $\{M\}$: ${}^{M}\bm{O}_{B}$
-
-
-* Procedure
-The procedure to define the Stewart platform is the following:
-1. Define the initial position of frames {A}, {B}, {F} and {M}.
- We do that using the =initializeFramesPositions= function.
- We have to specify the total height of the Stewart platform $H$ and the position ${}^{M}O_{B}$ of {B} with respect to {M}.
-2. Compute the positions of joints ${}^{F}a_{i}$ and ${}^{M}b_{i}$.
- We can do that using various methods depending on the wanted architecture:
- - =generateCubicConfiguration= permits to generate a cubic configuration
-3. Compute the position and orientation of the joints with respect to the fixed base and the moving platform.
- This is done with the =computeJointsPose= function.
-4. Define the dynamical properties of the Stewart platform.
- The output are the stiffness and damping of each strut $k_{i}$ and $c_{i}$.
- This can be done we simply choosing directly the stiffness and damping of each strut.
- The stiffness and damping of each actuator can also be determine from the wanted stiffness of the Stewart platform for instance.
-5. Define the mass and inertia of each element of the Stewart platform.
-
-By following this procedure, we obtain a Matlab structure =stewart= that contains all the information for the Simscape model and for further analysis.
-
-* Matlab Code
-** Matlab Init :noexport:ignore:
-#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name)
- <>
-#+end_src
-
-#+begin_src matlab :exports none :results silent :noweb yes
- <>
-#+end_src
-
-#+begin_src matlab
- simulinkproject('./');
-#+end_src
-
-** Simscape Model
-#+begin_src matlab
- open('stewart_platform.slx')
-#+end_src
-
-** Test the functions
-#+begin_src matlab
- stewart = initializeFramesPositions('H', 90e-3, 'MO_B', 45e-3);
- % stewart = generateCubicConfiguration(stewart, 'Hc', 60e-3, 'FOc', 45e-3, 'FHa', 5e-3, 'MHb', 5e-3);
- stewart = generateGeneralConfiguration(stewart);
- stewart = computeJointsPose(stewart);
- stewart = initializeStrutDynamics(stewart, 'Ki', 1e6*ones(6,1), 'Ci', 1e2*ones(6,1));
- stewart = initializeCylindricalPlatforms(stewart);
- stewart = initializeCylindricalStruts(stewart);
- stewart = computeJacobian(stewart);
- stewart = initializeStewartPose(stewart, 'AP', [0;0;0.01], 'ARB', eye(3));
-
- [Li, dLi] = inverseKinematics(stewart, 'AP', [0;0;0.00001], 'ARB', eye(3));
- [P, R] = forwardKinematicsApprox(stewart, 'dL', dLi);
-#+end_src
-
-* =initializeFramesPositions=: Initialize the positions of frames {A}, {B}, {F} and {M}
-:PROPERTIES:
-:header-args:matlab+: :tangle src/initializeFramesPositions.m
-:header-args:matlab+: :comments none :mkdirp yes :eval no
-:END:
-<>
-
-This Matlab function is accessible [[file:src/initializeFramesPositions.m][here]].
-
-** Function description
-#+begin_src matlab
- function [stewart] = initializeFramesPositions(args)
- % initializeFramesPositions - Initialize the positions of frames {A}, {B}, {F} and {M}
- %
- % Syntax: [stewart] = initializeFramesPositions(args)
- %
- % Inputs:
- % - args - Can have the following fields:
- % - H [1x1] - Total Height of the Stewart Platform (height from {F} to {M}) [m]
- % - MO_B [1x1] - Height of the frame {B} with respect to {M} [m]
- %
- % Outputs:
- % - stewart - A structure with the following fields:
- % - H [1x1] - Total Height of the Stewart Platform [m]
- % - FO_M [3x1] - Position of {M} with respect to {F} [m]
- % - MO_B [3x1] - Position of {B} with respect to {M} [m]
- % - FO_A [3x1] - Position of {A} with respect to {F} [m]
-#+end_src
-
-** Documentation
-
-#+name: fig:stewart-frames-position
-#+caption: Definition of the position of the frames
-[[file:figs/stewart-frames-position.png]]
-
-** Optional Parameters
-#+begin_src matlab
- arguments
- args.H (1,1) double {mustBeNumeric, mustBePositive} = 90e-3
- args.MO_B (1,1) double {mustBeNumeric} = 50e-3
- end
-#+end_src
-
-** Initialize the Stewart structure
-#+begin_src matlab
- stewart = struct();
-#+end_src
-
-** Compute the position of each frame
-#+begin_src matlab
- stewart.H = args.H; % Total Height of the Stewart Platform [m]
-
- stewart.FO_M = [0; 0; stewart.H]; % Position of {M} with respect to {F} [m]
-
- stewart.MO_B = [0; 0; args.MO_B]; % Position of {B} with respect to {M} [m]
-
- stewart.FO_A = stewart.MO_B + stewart.FO_M; % Position of {A} with respect to {F} [m]
-#+end_src
-
-* Initialize the position of the Joints
-** =generateCubicConfiguration=: Generate a Cubic Configuration
-:PROPERTIES:
-:header-args:matlab+: :tangle src/generateCubicConfiguration.m
-:header-args:matlab+: :comments none :mkdirp yes :eval no
-:END:
-<>
-
-This Matlab function is accessible [[file:src/generateCubicConfiguration.m][here]].
-
-*** Function description
-#+begin_src matlab
- function [stewart] = generateCubicConfiguration(stewart, args)
- % generateCubicConfiguration - Generate a Cubic Configuration
- %
- % Syntax: [stewart] = generateCubicConfiguration(stewart, args)
- %
- % Inputs:
- % - stewart - A structure with the following fields
- % - H [1x1] - Total height of the platform [m]
- % - args - Can have the following fields:
- % - Hc [1x1] - Height of the "useful" part of the cube [m]
- % - FOc [1x1] - Height of the center of the cube with respect to {F} [m]
- % - FHa [1x1] - Height of the plane joining the points ai with respect to the frame {F} [m]
- % - MHb [1x1] - Height of the plane joining the points bi with respect to the frame {M} [m]
- %
- % Outputs:
- % - stewart - updated Stewart structure with the added fields:
- % - Fa [3x6] - Its i'th column is the position vector of joint ai with respect to {F}
- % - Mb [3x6] - Its i'th column is the position vector of joint bi with respect to {M}
-#+end_src
-
-*** Documentation
-#+name: fig:cubic-configuration-definition
-#+caption: Cubic Configuration
-[[file:figs/cubic-configuration-definition.png]]
-
-*** Optional Parameters
-#+begin_src matlab
- arguments
- stewart
- args.Hc (1,1) double {mustBeNumeric, mustBePositive} = 60e-3
- args.FOc (1,1) double {mustBeNumeric} = 50e-3
- args.FHa (1,1) double {mustBeNumeric, mustBePositive} = 15e-3
- args.MHb (1,1) double {mustBeNumeric, mustBePositive} = 15e-3
- end
-#+end_src
-
-*** Position of the Cube
-We define the useful points of the cube with respect to the Cube's center.
-${}^{C}C$ are the 6 vertices of the cubes expressed in a frame {C} which is
-located at the center of the cube and aligned with {F} and {M}.
-
-#+begin_src matlab
- sx = [ 2; -1; -1];
- sy = [ 0; 1; -1];
- sz = [ 1; 1; 1];
-
- R = [sx, sy, sz]./vecnorm([sx, sy, sz]);
-
- L = args.Hc*sqrt(3);
-
- Cc = R'*[[0;0;L],[L;0;L],[L;0;0],[L;L;0],[0;L;0],[0;L;L]] - [0;0;1.5*args.Hc];
-
- CCf = [Cc(:,1), Cc(:,3), Cc(:,3), Cc(:,5), Cc(:,5), Cc(:,1)]; % CCf(:,i) corresponds to the bottom cube's vertice corresponding to the i'th leg
- CCm = [Cc(:,2), Cc(:,2), Cc(:,4), Cc(:,4), Cc(:,6), Cc(:,6)]; % CCm(:,i) corresponds to the top cube's vertice corresponding to the i'th leg
-#+end_src
-
-*** Compute the pose
-We can compute the vector of each leg ${}^{C}\hat{\bm{s}}_{i}$ (unit vector from ${}^{C}C_{f}$ to ${}^{C}C_{m}$).
-#+begin_src matlab
- CSi = (CCm - CCf)./vecnorm(CCm - CCf);
-#+end_src
-
-We now which to compute the position of the joints $a_{i}$ and $b_{i}$.
-#+begin_src matlab
- stewart.Fa = CCf + [0; 0; args.FOc] + ((args.FHa-(args.FOc-args.Hc/2))./CSi(3,:)).*CSi;
- stewart.Mb = CCf + [0; 0; args.FOc-stewart.H] + ((stewart.H-args.MHb-(args.FOc-args.Hc/2))./CSi(3,:)).*CSi;
-#+end_src
-
-** =generateGeneralConfiguration=: Generate a Very General Configuration
-:PROPERTIES:
-:header-args:matlab+: :tangle src/generateGeneralConfiguration.m
-:header-args:matlab+: :comments none :mkdirp yes :eval no
-:END:
-<>
-
-This Matlab function is accessible [[file:src/generateGeneralConfiguration.m][here]].
-
-*** Function description
-#+begin_src matlab
- function [stewart] = generateGeneralConfiguration(stewart, args)
- % generateGeneralConfiguration - Generate a Very General Configuration
- %
- % Syntax: [stewart] = generateGeneralConfiguration(stewart, args)
- %
- % Inputs:
- % - args - Can have the following fields:
- % - FH [1x1] - Height of the position of the fixed joints with respect to the frame {F} [m]
- % - FR [1x1] - Radius of the position of the fixed joints in the X-Y [m]
- % - FTh [6x1] - Angles of the fixed joints in the X-Y plane with respect to the X axis [rad]
- % - MH [1x1] - Height of the position of the mobile joints with respect to the frame {M} [m]
- % - FR [1x1] - Radius of the position of the mobile joints in the X-Y [m]
- % - MTh [6x1] - Angles of the mobile joints in the X-Y plane with respect to the X axis [rad]
- %
- % Outputs:
- % - stewart - updated Stewart structure with the added fields:
- % - Fa [3x6] - Its i'th column is the position vector of joint ai with respect to {F}
- % - Mb [3x6] - Its i'th column is the position vector of joint bi with respect to {M}
-#+end_src
-
-*** Documentation
-Joints are positions on a circle centered with the Z axis of {F} and {M} and at a chosen distance from {F} and {M}.
-The radius of the circles can be chosen as well as the angles where the joints are located.
-
-*** Optional Parameters
-#+begin_src matlab
- arguments
- stewart
- args.FH (1,1) double {mustBeNumeric, mustBePositive} = 15e-3
- args.FR (1,1) double {mustBeNumeric, mustBePositive} = 90e-3;
- args.FTh (6,1) double {mustBeNumeric} = [-10, 10, 120-10, 120+10, 240-10, 240+10]*(pi/180);
- args.MH (1,1) double {mustBeNumeric, mustBePositive} = 15e-3
- args.MR (1,1) double {mustBeNumeric, mustBePositive} = 70e-3;
- args.MTh (6,1) double {mustBeNumeric} = [-60+10, 60-10, 60+10, 180-10, 180+10, -60-10]*(pi/180);
- end
-#+end_src
-
-*** Compute the pose
-#+begin_src matlab
- stewart.Fa = zeros(3,6);
- stewart.Mb = zeros(3,6);
-#+end_src
-
-#+begin_src matlab
- for i = 1:6
- stewart.Fa(:,i) = [args.FR*cos(args.FTh(i)); args.FR*sin(args.FTh(i)); args.FH];
- stewart.Mb(:,i) = [args.MR*cos(args.MTh(i)); args.MR*sin(args.MTh(i)); -args.MH];
- end
-#+end_src
-
-* =computeJointsPose=: Compute the Pose of the Joints
-:PROPERTIES:
-:header-args:matlab+: :tangle src/computeJointsPose.m
-:header-args:matlab+: :comments none :mkdirp yes :eval no
-:END:
-<>
-
-This Matlab function is accessible [[file:src/computeJointsPose.m][here]].
-
-** Function description
-#+begin_src matlab
- function [stewart] = computeJointsPose(stewart)
- % computeJointsPose -
- %
- % Syntax: [stewart] = computeJointsPose(stewart)
- %
- % Inputs:
- % - stewart - A structure with the following fields
- % - Fa [3x6] - Its i'th column is the position vector of joint ai with respect to {F}
- % - Mb [3x6] - Its i'th column is the position vector of joint bi with respect to {M}
- % - FO_A [3x1] - Position of {A} with respect to {F}
- % - MO_B [3x1] - Position of {B} with respect to {M}
- % - FO_M [3x1] - Position of {M} with respect to {F}
- %
- % Outputs:
- % - stewart - A structure with the following added fields
- % - Aa [3x6] - The i'th column is the position of ai with respect to {A}
- % - Ab [3x6] - The i'th column is the position of bi with respect to {A}
- % - Ba [3x6] - The i'th column is the position of ai with respect to {B}
- % - Bb [3x6] - The i'th column is the position of bi with respect to {B}
- % - l [6x1] - The i'th element is the initial length of strut i
- % - As [3x6] - The i'th column is the unit vector of strut i expressed in {A}
- % - Bs [3x6] - The i'th column is the unit vector of strut i expressed in {B}
- % - FRa [3x3x6] - The i'th 3x3 array is the rotation matrix to orientate the bottom of the i'th strut from {F}
- % - MRb [3x3x6] - The i'th 3x3 array is the rotation matrix to orientate the top of the i'th strut from {M}
-#+end_src
-
-** Documentation
-
-#+name: fig:stewart-struts
-#+caption: Position and orientation of the struts
-[[file:figs/stewart-struts.png]]
-
-** Compute the position of the Joints
-#+begin_src matlab
- stewart.Aa = stewart.Fa - repmat(stewart.FO_A, [1, 6]);
- stewart.Bb = stewart.Mb - repmat(stewart.MO_B, [1, 6]);
-
- stewart.Ab = stewart.Bb - repmat(-stewart.MO_B-stewart.FO_M+stewart.FO_A, [1, 6]);
- stewart.Ba = stewart.Aa - repmat( stewart.MO_B+stewart.FO_M-stewart.FO_A, [1, 6]);
-#+end_src
-
-** Compute the strut length and orientation
-#+begin_src matlab
- stewart.As = (stewart.Ab - stewart.Aa)./vecnorm(stewart.Ab - stewart.Aa); % As_i is the i'th vector of As
-
- stewart.l = vecnorm(stewart.Ab - stewart.Aa)';
-#+end_src
-
-#+begin_src matlab
- stewart.Bs = (stewart.Bb - stewart.Ba)./vecnorm(stewart.Bb - stewart.Ba);
-#+end_src
-
-** Compute the orientation of the Joints
-#+begin_src matlab
- stewart.FRa = zeros(3,3,6);
- stewart.MRb = zeros(3,3,6);
-
- for i = 1:6
- stewart.FRa(:,:,i) = [cross([0;1;0], stewart.As(:,i)) , cross(stewart.As(:,i), cross([0;1;0], stewart.As(:,i))) , stewart.As(:,i)];
- stewart.FRa(:,:,i) = stewart.FRa(:,:,i)./vecnorm(stewart.FRa(:,:,i));
-
- stewart.MRb(:,:,i) = [cross([0;1;0], stewart.Bs(:,i)) , cross(stewart.Bs(:,i), cross([0;1;0], stewart.Bs(:,i))) , stewart.Bs(:,i)];
- stewart.MRb(:,:,i) = stewart.MRb(:,:,i)./vecnorm(stewart.MRb(:,:,i));
- end
-#+end_src
-
-* =initializeStrutDynamics=: Add Stiffness and Damping properties of each strut
-:PROPERTIES:
-:header-args:matlab+: :tangle src/initializeStrutDynamics.m
-:header-args:matlab+: :comments none :mkdirp yes :eval no
-:END:
-<>
-
-This Matlab function is accessible [[file:src/initializeStrutDynamics.m][here]].
-
-** Function description
-#+begin_src matlab
- function [stewart] = initializeStrutDynamics(stewart, args)
- % initializeStrutDynamics - Add Stiffness and Damping properties of each strut
- %
- % Syntax: [stewart] = initializeStrutDynamics(args)
- %
- % Inputs:
- % - args - Structure with the following fields:
- % - Ki [6x1] - Stiffness of each strut [N/m]
- % - Ci [6x1] - Damping of each strut [N/(m/s)]
- %
- % Outputs:
- % - stewart - updated Stewart structure with the added fields:
- % - Ki [6x1] - Stiffness of each strut [N/m]
- % - Ci [6x1] - Damping of each strut [N/(m/s)]
-#+end_src
-
-** Optional Parameters
-#+begin_src matlab
- arguments
- stewart
- args.Ki (6,1) double {mustBeNumeric, mustBePositive} = 1e6*ones(6,1)
- args.Ci (6,1) double {mustBeNumeric, mustBePositive} = 1e3*ones(6,1)
- end
-#+end_src
-
-** Add Stiffness and Damping properties of each strut
-#+begin_src matlab
- stewart.Ki = args.Ki;
- stewart.Ci = args.Ci;
-#+end_src
-
-* =computeJacobian=: Compute the Jacobian Matrix
-:PROPERTIES:
-:header-args:matlab+: :tangle src/computeJacobian.m
-:header-args:matlab+: :comments none :mkdirp yes :eval no
-:END:
-<>
-
-This Matlab function is accessible [[file:src/computeJacobian.m][here]].
-
-** Function description
-#+begin_src matlab
- function [stewart] = computeJacobian(stewart)
- % computeJacobian -
- %
- % Syntax: [stewart] = computeJacobian(stewart)
- %
- % Inputs:
- % - stewart - With at least the following fields:
- % - As [3x6] - The 6 unit vectors for each strut expressed in {A}
- % - Ab [3x6] - The 6 position of the joints bi expressed in {A}
- %
- % Outputs:
- % - stewart - With the 3 added field:
- % - J [6x6] - The Jacobian Matrix
- % - K [6x6] - The Stiffness Matrix
- % - C [6x6] - The Compliance Matrix
-#+end_src
-
-** Compute Jacobian Matrix
-#+begin_src matlab
- stewart.J = [stewart.As' , cross(stewart.Ab, stewart.As)'];
-#+end_src
-
-** Compute Stiffness Matrix
-#+begin_src matlab
- stewart.K = stewart.J'*diag(stewart.Ki)*stewart.J;
-#+end_src
-
-** Compute Compliance Matrix
-#+begin_src matlab
- stewart.C = inv(stewart.K);
-#+end_src
-
-* Initialize the Geometry of the Mechanical Elements
-** =initializeCylindricalPlatforms=: Initialize the geometry of the Fixed and Mobile Platforms
-:PROPERTIES:
-:header-args:matlab+: :tangle src/initializeCylindricalPlatforms.m
-:header-args:matlab+: :comments none :mkdirp yes :eval no
-:END:
-<>
-
-This Matlab function is accessible [[file:src/initializeCylindricalPlatforms.m][here]].
-
-*** Function description
-#+begin_src matlab
- function [stewart] = initializeCylindricalPlatforms(stewart, args)
- % initializeCylindricalPlatforms - Initialize the geometry of the Fixed and Mobile Platforms
- %
- % Syntax: [stewart] = initializeCylindricalPlatforms(args)
- %
- % Inputs:
- % - args - Structure with the following fields:
- % - Fpm [1x1] - Fixed Platform Mass [kg]
- % - Fph [1x1] - Fixed Platform Height [m]
- % - Fpr [1x1] - Fixed Platform Radius [m]
- % - Mpm [1x1] - Mobile Platform Mass [kg]
- % - Mph [1x1] - Mobile Platform Height [m]
- % - Mpr [1x1] - Mobile Platform Radius [m]
- %
- % Outputs:
- % - stewart - updated Stewart structure with the added fields:
- % - platforms [struct] - structure with the following fields:
- % - Fpm [1x1] - Fixed Platform Mass [kg]
- % - Msi [3x3] - Mobile Platform Inertia matrix [kg*m^2]
- % - Fph [1x1] - Fixed Platform Height [m]
- % - Fpr [1x1] - Fixed Platform Radius [m]
- % - Mpm [1x1] - Mobile Platform Mass [kg]
- % - Fsi [3x3] - Fixed Platform Inertia matrix [kg*m^2]
- % - Mph [1x1] - Mobile Platform Height [m]
- % - Mpr [1x1] - Mobile Platform Radius [m]
-#+end_src
-
-*** Optional Parameters
-#+begin_src matlab
- arguments
- stewart
- args.Fpm (1,1) double {mustBeNumeric, mustBePositive} = 1
- args.Fph (1,1) double {mustBeNumeric, mustBePositive} = 10e-3
- args.Fpr (1,1) double {mustBeNumeric, mustBePositive} = 125e-3
- args.Mpm (1,1) double {mustBeNumeric, mustBePositive} = 1
- args.Mph (1,1) double {mustBeNumeric, mustBePositive} = 10e-3
- args.Mpr (1,1) double {mustBeNumeric, mustBePositive} = 100e-3
- end
-#+end_src
-
-*** Create the =platforms= struct
-#+begin_src matlab
- platforms = struct();
-
- platforms.Fpm = args.Fpm;
- platforms.Fph = args.Fph;
- platforms.Fpr = args.Fpr;
- platforms.Fpi = diag([1/12 * platforms.Fpm * (3*platforms.Fpr^2 + platforms.Fph^2), ...
- 1/12 * platforms.Fpm * (3*platforms.Fpr^2 + platforms.Fph^2), ...
- 1/2 * platforms.Fpm * platforms.Fpr^2]);
-
- platforms.Mpm = args.Mpm;
- platforms.Mph = args.Mph;
- platforms.Mpr = args.Mpr;
- platforms.Mpi = diag([1/12 * platforms.Mpm * (3*platforms.Mpr^2 + platforms.Mph^2), ...
- 1/12 * platforms.Mpm * (3*platforms.Mpr^2 + platforms.Mph^2), ...
- 1/2 * platforms.Mpm * platforms.Mpr^2]);
-#+end_src
-
-*** Save the =platforms= struct
-#+begin_src matlab
- stewart.platforms = platforms;
-#+end_src
-
-** =initializeCylindricalStruts=: Define the mass and moment of inertia of cylindrical struts
-:PROPERTIES:
-:header-args:matlab+: :tangle src/initializeCylindricalStruts.m
-:header-args:matlab+: :comments none :mkdirp yes :eval no
-:END:
-<>
-
-This Matlab function is accessible [[file:src/initializeCylindricalStruts.m][here]].
-
-*** Function description
-#+begin_src matlab
- function [stewart] = initializeCylindricalStruts(stewart, args)
- % initializeCylindricalStruts - Define the mass and moment of inertia of cylindrical struts
- %
- % Syntax: [stewart] = initializeCylindricalStruts(args)
- %
- % Inputs:
- % - args - Structure with the following fields:
- % - Fsm [1x1] - Mass of the Fixed part of the struts [kg]
- % - Fsh [1x1] - Height of cylinder for the Fixed part of the struts [m]
- % - Fsr [1x1] - Radius of cylinder for the Fixed part of the struts [m]
- % - Msm [1x1] - Mass of the Mobile part of the struts [kg]
- % - Msh [1x1] - Height of cylinder for the Mobile part of the struts [m]
- % - Msr [1x1] - Radius of cylinder for the Mobile part of the struts [m]
- %
- % Outputs:
- % - stewart - updated Stewart structure with the added fields:
- % - struts [struct] - structure with the following fields:
- % - Fsm [6x1] - Mass of the Fixed part of the struts [kg]
- % - Fsi [3x3x6] - Moment of Inertia for the Fixed part of the struts [kg*m^2]
- % - Msm [6x1] - Mass of the Mobile part of the struts [kg]
- % - Msi [3x3x6] - Moment of Inertia for the Mobile part of the struts [kg*m^2]
- % - Fsh [6x1] - Height of cylinder for the Fixed part of the struts [m]
- % - Fsr [6x1] - Radius of cylinder for the Fixed part of the struts [m]
- % - Msh [6x1] - Height of cylinder for the Mobile part of the struts [m]
- % - Msr [6x1] - Radius of cylinder for the Mobile part of the struts [m]
-#+end_src
-
-*** Optional Parameters
-#+begin_src matlab
- arguments
- stewart
- args.Fsm (1,1) double {mustBeNumeric, mustBePositive} = 0.1
- args.Fsh (1,1) double {mustBeNumeric, mustBePositive} = 50e-3
- args.Fsr (1,1) double {mustBeNumeric, mustBePositive} = 5e-3
- args.Msm (1,1) double {mustBeNumeric, mustBePositive} = 0.1
- args.Msh (1,1) double {mustBeNumeric, mustBePositive} = 50e-3
- args.Msr (1,1) double {mustBeNumeric, mustBePositive} = 5e-3
- end
-#+end_src
-
-*** Create the =struts= structure
-#+begin_src matlab
- struts = struct();
-
- struts.Fsm = ones(6,1).*args.Fsm;
- struts.Msm = ones(6,1).*args.Msm;
-
- struts.Fsh = ones(6,1).*args.Fsh;
- struts.Fsr = ones(6,1).*args.Fsr;
- struts.Msh = ones(6,1).*args.Msh;
- struts.Msr = ones(6,1).*args.Msr;
-
- struts.Fsi = zeros(3, 3, 6);
- struts.Msi = zeros(3, 3, 6);
- for i = 1:6
- struts.Fsi(:,:,i) = diag([1/12 * struts.Fsm(i) * (3*struts.Fsr(i)^2 + struts.Fsh(i)^2), ...
- 1/12 * struts.Fsm(i) * (3*struts.Fsr(i)^2 + struts.Fsh(i)^2), ...
- 1/2 * struts.Fsm(i) * struts.Fsr(i)^2]);
- struts.Msi(:,:,i) = diag([1/12 * struts.Msm(i) * (3*struts.Msr(i)^2 + struts.Msh(i)^2), ...
- 1/12 * struts.Msm(i) * (3*struts.Msr(i)^2 + struts.Msh(i)^2), ...
- 1/2 * struts.Msm(i) * struts.Msr(i)^2]);
- end
-#+end_src
-
-#+begin_src matlab
- stewart.struts = struts;
-#+end_src
-
-* =initializeStewartPose=: Determine the initial stroke in each leg to have the wanted pose
-:PROPERTIES:
-:header-args:matlab+: :tangle src/initializeStewartPose.m
-:header-args:matlab+: :comments none :mkdirp yes :eval no
-:END:
-<>
-
-This Matlab function is accessible [[file:src/initializeStewartPose.m][here]].
-
-** Function description
-#+begin_src matlab
- function [stewart] = initializeStewartPose(stewart, args)
- % initializeStewartPose - Determine the initial stroke in each leg to have the wanted pose
- % It uses the inverse kinematic
- %
- % Syntax: [stewart] = initializeStewartPose(stewart, args)
- %
- % Inputs:
- % - stewart - A structure with the following fields
- % - Aa [3x6] - The positions ai expressed in {A}
- % - Bb [3x6] - The positions bi expressed in {B}
- % - args - Can have the following fields:
- % - AP [3x1] - The wanted position of {B} with respect to {A}
- % - ARB [3x3] - The rotation matrix that gives the wanted orientation of {B} with respect to {A}
- %
- % Outputs:
- % - stewart - updated Stewart structure with the added fields:
- % - dLi[6x1] - The 6 needed displacement of the struts from the initial position in [m] to have the wanted pose of {B} w.r.t. {A}
-#+end_src
-
-** Optional Parameters
-#+begin_src matlab
- arguments
- stewart
- args.AP (3,1) double {mustBeNumeric} = zeros(3,1)
- args.ARB (3,3) double {mustBeNumeric} = eye(3)
- end
-#+end_src
-
-** Use the Inverse Kinematic function
-#+begin_src matlab
- [Li, dLi] = inverseKinematics(stewart, 'AP', args.AP, 'ARB', args.ARB);
-
- stewart.dLi = dLi;
-#+end_src
-
-* Utility Functions
-** =inverseKinematics=: Compute Inverse Kinematics
-:PROPERTIES:
-:header-args:matlab+: :tangle src/inverseKinematics.m
-:header-args:matlab+: :comments none :mkdirp yes :eval no
-:END:
-<>
-
-This Matlab function is accessible [[file:src/inverseKinematics.m][here]].
-
-*** Function description
-#+begin_src matlab
- function [Li, dLi] = inverseKinematics(stewart, args)
- % inverseKinematics - Compute the needed length of each strut to have the wanted position and orientation of {B} with respect to {A}
- %
- % Syntax: [stewart] = inverseKinematics(stewart)
- %
- % Inputs:
- % - stewart - A structure with the following fields
- % - Aa [3x6] - The positions ai expressed in {A}
- % - Bb [3x6] - The positions bi expressed in {B}
- % - args - Can have the following fields:
- % - AP [3x1] - The wanted position of {B} with respect to {A}
- % - ARB [3x3] - The rotation matrix that gives the wanted orientation of {B} with respect to {A}
- %
- % Outputs:
- % - Li [6x1] - The 6 needed length of the struts in [m] to have the wanted pose of {B} w.r.t. {A}
- % - dLi [6x1] - The 6 needed displacement of the struts from the initial position in [m] to have the wanted pose of {B} w.r.t. {A}
-#+end_src
-
-*** Optional Parameters
-#+begin_src matlab
- arguments
- stewart
- args.AP (3,1) double {mustBeNumeric} = zeros(3,1)
- args.ARB (3,3) double {mustBeNumeric} = eye(3)
- end
-#+end_src
-
-*** Theory
-For inverse kinematic analysis, it is assumed that the position ${}^A\bm{P}$ and orientation of the moving platform ${}^A\bm{R}_B$ are given and the problem is to obtain the joint variables, namely, $\bm{L} = [l_1, l_2, \dots, l_6]^T$.
-
-From the geometry of the manipulator, the loop closure for each limb, $i = 1, 2, \dots, 6$ can be written as
-\begin{align*}
- l_i {}^A\hat{\bm{s}}_i &= {}^A\bm{A} + {}^A\bm{b}_i - {}^A\bm{a}_i \\
- &= {}^A\bm{A} + {}^A\bm{R}_b {}^B\bm{b}_i - {}^A\bm{a}_i
-\end{align*}
-
-To obtain the length of each actuator and eliminate $\hat{\bm{s}}_i$, it is sufficient to dot multiply each side by itself:
-\begin{equation}
- l_i^2 \left[ {}^A\hat{\bm{s}}_i^T {}^A\hat{\bm{s}}_i \right] = \left[ {}^A\bm{P} + {}^A\bm{R}_B {}^B\bm{b}_i - {}^A\bm{a}_i \right]^T \left[ {}^A\bm{P} + {}^A\bm{R}_B {}^B\bm{b}_i - {}^A\bm{a}_i \right]
-\end{equation}
-
-Hence, for $i = 1, 2, \dots, 6$, each limb length can be uniquely determined by:
-\begin{equation}
- l_i = \sqrt{{}^A\bm{P}^T {}^A\bm{P} + {}^B\bm{b}_i^T {}^B\bm{b}_i + {}^A\bm{a}_i^T {}^A\bm{a}_i - 2 {}^A\bm{P}^T {}^A\bm{a}_i + 2 {}^A\bm{P}^T \left[{}^A\bm{R}_B {}^B\bm{b}_i\right] - 2 \left[{}^A\bm{R}_B {}^B\bm{b}_i\right]^T {}^A\bm{a}_i}
-\end{equation}
-
-If the position and orientation of the moving platform lie in the feasible workspace of the manipulator, one unique solution to the limb length is determined by the above equation.
-Otherwise, when the limbs' lengths derived yield complex numbers, then the position or orientation of the moving platform is not reachable.
-
-*** Compute
-#+begin_src matlab
- Li = sqrt(args.AP'*args.AP + diag(stewart.Bb'*stewart.Bb) + diag(stewart.Aa'*stewart.Aa) - (2*args.AP'*stewart.Aa)' + (2*args.AP'*(args.ARB*stewart.Bb))' - diag(2*(args.ARB*stewart.Bb)'*stewart.Aa));
-#+end_src
-
-#+begin_src matlab
- dLi = Li-stewart.l;
-#+end_src
-
-** =forwardKinematicsApprox=: Compute the Forward Kinematics
-:PROPERTIES:
-:header-args:matlab+: :tangle src/forwardKinematicsApprox.m
-:header-args:matlab+: :comments none :mkdirp yes :eval no
-:END:
-<>
-
-This Matlab function is accessible [[file:src/forwardKinematicsApprox.m][here]].
-
-*** Function description
-#+begin_src matlab
- function [P, R] = forwardKinematicsApprox(stewart, args)
- % forwardKinematicsApprox - Computed the approximate pose of {B} with respect to {A} from the length of each strut and using
- % the Jacobian Matrix
- %
- % Syntax: [P, R] = forwardKinematicsApprox(stewart, args)
- %
- % Inputs:
- % - stewart - A structure with the following fields
- % - J [6x6] - The Jacobian Matrix
- % - args - Can have the following fields:
- % - dL [6x1] - Displacement of each strut [m]
- %
- % Outputs:
- % - P [3x1] - The estimated position of {B} with respect to {A}
- % - R [3x3] - The estimated rotation matrix that gives the orientation of {B} with respect to {A}
-#+end_src
-
-*** Optional Parameters
-#+begin_src matlab
- arguments
- stewart
- args.dL (6,1) double {mustBeNumeric} = zeros(6,1)
- end
-#+end_src
-
-*** Computation
-From a small displacement of each strut $d\bm{\mathcal{L}}$, we can compute the
-position and orientation of {B} with respect to {A} using the following formula:
-\[ d \bm{\mathcal{X}} = \bm{J}^{-1} d\bm{\mathcal{L}} \]
-#+begin_src matlab
- X = stewart.J\args.dL;
-#+end_src
-
-The position vector corresponds to the first 3 elements.
-#+begin_src matlab
- P = X(1:3);
-#+end_src
-
-The next 3 elements are the orientation of {B} with respect to {A} expressed
-using the screw axis.
-#+begin_src matlab
- theta = norm(X(4:6));
- s = X(4:6)/theta;
-#+end_src
-
-We then compute the corresponding rotation matrix.
-#+begin_src matlab
- R = [s(1)^2*(1-cos(theta)) + cos(theta) , s(1)*s(2)*(1-cos(theta)) - s(3)*sin(theta), s(1)*s(3)*(1-cos(theta)) + s(2)*sin(theta);
- s(2)*s(1)*(1-cos(theta)) + s(3)*sin(theta), s(2)^2*(1-cos(theta)) + cos(theta), s(2)*s(3)*(1-cos(theta)) - s(1)*sin(theta);
- s(3)*s(1)*(1-cos(theta)) - s(2)*sin(theta), s(3)*s(2)*(1-cos(theta)) + s(1)*sin(theta), s(3)^2*(1-cos(theta)) + cos(theta)];
-#+end_src
-
-* Other Elements
-** Z-Axis Geophone
-:PROPERTIES:
-:header-args:matlab+: :tangle ./src/initializeZAxisGeophone.m
-:header-args:matlab+: :comments none :mkdirp yes :eval no
-:END:
-<>
-
-This Matlab function is accessible [[file:../src/initializeZAxisGeophone.m][here]].
-
-#+begin_src matlab
- function [geophone] = initializeZAxisGeophone(args)
- arguments
- args.mass (1,1) double {mustBeNumeric, mustBePositive} = 1e-3 % [kg]
- args.freq (1,1) double {mustBeNumeric, mustBePositive} = 1 % [Hz]
- end
-
- %%
- geophone.m = args.mass;
-
- %% The Stiffness is set to have the damping resonance frequency
- geophone.k = geophone.m * (2*pi*args.freq)^2;
-
- %% We set the damping value to have critical damping
- geophone.c = 2*sqrt(geophone.m * geophone.k);
-
- %% Save
- save('./mat/geophone_z_axis.mat', 'geophone');
- end
-#+end_src
-
-** Z-Axis Accelerometer
-:PROPERTIES:
-:header-args:matlab+: :tangle ./src/initializeZAxisAccelerometer.m
-:header-args:matlab+: :comments none :mkdirp yes :eval no
-:END:
-<>
-
-This Matlab function is accessible [[file:../src/initializeZAxisAccelerometer.m][here]].
-
-#+begin_src matlab
- function [accelerometer] = initializeZAxisAccelerometer(args)
- arguments
- args.mass (1,1) double {mustBeNumeric, mustBePositive} = 1e-3 % [kg]
- args.freq (1,1) double {mustBeNumeric, mustBePositive} = 5e3 % [Hz]
- end
-
- %%
- accelerometer.m = args.mass;
-
- %% The Stiffness is set to have the damping resonance frequency
- accelerometer.k = accelerometer.m * (2*pi*args.freq)^2;
-
- %% We set the damping value to have critical damping
- accelerometer.c = 2*sqrt(accelerometer.m * accelerometer.k);
-
- %% Gain correction of the accelerometer to have a unity gain until the resonance
- accelerometer.gain = -accelerometer.k/accelerometer.m;
-
- %% Save
- save('./mat/accelerometer_z_axis.mat', 'accelerometer');
- end
-#+end_src
-
-* OLD :noexport:
-** Define the Height of the Platform :noexport:
-#+begin_src matlab
- %% 1. Height of the platform. Location of {F} and {M}
- H = 90e-3; % [m]
- FO_M = [0; 0; H];
-#+end_src
-
-** Define the location of {A} and {B} :noexport:
-#+begin_src matlab
- %% 2. Location of {A} and {B}
- FO_A = [0; 0; 100e-3] + FO_M;% [m,m,m]
- MO_B = [0; 0; 100e-3];% [m,m,m]
-#+end_src
-
-** Define the position of $a_{i}$ and $b_{i}$ :noexport:
-#+begin_src matlab
- %% 3. Position of ai and bi
- Fa = zeros(3, 6); % Fa_i is the i'th vector of Fa
- Mb = zeros(3, 6); % Mb_i is the i'th vector of Mb
-#+end_src
-
-#+begin_src matlab
- Aa = Fa - repmat(FO_A, [1, 6]);
- Bb = Mb - repmat(MO_B, [1, 6]);
-
- Ab = Bb - repmat(-MO_B-FO_M+FO_A, [1, 6]);
- Ba = Aa - repmat( MO_B+FO_M-FO_A, [1, 6]);
-
- As = (Ab - Aa)./vecnorm(Ab - Aa); % As_i is the i'th vector of As
- l = vecnorm(Ab - Aa);
-
- Bs = (Bb - Ba)./vecnorm(Bb - Ba);
-
- FRa = zeros(3,3,6);
- MRb = zeros(3,3,6);
-
- for i = 1:6
- FRa(:,:,i) = [cross([0;1;0],As(:,i)) , cross(As(:,i), cross([0;1;0], As(:,i))) , As(:,i)];
- FRa(:,:,i) = FRa(:,:,i)./vecnorm(FRa(:,:,i));
-
- MRb(:,:,i) = [cross([0;1;0],Bs(:,i)) , cross(Bs(:,i), cross([0;1;0], Bs(:,i))) , Bs(:,i)];
- MRb(:,:,i) = MRb(:,:,i)./vecnorm(MRb(:,:,i));
- end
-#+end_src
-
-** Define the dynamical properties of each strut :noexport:
-#+begin_src matlab
- %% 4. Stiffness and Damping of each strut
- Ki = 1e6*ones(6,1);
- Ci = 1e2*ones(6,1);
-#+end_src
-
-** Old Introduction :noexport:
-First, geometrical parameters are defined:
-- ${}^A\bm{a}_i$ - Position of the joints fixed to the fixed base w.r.t $\{A\}$
-- ${}^A\bm{b}_i$ - Position of the joints fixed to the mobile platform w.r.t $\{A\}$
-- ${}^B\bm{b}_i$ - Position of the joints fixed to the mobile platform w.r.t $\{B\}$
-- $H$ - Total height of the mobile platform
-
-These parameter are enough to determine all the kinematic properties of the platform like the Jacobian, stroke, stiffness, ...
-These geometrical parameters can be generated using different functions: =initializeCubicConfiguration= for cubic configuration or =initializeGeneralConfiguration= for more general configuration.
-
-A function =computeGeometricalProperties= is then used to compute:
-- $\bm{J}_f$ - Jacobian matrix for the force location
-- $\bm{J}_d$ - Jacobian matrix for displacement estimation
-- $\bm{R}_m$ - Rotation matrices to position the leg vectors
-
-Then, geometrical parameters are computed for all the mechanical elements with the function =initializeMechanicalElements=:
-- Shape of the platforms
- - External Radius
- - Internal Radius
- - Density
- - Thickness
-- Shape of the Legs
- - Radius
- - Size of ball joint
- - Density
-
-Other Parameters are defined for the Simscape simulation:
-- Sample mass, volume and position (=initializeSample= function)
-- Location of the inertial sensor
-- Location of the point for the differential measurements
-- Location of the Jacobian point for velocity/displacement computation
-
-** Cubic Configuration :noexport:
-To define the cubic configuration, we need to define 4 parameters:
-- The size of the cube
-- The location of the cube
-- The position of the plane joint the points $a_{i}$
-- The position of the plane joint the points $b_{i}$
-
-To do so, we specify the following parameters:
-- $H_{C}$ the height of the useful part of the cube
-- ${}^{F}O_{C}$ the position of the center of the cube with respect to $\{F\}$
-- ${}^{F}H_{A}$: the height of the plane joining the points $a_{i}$ with respect to the frame $\{F\}$
-- ${}^{M}H_{B}$: the height of the plane joining the points $b_{i}$ with respect to the frame $\{M\}$
-
-We define the parameters
-#+begin_src matlab
- Hc = 60e-3; % [m]
- FOc = 50e-3; % [m]
- FHa = 15e-3; % [m]
- MHb = 15e-3; % [m]
-#+end_src
-
-We define the useful points of the cube with respect to the Cube's center.
-${}^{C}C$ are the 6 vertices of the cubes expressed in a frame {C} which is located at the center of the cube and aligned with {F} and {M}.
-#+begin_src matlab
- sx = [ 2; -1; -1];
- sy = [ 0; 1; -1];
- sz = [ 1; 1; 1];
-
- R = [sx, sy, sz]./vecnorm([sx, sy, sz]);
-
- L = Hc*sqrt(3);
-
- Cc = R'*[[0;0;L],[L;0;L],[L;0;0],[L;L;0],[0;L;0],[0;L;L]] - [0;0;1.5*Hc];
-
- CCf = [Cc(:,1), Cc(:,3), Cc(:,3), Cc(:,5), Cc(:,5), Cc(:,1)]; % CCf(:,i) corresponds to the bottom cube's vertice corresponding to the i'th leg
- CCm = [Cc(:,2), Cc(:,2), Cc(:,4), Cc(:,4), Cc(:,6), Cc(:,6)]; % CCm(:,i) corresponds to the top cube's vertice corresponding to the i'th leg
-#+end_src
-
-We can compute the vector of each leg ${}^{C}\hat{\bm{s}}_{i}$ (unit vector from ${}^{C}C_{f}$ to ${}^{C}C_{m}$).
-#+begin_src matlab
- CSi = (CCm - CCf)./vecnorm(CCm - CCf);
-#+end_src
-
-We now which to compute the position of the joints $a_{i}$ and $b_{i}$.
-#+begin_src matlab
- Fa = zeros(3, 6); % Fa_i is the i'th vector of Fa
- Mb = zeros(3, 6); % Mb_i is the i'th vector of Mb
-#+end_src
-
-#+begin_src matlab
- Fa = CCf + [0; 0; FOc] + ((FHa-(FOc-Hc/2))./CSi(3,:)).*CSi;
- Mb = CCf + [0; 0; FOc-H] + ((H-MHb-(FOc-Hc/2))./CSi(3,:)).*CSi; % TODO
-#+end_src
-
-** initializeGeneralConfiguration :noexport:
-:PROPERTIES:
-:HEADER-ARGS:matlab+: :exports code
-:HEADER-ARGS:matlab+: :comments no
-:HEADER-ARGS:matlab+: :eval no
-:HEADER-ARGS:matlab+: :tangle src/initializeGeneralConfiguration.m
-:END:
-
-*** Function description
-The =initializeGeneralConfiguration= function takes one structure that contains configurations for the hexapod and returns one structure representing the Hexapod.
-
-#+begin_src matlab
- function [stewart] = initializeGeneralConfiguration(opts_param)
-#+end_src
-
-*** Optional Parameters
-Default values for opts.
-#+begin_src matlab
- opts = struct(...
- 'H_tot', 90, ... % Height of the platform [mm]
- 'H_joint', 15, ... % Height of the joints [mm]
- 'H_plate', 10, ... % Thickness of the fixed and mobile platforms [mm]
- 'R_bot', 100, ... % Radius where the legs articulations are positionned [mm]
- 'R_top', 80, ... % Radius where the legs articulations are positionned [mm]
- 'a_bot', 10, ... % Angle Offset [deg]
- 'a_top', 40, ... % Angle Offset [deg]
- 'da_top', 0 ... % Angle Offset from 0 position [deg]
- );
-#+end_src
-
-Populate opts with input parameters
-#+begin_src matlab
- if exist('opts_param','var')
- for opt = fieldnames(opts_param)'
- opts.(opt{1}) = opts_param.(opt{1});
- end
- end
-#+end_src
-
-*** Geometry Description
-#+name: fig:stewart_bottom_plate
-#+caption: Schematic of the bottom plates with all the parameters
-[[file:./figs/stewart_bottom_plate.png]]
-
-*** Compute Aa and Ab
-We compute $[a_1, a_2, a_3, a_4, a_5, a_6]^T$ and $[b_1, b_2, b_3, b_4, b_5, b_6]^T$.
-
-#+begin_src matlab
- Aa = zeros(6, 3); % [mm]
- Ab = zeros(6, 3); % [mm]
- Bb = zeros(6, 3); % [mm]
-#+end_src
-
-#+begin_src matlab
- for i = 1:3
- Aa(2*i-1,:) = [opts.R_bot*cos( pi/180*(120*(i-1) - opts.a_bot) ), ...
- opts.R_bot*sin( pi/180*(120*(i-1) - opts.a_bot) ), ...
- opts.H_plate+opts.H_joint];
- Aa(2*i,:) = [opts.R_bot*cos( pi/180*(120*(i-1) + opts.a_bot) ), ...
- opts.R_bot*sin( pi/180*(120*(i-1) + opts.a_bot) ), ...
- opts.H_plate+opts.H_joint];
-
- Ab(2*i-1,:) = [opts.R_top*cos( pi/180*(120*(i-1) + opts.da_top - opts.a_top) ), ...
- opts.R_top*sin( pi/180*(120*(i-1) + opts.da_top - opts.a_top) ), ...
- opts.H_tot - opts.H_plate - opts.H_joint];
- Ab(2*i,:) = [opts.R_top*cos( pi/180*(120*(i-1) + opts.da_top + opts.a_top) ), ...
- opts.R_top*sin( pi/180*(120*(i-1) + opts.da_top + opts.a_top) ), ...
- opts.H_tot - opts.H_plate - opts.H_joint];
- end
-
- Bb = Ab - opts.H_tot*[0,0,1];
-#+end_src
-
-*** Returns Stewart Structure
-#+begin_src matlab :results none
- stewart = struct();
- stewart.Aa = Aa;
- stewart.Ab = Ab;
- stewart.Bb = Bb;
- stewart.H_tot = opts.H_tot;
-end
-#+end_src
-
-** initializeCubicConfiguration :noexport:
-:PROPERTIES:
-:HEADER-ARGS:matlab+: :exports code
-:HEADER-ARGS:matlab+: :comments no
-:HEADER-ARGS:matlab+: :eval no
-:HEADER-ARGS:matlab+: :tangle src/initializeCubicConfiguration.m
-:END:
-<>
-
-*** Function description
-#+begin_src matlab
- function [stewart] = initializeCubicConfiguration(opts_param)
-#+end_src
-
-*** Optional Parameters
-Default values for opts.
-#+begin_src matlab
- opts = struct(...
- 'H_tot', 90, ... % Total height of the Hexapod [mm]
- 'L', 110, ... % Size of the Cube [mm]
- 'H', 40, ... % Height between base joints and platform joints [mm]
- 'H0', 75 ... % Height between the corner of the cube and the plane containing the base joints [mm]
- );
-#+end_src
-
-Populate opts with input parameters
-#+begin_src matlab
- if exist('opts_param','var')
- for opt = fieldnames(opts_param)'
- opts.(opt{1}) = opts_param.(opt{1});
- end
- end
-#+end_src
-
-*** Cube Creation
-#+begin_src matlab :results none
- points = [0, 0, 0; ...
- 0, 0, 1; ...
- 0, 1, 0; ...
- 0, 1, 1; ...
- 1, 0, 0; ...
- 1, 0, 1; ...
- 1, 1, 0; ...
- 1, 1, 1];
- points = opts.L*points;
-#+end_src
-
-We create the rotation matrix to rotate the cube
-#+begin_src matlab :results none
- sx = cross([1, 1, 1], [1 0 0]);
- sx = sx/norm(sx);
-
- sy = -cross(sx, [1, 1, 1]);
- sy = sy/norm(sy);
-
- sz = [1, 1, 1];
- sz = sz/norm(sz);
-
- R = [sx', sy', sz']';
-#+end_src
-
-We use to rotation matrix to rotate the cube
-#+begin_src matlab :results none
- cube = zeros(size(points));
- for i = 1:size(points, 1)
- cube(i, :) = R * points(i, :)';
- end
-#+end_src
-
-*** Vectors of each leg
-#+begin_src matlab :results none
- leg_indices = [3, 4; ...
- 2, 4; ...
- 2, 6; ...
- 5, 6; ...
- 5, 7; ...
- 3, 7];
-#+end_src
-
-Vectors are:
-#+begin_src matlab :results none
- legs = zeros(6, 3);
- legs_start = zeros(6, 3);
-
- for i = 1:6
- legs(i, :) = cube(leg_indices(i, 2), :) - cube(leg_indices(i, 1), :);
- legs_start(i, :) = cube(leg_indices(i, 1), :);
- end
-#+end_src
-
-*** Verification of Height of the Stewart Platform
-If the Stewart platform is not contained in the cube, throw an error.
-
-#+begin_src matlab :results none
- Hmax = cube(4, 3) - cube(2, 3);
- if opts.H0 < cube(2, 3)
- error(sprintf('H0 is not high enought. Minimum H0 = %.1f', cube(2, 3)));
- else if opts.H0 + opts.H > cube(4, 3)
- error(sprintf('H0+H is too high. Maximum H0+H = %.1f', cube(4, 3)));
- error('H0+H is too high');
- end
-#+end_src
-
-*** Determinate the location of the joints
-We now determine the location of the joints on the fixed platform w.r.t the fixed frame $\{A\}$.
-$\{A\}$ is fixed to the bottom of the base.
-#+begin_src matlab :results none
- Aa = zeros(6, 3);
- for i = 1:6
- t = (opts.H0-legs_start(i, 3))/(legs(i, 3));
- Aa(i, :) = legs_start(i, :) + t*legs(i, :);
- end
-#+end_src
-
-And the location of the joints on the mobile platform with respect to $\{A\}$.
-#+begin_src matlab :results none
- Ab = zeros(6, 3);
- for i = 1:6
- t = (opts.H0+opts.H-legs_start(i, 3))/(legs(i, 3));
- Ab(i, :) = legs_start(i, :) + t*legs(i, :);
- end
-#+end_src
-
-And the location of the joints on the mobile platform with respect to $\{B\}$.
-#+begin_src matlab :results none
- Bb = zeros(6, 3);
- Bb = Ab - (opts.H0 + opts.H_tot/2 + opts.H/2)*[0, 0, 1];
-#+end_src
-
-#+begin_src matlab :results none
- h = opts.H0 + opts.H/2 - opts.H_tot/2;
- Aa = Aa - h*[0, 0, 1];
- Ab = Ab - h*[0, 0, 1];
-#+end_src
-
-*** Returns Stewart Structure
-#+begin_src matlab :results none
- stewart = struct();
- stewart.Aa = Aa;
- stewart.Ab = Ab;
- stewart.Bb = Bb;
- stewart.H_tot = opts.H_tot;
-end
-#+end_src
-
-** computeGeometricalProperties :noexport:
-:PROPERTIES:
-:HEADER-ARGS:matlab+: :exports code
-:HEADER-ARGS:matlab+: :comments no
-:HEADER-ARGS:matlab+: :eval no
-:HEADER-ARGS:matlab+: :tangle src/computeGeometricalProperties.m
-:END:
-
-*** Function description
-#+begin_src matlab
- function [stewart] = computeGeometricalProperties(stewart, opts_param)
-#+end_src
-
-*** Optional Parameters
-Default values for opts.
-#+begin_src matlab
- opts = struct(...
- 'Jd_pos', [0, 0, 30], ... % Position of the Jacobian for displacement estimation from the top of the mobile platform [mm]
- 'Jf_pos', [0, 0, 30] ... % Position of the Jacobian for force location from the top of the mobile platform [mm]
- );
-#+end_src
-
-Populate opts with input parameters
-#+begin_src matlab
- if exist('opts_param','var')
- for opt = fieldnames(opts_param)'
- opts.(opt{1}) = opts_param.(opt{1});
- end
- end
-#+end_src
-
-*** Rotation matrices
-We initialize $l_i$ and $\hat{s}_i$
-#+begin_src matlab
- leg_length = zeros(6, 1); % [mm]
- leg_vectors = zeros(6, 3);
-#+end_src
-
-We compute $b_i - a_i$, and then:
-\begin{align*}
- l_i &= \left|b_i - a_i\right| \\
- \hat{s}_i &= \frac{b_i - a_i}{l_i}
-\end{align*}
-
-#+begin_src matlab
- legs = stewart.Ab - stewart.Aa;
-
- for i = 1:6
- leg_length(i) = norm(legs(i,:));
- leg_vectors(i,:) = legs(i,:) / leg_length(i);
- end
-#+end_src
-
-We compute rotation matrices to have the orientation of the legs.
-The rotation matrix transforms the $z$ axis to the axis of the leg. The other axis are not important here.
-#+begin_src matlab
- stewart.Rm = struct('R', eye(3));
-
- for i = 1:6
- sx = cross(leg_vectors(i,:), [1 0 0]);
- sx = sx/norm(sx);
-
- sy = -cross(sx, leg_vectors(i,:));
- sy = sy/norm(sy);
-
- sz = leg_vectors(i,:);
- sz = sz/norm(sz);
-
- stewart.Rm(i).R = [sx', sy', sz'];
- end
-#+end_src
-
-*** Jacobian matrices
-Compute Jacobian Matrix
-#+begin_src matlab
- Jd = zeros(6);
-
- for i = 1:6
- Jd(i, 1:3) = leg_vectors(i, :);
- Jd(i, 4:6) = cross(0.001*(stewart.Bb(i, :) - opts.Jd_pos), leg_vectors(i, :));
- end
-
- stewart.Jd = Jd;
- stewart.Jd_inv = inv(Jd);
-#+end_src
-
-#+begin_src matlab
- Jf = zeros(6);
-
- for i = 1:6
- Jf(i, 1:3) = leg_vectors(i, :);
- Jf(i, 4:6) = cross(0.001*(stewart.Bb(i, :) - opts.Jf_pos), leg_vectors(i, :));
- end
-
- stewart.Jf = Jf;
- stewart.Jf_inv = inv(Jf);
-#+end_src
-
-#+begin_src matlab
- end
-#+end_src
-
-** initializeMechanicalElements :noexport:
-:PROPERTIES:
-:HEADER-ARGS:matlab+: :exports code
-:HEADER-ARGS:matlab+: :comments no
-:HEADER-ARGS:matlab+: :eval no
-:HEADER-ARGS:matlab+: :tangle src/initializeMechanicalElements.m
-:END:
-
-*** Function description
-#+begin_src matlab
- function [stewart] = initializeMechanicalElements(stewart, opts_param)
-#+end_src
-
-*** Optional Parameters
-Default values for opts.
-#+begin_src matlab
- opts = struct(...
- 'thickness', 10, ... % Thickness of the base and platform [mm]
- 'density', 1000, ... % Density of the material used for the hexapod [kg/m3]
- 'k_ax', 1e8, ... % Stiffness of each actuator [N/m]
- 'c_ax', 1000, ... % Damping of each actuator [N/(m/s)]
- 'stroke', 50e-6 ... % Maximum stroke of each actuator [m]
- );
-#+end_src
-
-Populate opts with input parameters
-#+begin_src matlab
- if exist('opts_param','var')
- for opt = fieldnames(opts_param)'
- opts.(opt{1}) = opts_param.(opt{1});
- end
- end
-#+end_src
-
-*** Bottom Plate
-#+name: fig:stewart_bottom_plate
-#+caption: Schematic of the bottom plates with all the parameters
-[[file:./figs/stewart_bottom_plate.png]]
-
-The bottom plate structure is initialized.
-#+begin_src matlab
- BP = struct();
-#+end_src
-
-We defined its internal radius (if there is a hole in the bottom plate) and its outer radius.
-#+begin_src matlab
- BP.Rint = 0; % Internal Radius [mm]
- BP.Rext = 150; % External Radius [mm]
-#+end_src
-
-We define its thickness.
-#+begin_src matlab
- BP.H = opts.thickness; % Thickness of the Bottom Plate [mm]
-#+end_src
-
-We defined the density of the material of the bottom plate.
-#+begin_src matlab
- BP.density = opts.density; % Density of the material [kg/m3]
-#+end_src
-
-And its color.
-#+begin_src matlab
- BP.color = [0.7 0.7 0.7]; % Color [RGB]
-#+end_src
-
-Then the profile of the bottom plate is computed and will be used by Simscape
-#+begin_src matlab
- BP.shape = [BP.Rint BP.H; BP.Rint 0; BP.Rext 0; BP.Rext BP.H]; % [mm]
-#+end_src
-
-The structure is added to the stewart structure
-#+begin_src matlab
- stewart.BP = BP;
-#+end_src
-
-*** Top Plate
-The top plate structure is initialized.
-#+begin_src matlab
- TP = struct();
-#+end_src
-
-We defined the internal and external radius of the top plate.
-#+begin_src matlab
- TP.Rint = 0; % [mm]
- TP.Rext = 100; % [mm]
-#+end_src
-
-The thickness of the top plate.
-#+begin_src matlab
- TP.H = 10; % [mm]
-#+end_src
-
-The density of its material.
-#+begin_src matlab
- TP.density = opts.density; % Density of the material [kg/m3]
-#+end_src
-
-Its color.
-#+begin_src matlab
- TP.color = [0.7 0.7 0.7]; % Color [RGB]
-#+end_src
-
-Then the shape of the top plate is computed
-#+begin_src matlab
- TP.shape = [TP.Rint TP.H; TP.Rint 0; TP.Rext 0; TP.Rext TP.H];
-#+end_src
-
-The structure is added to the stewart structure
-#+begin_src matlab
- stewart.TP = TP;
-#+end_src
-
-*** Legs
-#+name: fig:stewart_legs
-#+caption: Schematic for the legs of the Stewart platform
-[[file:./figs/stewart_legs.png]]
-
-The leg structure is initialized.
-#+begin_src matlab
- Leg = struct();
-#+end_src
-
-The maximum Stroke of each leg is defined.
-#+begin_src matlab
- Leg.stroke = opts.stroke; % [m]
-#+end_src
-
-The stiffness and damping of each leg are defined
-#+begin_src matlab
- Leg.k_ax = opts.k_ax; % Stiffness of each leg [N/m]
- Leg.c_ax = opts.c_ax; % Damping of each leg [N/(m/s)]
-#+end_src
-
-The radius of the legs are defined
-#+begin_src matlab
- Leg.Rtop = 10; % Radius of the cylinder of the top part of the leg[mm]
- Leg.Rbot = 12; % Radius of the cylinder of the bottom part of the leg [mm]
-#+end_src
-
-The density of its material.
-#+begin_src matlab
- Leg.density = opts.density; % Density of the material used for the legs [kg/m3]
-#+end_src
-
-Its color.
-#+begin_src matlab
- Leg.color = [0.5 0.5 0.5]; % Color of the top part of the leg [RGB]
-#+end_src
-
-The radius of spheres representing the ball joints are defined.
-#+begin_src matlab
- Leg.R = 1.3*Leg.Rbot; % Size of the sphere at the extremity of the leg [mm]
-#+end_src
-
-We estimate the length of the legs.
-#+begin_src matlab
- legs = stewart.Ab - stewart.Aa;
- Leg.lenght = norm(legs(1,:))/1.5;
-#+end_src
-
-Then the shape of the bottom leg is estimated
-#+begin_src matlab
- Leg.shape.bot = ...
- [0 0; ...
- Leg.Rbot 0; ...
- Leg.Rbot Leg.lenght; ...
- Leg.Rtop Leg.lenght; ...
- Leg.Rtop 0.2*Leg.lenght; ...
- 0 0.2*Leg.lenght];
-#+end_src
-
-The structure is added to the stewart structure
-#+begin_src matlab
- stewart.Leg = Leg;
-#+end_src
-
-*** Ball Joints
-#+name: fig:stewart_ball_joints
-#+caption: Schematic of the support for the ball joints
-[[file:./figs/stewart_ball_joints.png]]
-
-=SP= is the structure representing the support for the ball joints at the extremity of each leg.
-
-The =SP= structure is initialized.
-#+begin_src matlab
- SP = struct();
-#+end_src
-
-We can define its rotational stiffness and damping. For now, we use perfect joints.
-#+begin_src matlab
- SP.k = 0; % [N*m/deg]
- SP.c = 0; % [N*m/deg]
-#+end_src
-
-Its height is defined
-#+begin_src matlab
- SP.H = stewart.Aa(1, 3) - BP.H; % [mm]
-#+end_src
-
-Its radius is based on the radius on the sphere at the end of the legs.
-#+begin_src matlab
- SP.R = Leg.R; % [mm]
-#+end_src
-
-#+begin_src matlab
- SP.section = [0 SP.H-SP.R;
- 0 0;
- SP.R 0;
- SP.R SP.H];
-#+end_src
-
-The density of its material is defined.
-#+begin_src matlab
- SP.density = opts.density; % [kg/m^3]
-#+end_src
-
-Its color is defined.
-#+begin_src matlab
- SP.color = [0.7 0.7 0.7]; % [RGB]
-#+end_src
-
-The structure is added to the Hexapod structure
-#+begin_src matlab
- stewart.SP = SP;
-#+end_src
-
-** initializeSample :noexport:
-:PROPERTIES:
-:HEADER-ARGS:matlab+: :exports code
-:HEADER-ARGS:matlab+: :comments no
-:HEADER-ARGS:matlab+: :eval no
-:HEADER-ARGS:matlab+: :tangle src/initializeSample.m
-:END:
-
-*** Function description
-#+begin_src matlab
- function [] = initializeSample(opts_param)
-#+end_src
-
-*** Optional Parameters
-Default values for opts.
-#+begin_src matlab
- sample = struct( ...
- 'radius', 100, ... % radius of the cylinder [mm]
- 'height', 100, ... % height of the cylinder [mm]
- 'mass', 10, ... % mass of the cylinder [kg]
- 'measheight', 50, ... % measurement point z-offset [mm]
- 'offset', [0, 0, 0], ... % offset position of the sample [mm]
- 'color', [0.9 0.1 0.1] ...
- );
-#+end_src
-
-Populate opts with input parameters
-#+begin_src matlab
- if exist('opts_param','var')
- for opt = fieldnames(opts_param)'
- sample.(opt{1}) = opts_param.(opt{1});
- end
- end
-#+end_src
-
-*** Save the Sample structure
-#+begin_src matlab
- save('./mat/sample.mat', 'sample');
-#+end_src
-
-#+begin_src matlab
- end
-#+end_src
diff --git a/simscape_subsystems/stewart_strut_no_sensors.slx b/simscape_subsystems/stewart_strut_no_sensors.slx
index bddaa6f..2d9d91f 100644
Binary files a/simscape_subsystems/stewart_strut_no_sensors.slx and b/simscape_subsystems/stewart_strut_no_sensors.slx differ
diff --git a/simulink/stewart_platform_identification.slx b/simulink/stewart_platform_identification.slx
new file mode 100644
index 0000000..87bc8ff
Binary files /dev/null and b/simulink/stewart_platform_identification.slx differ
diff --git a/simulink/stewart_platform_identification_simple.slx b/simulink/stewart_platform_identification_simple.slx
new file mode 100644
index 0000000..f7cbad2
Binary files /dev/null and b/simulink/stewart_platform_identification_simple.slx differ
diff --git a/src/computeJointsPose.m b/src/computeJointsPose.m
index 26619bb..5b5754e 100644
--- a/src/computeJointsPose.m
+++ b/src/computeJointsPose.m
@@ -1,10 +1,12 @@
function [stewart] = computeJointsPose(stewart)
% computeJointsPose -
%
-% Syntax: [stewart] = computeJointsPose(stewart, opts_param)
+% Syntax: [stewart] = computeJointsPose(stewart)
%
% Inputs:
% - stewart - A structure with the following fields
+% - Fa [3x6] - Its i'th column is the position vector of joint ai with respect to {F}
+% - Mb [3x6] - Its i'th column is the position vector of joint bi with respect to {M}
% - FO_A [3x1] - Position of {A} with respect to {F}
% - MO_B [3x1] - Position of {B} with respect to {M}
% - FO_M [3x1] - Position of {M} with respect to {F}
diff --git a/src/forwardKinematics.m b/src/forwardKinematics.m
deleted file mode 100644
index 8814647..0000000
--- a/src/forwardKinematics.m
+++ /dev/null
@@ -1,30 +0,0 @@
-function [P, R] = forwardKinematics(stewart, args)
-% forwardKinematics - Computed the pose of {B} with respect to {A} from the length of each strut
-%
-% Syntax: [in_data] = forwardKinematics(stewart)
-%
-% Inputs:
-% - stewart - A structure with the following fields
-% - J [6x6] - The Jacobian Matrix
-% - args - Can have the following fields:
-% - L [6x1] - Length of each strut [m]
-%
-% Outputs:
-% - P [3x1] - The estimated position of {B} with respect to {A}
-% - R [3x3] - The estimated rotation matrix that gives the orientation of {B} with respect to {A}
-
-arguments
- stewart
- args.L (6,1) double {mustBeNumeric} = zeros(6,1)
-end
-
-X = stewart.J\args.L;
-
-P = X(1:3);
-
-theta = norm(X(4:6));
-s = X(4:6)/theta;
-
-R = [s(1)^2*(1-cos(theta)) + cos(theta) , s(1)*s(2)*(1-cos(theta)) - s(3)*sin(theta), s(1)*s(3)*(1-cos(theta)) + s(2)*sin(theta);
- s(2)*s(1)*(1-cos(theta)) + s(3)*sin(theta), s(2)^2*(1-cos(theta)) + cos(theta), s(2)*s(3)*(1-cos(theta)) - s(1)*sin(theta);
- s(3)*s(1)*(1-cos(theta)) - s(2)*sin(theta), s(3)*s(2)*(1-cos(theta)) + s(1)*sin(theta), s(3)^2*(1-cos(theta)) + cos(theta)];
diff --git a/src/generateGeneralConfiguration.m b/src/generateGeneralConfiguration.m
index 99f9afa..ce9de8b 100644
--- a/src/generateGeneralConfiguration.m
+++ b/src/generateGeneralConfiguration.m
@@ -4,8 +4,6 @@ function [stewart] = generateGeneralConfiguration(stewart, args)
% Syntax: [stewart] = generateGeneralConfiguration(stewart, args)
%
% Inputs:
-% - stewart - A structure with the following fields
-% - H [1x1] - Total height of the platform [m]
% - args - Can have the following fields:
% - FH [1x1] - Height of the position of the fixed joints with respect to the frame {F} [m]
% - FR [1x1] - Radius of the position of the fixed joints in the X-Y [m]
@@ -22,10 +20,10 @@ function [stewart] = generateGeneralConfiguration(stewart, args)
arguments
stewart
args.FH (1,1) double {mustBeNumeric, mustBePositive} = 15e-3
- args.FR (1,1) double {mustBeNumeric, mustBePositive} = 90e-3;
+ args.FR (1,1) double {mustBeNumeric, mustBePositive} = 115e-3;
args.FTh (6,1) double {mustBeNumeric} = [-10, 10, 120-10, 120+10, 240-10, 240+10]*(pi/180);
args.MH (1,1) double {mustBeNumeric, mustBePositive} = 15e-3
- args.MR (1,1) double {mustBeNumeric, mustBePositive} = 70e-3;
+ args.MR (1,1) double {mustBeNumeric, mustBePositive} = 90e-3;
args.MTh (6,1) double {mustBeNumeric} = [-60+10, 60-10, 60+10, 180-10, 180+10, -60-10]*(pi/180);
end
diff --git a/src/getMaxPositions.m b/src/getMaxPositions.m
deleted file mode 100644
index 5038912..0000000
--- a/src/getMaxPositions.m
+++ /dev/null
@@ -1,18 +0,0 @@
-function [X, Y, Z] = getMaxPositions(stewart)
- Leg = stewart.Leg;
- J = stewart.Jd;
- theta = linspace(0, 2*pi, 100);
- phi = linspace(-pi/2 , pi/2, 100);
- dmax = zeros(length(theta), length(phi));
-
- for i = 1:length(theta)
- for j = 1:length(phi)
- L = J*[cos(phi(j))*cos(theta(i)) cos(phi(j))*sin(theta(i)) sin(phi(j)) 0 0 0]';
- dmax(i, j) = Leg.stroke/max(abs(L));
- end
- end
-
- X = dmax.*cos(repmat(phi,length(theta),1)).*cos(repmat(theta,length(phi),1))';
- Y = dmax.*cos(repmat(phi,length(theta),1)).*sin(repmat(theta,length(phi),1))';
- Z = dmax.*sin(repmat(phi,length(theta),1));
-end
diff --git a/src/getMaxPureDisplacement.m b/src/getMaxPureDisplacement.m
deleted file mode 100644
index 8a14569..0000000
--- a/src/getMaxPureDisplacement.m
+++ /dev/null
@@ -1,9 +0,0 @@
-function [max_disp] = getMaxPureDisplacement(Leg, J)
- max_disp = zeros(6, 1);
- max_disp(1) = Leg.stroke/max(abs(J*[1 0 0 0 0 0]'));
- max_disp(2) = Leg.stroke/max(abs(J*[0 1 0 0 0 0]'));
- max_disp(3) = Leg.stroke/max(abs(J*[0 0 1 0 0 0]'));
- max_disp(4) = Leg.stroke/max(abs(J*[0 0 0 1 0 0]'));
- max_disp(5) = Leg.stroke/max(abs(J*[0 0 0 0 1 0]'));
- max_disp(6) = Leg.stroke/max(abs(J*[0 0 0 0 0 1]'));
-end
diff --git a/src/getStiffnessMatrix.m b/src/getStiffnessMatrix.m
deleted file mode 100644
index 8b282d5..0000000
--- a/src/getStiffnessMatrix.m
+++ /dev/null
@@ -1,5 +0,0 @@
-function [K] = getStiffnessMatrix(k, J)
-% k - leg stiffness
-% J - Jacobian matrix
- K = k*(J'*J);
-end
diff --git a/src/identifyPlant.m b/src/identifyPlant.m
deleted file mode 100644
index 868b2a8..0000000
--- a/src/identifyPlant.m
+++ /dev/null
@@ -1,67 +0,0 @@
-% [[file:~/MEGA/These/Matlab/Simscape/stewart-simscape/identification.org::*identifyPlant][identifyPlant:1]]
-function [sys] = identifyPlant(opts_param)
-% identifyPlant:1 ends here
-
-% [[file:~/MEGA/These/Matlab/Simscape/stewart-simscape/identification.org::*identifyPlant][identifyPlant:2]]
-%% Default values for opts
-opts = struct();
-
-%% Populate opts with input parameters
-if exist('opts_param','var')
- for opt = fieldnames(opts_param)'
- opts.(opt{1}) = opts_param.(opt{1});
- end
-end
-% identifyPlant:2 ends here
-
-% [[file:~/MEGA/These/Matlab/Simscape/stewart-simscape/identification.org::*identifyPlant][identifyPlant:3]]
-options = linearizeOptions;
-options.SampleTime = 0;
-% identifyPlant:3 ends here
-
-% [[file:~/MEGA/These/Matlab/Simscape/stewart-simscape/identification.org::*identifyPlant][identifyPlant:4]]
-mdl = 'stewart';
-% identifyPlant:4 ends here
-
-% [[file:~/MEGA/These/Matlab/Simscape/stewart-simscape/identification.org::*identifyPlant][identifyPlant:5]]
-%% Inputs
-io(1) = linio([mdl, '/F'], 1, 'input'); % Cartesian forces
-io(2) = linio([mdl, '/Fl'], 1, 'input'); % Leg forces
-io(3) = linio([mdl, '/Fd'], 1, 'input'); % Direct forces
-io(4) = linio([mdl, '/Dw'], 1, 'input'); % Base motion
-
-%% Outputs
-io(5) = linio([mdl, '/Dm'], 1, 'output'); % Relative Motion
-io(6) = linio([mdl, '/Dlm'], 1, 'output'); % Displacement of each leg
-io(7) = linio([mdl, '/Flm'], 1, 'output'); % Force sensor in each leg
-io(8) = linio([mdl, '/Xm'], 1, 'output'); % Absolute motion of platform
-% identifyPlant:5 ends here
-
-% [[file:~/MEGA/These/Matlab/Simscape/stewart-simscape/identification.org::*identifyPlant][identifyPlant:6]]
-G = linearize(mdl, io, 0);
-% identifyPlant:6 ends here
-
-% [[file:~/MEGA/These/Matlab/Simscape/stewart-simscape/identification.org::*identifyPlant][identifyPlant:7]]
-G.InputName = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz', ...
- 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', ...
- 'Fdx', 'Fdy', 'Fdz', 'Mdx', 'Mdy', 'Mdz', ...
- 'Dwx', 'Dwy', 'Dwz', 'Rwx', 'Rwy', 'Rwz'};
-G.OutputName = {'Dxm', 'Dym', 'Dzm', 'Rxm', 'Rym', 'Rzm', ...
- 'D1m', 'D2m', 'D3m', 'D4m', 'D5m', 'D6m', ...
- 'F1m', 'F2m', 'F3m', 'F4m', 'F5m', 'F6m', ...
- 'Dxtm', 'Dytm', 'Dztm', 'Rxtm', 'Rytm', 'Rztm'};
-% identifyPlant:7 ends here
-
-% [[file:~/MEGA/These/Matlab/Simscape/stewart-simscape/identification.org::*identifyPlant][identifyPlant:8]]
-sys.G_cart = G({'Dxm', 'Dym', 'Dzm', 'Rxm', 'Rym', 'Rzm'}, {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'});
-sys.G_forc = minreal(G({'F1m', 'F2m', 'F3m', 'F4m', 'F5m', 'F6m'}, {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'}));
-sys.G_legs = minreal(G({'D1m', 'D2m', 'D3m', 'D4m', 'D5m', 'D6m'}, {'F1', 'F2', 'F3', 'F4', 'F5', 'F6'}));
-sys.G_tran = minreal(G({'Dxtm', 'Dytm', 'Dztm', 'Rxtm', 'Rytm', 'Rztm'}, {'Dwx', 'Dwy', 'Dwz', 'Rwx', 'Rwy', 'Rwz'}));
-sys.G_comp = minreal(G({'Dxm', 'Dym', 'Dzm', 'Rxm', 'Rym', 'Rzm'}, {'Fdx', 'Fdy', 'Fdz', 'Mdx', 'Mdy', 'Mdz'}));
-sys.G_iner = minreal(G({'Dxtm', 'Dytm', 'Dztm', 'Rxtm', 'Rytm', 'Rztm'}, {'Fdx', 'Fdy', 'Fdz', 'Mdx', 'Mdy', 'Mdz'}));
-% sys.G_all = minreal(G);
-% identifyPlant:8 ends here
-
-% [[file:~/MEGA/These/Matlab/Simscape/stewart-simscape/identification.org::*identifyPlant][identifyPlant:9]]
-end
-% identifyPlant:9 ends here
diff --git a/src/initializeHexapod.m b/src/initializeHexapod.m
deleted file mode 100644
index d7517da..0000000
--- a/src/initializeHexapod.m
+++ /dev/null
@@ -1,171 +0,0 @@
-function [stewart] = initializeHexapod(opts_param)
-
-opts = struct(...
- 'height', 90, ... % Height of the platform [mm]
- 'density', 10, ... % Density of the material used for the hexapod [kg/m3]
- 'k_ax', 1e8, ... % Stiffness of each actuator [N/m]
- 'c_ax', 1000, ... % Damping of each actuator [N/(m/s)]
- 'stroke', 50e-6, ... % Maximum stroke of each actuator [m]
- 'name', 'stewart' ... % Name of the file
- );
-
-if exist('opts_param','var')
- for opt = fieldnames(opts_param)'
- opts.(opt{1}) = opts_param.(opt{1});
- end
-end
-
-stewart = struct();
-
-stewart.H = opts.height; % [mm]
-
-BP = struct();
-
-BP.Rint = 0; % Internal Radius [mm]
-BP.Rext = 150; % External Radius [mm]
-
-BP.H = 10; % Thickness of the Bottom Plate [mm]
-
-BP.Rleg = 100; % Radius where the legs articulations are positionned [mm]
-BP.alpha = 30; % Angle Offset [deg]
-
-BP.density = opts.density; % Density of the material [kg/m3]
-
-BP.color = [0.7 0.7 0.7]; % Color [RGB]
-
-BP.shape = [BP.Rint BP.H; BP.Rint 0; BP.Rext 0; BP.Rext BP.H]; % [mm]
-
-stewart.BP = BP;
-
-TP = struct();
-
-TP.Rint = 0; % [mm]
-TP.Rext = 100; % [mm]
-
-TP.H = 10; % [mm]
-
-TP.Rleg = 80; % Radius where the legs articulations are positionned [mm]
-TP.alpha = 10; % Angle [deg]
-TP.dalpha = 0; % Angle Offset from 0 position [deg]
-
-TP.density = opts.density; % Density of the material [kg/m3]
-
-TP.color = [0.7 0.7 0.7]; % Color [RGB]
-
-TP.shape = [TP.Rint TP.H; TP.Rint 0; TP.Rext 0; TP.Rext TP.H];
-
-stewart.TP = TP;
-
-Leg = struct();
-
-Leg.stroke = opts.stroke; % [m]
-
-Leg.k_ax = opts.k_ax; % Stiffness of each leg [N/m]
-Leg.c_ax = opts.c_ax; % Damping of each leg [N/(m/s)]
-
-Leg.Rtop = 10; % Radius of the cylinder of the top part of the leg[mm]
-Leg.Rbot = 12; % Radius of the cylinder of the bottom part of the leg [mm]
-
-Leg.density = 0.01*opts.density; % Density of the material used for the legs [kg/m3]
-
-Leg.color = [0.5 0.5 0.5]; % Color of the top part of the leg [RGB]
-
-Leg.R = 1.3*Leg.Rbot; % Size of the sphere at the extremity of the leg [mm]
-
-stewart.Leg = Leg;
-
-SP = struct();
-
-SP.k = 0; % [N*m/deg]
-SP.c = 0; % [N*m/deg]
-
-SP.H = 15; % [mm]
-
-SP.R = Leg.R; % [mm]
-
-SP.section = [0 SP.H-SP.R;
- 0 0;
- SP.R 0;
- SP.R SP.H];
-
-SP.density = opts.density; % [kg/m^3]
-
-SP.color = [0.7 0.7 0.7]; % [RGB]
-
-stewart.SP = SP;
-
-stewart = initializeParameters(stewart);
-
-save('./mat/stewart.mat', 'stewart')
-
-function [stewart] = initializeParameters(stewart)
-
-stewart.Aa = zeros(6, 3); % [mm]
-stewart.Ab = zeros(6, 3); % [mm]
-stewart.Bb = zeros(6, 3); % [mm]
-
-for i = 1:3
- stewart.Aa(2*i-1,:) = [stewart.BP.Rleg*cos( pi/180*(120*(i-1) - stewart.BP.alpha) ), ...
- stewart.BP.Rleg*sin( pi/180*(120*(i-1) - stewart.BP.alpha) ), ...
- stewart.BP.H+stewart.SP.H];
- stewart.Aa(2*i,:) = [stewart.BP.Rleg*cos( pi/180*(120*(i-1) + stewart.BP.alpha) ), ...
- stewart.BP.Rleg*sin( pi/180*(120*(i-1) + stewart.BP.alpha) ), ...
- stewart.BP.H+stewart.SP.H];
-
- stewart.Ab(2*i-1,:) = [stewart.TP.Rleg*cos( pi/180*(120*(i-1) + stewart.TP.dalpha - stewart.TP.alpha) ), ...
- stewart.TP.Rleg*sin( pi/180*(120*(i-1) + stewart.TP.dalpha - stewart.TP.alpha) ), ...
- stewart.H - stewart.TP.H - stewart.SP.H];
- stewart.Ab(2*i,:) = [stewart.TP.Rleg*cos( pi/180*(120*(i-1) + stewart.TP.dalpha + stewart.TP.alpha) ), ...
- stewart.TP.Rleg*sin( pi/180*(120*(i-1) + stewart.TP.dalpha + stewart.TP.alpha) ), ...
- stewart.H - stewart.TP.H - stewart.SP.H];
-end
-stewart.Bb = stewart.Ab - stewart.H*[0,0,1];
-
-leg_length = zeros(6, 1); % [mm]
-leg_vectors = zeros(6, 3);
-
-legs = stewart.Ab - stewart.Aa;
-
-for i = 1:6
- leg_length(i) = norm(legs(i,:));
- leg_vectors(i,:) = legs(i,:) / leg_length(i);
-end
-
-stewart.Leg.lenght = leg_length(1)/1.5;
-stewart.Leg.shape.bot = ...
- [0 0; ...
- stewart.Leg.Rbot 0; ...
- stewart.Leg.Rbot stewart.Leg.lenght; ...
- stewart.Leg.Rtop stewart.Leg.lenght; ...
- stewart.Leg.Rtop 0.2*stewart.Leg.lenght; ...
- 0 0.2*stewart.Leg.lenght];
-
-stewart.Rm = struct('R', eye(3));
-
-for i = 1:6
- sx = cross(leg_vectors(i,:), [1 0 0]);
- sx = sx/norm(sx);
-
- sy = -cross(sx, leg_vectors(i,:));
- sy = sy/norm(sy);
-
- sz = leg_vectors(i,:);
- sz = sz/norm(sz);
-
- stewart.Rm(i).R = [sx', sy', sz'];
-end
-
-J = zeros(6);
-
-for i = 1:6
- J(i, 1:3) = leg_vectors(i, :);
- J(i, 4:6) = cross(0.001*(stewart.Ab(i, :)- stewart.H*[0,0,1]), leg_vectors(i, :));
-end
-
-stewart.J = J;
-stewart.Jinv = inv(J);
-
-stewart.K = stewart.Leg.k_ax*stewart.J'*stewart.J;
-
-end
-end
diff --git a/src/initializeSimscapeData.m b/src/initializeSimscapeData.m
deleted file mode 100644
index ff0bfa5..0000000
--- a/src/initializeSimscapeData.m
+++ /dev/null
@@ -1,59 +0,0 @@
-function [stewart] = initializeSimscapeData(stewart, opts_param)
-
-opts = struct(...
- 'Jd_pos', [0, 0, 30], ... % Position of the Jacobian for displacement estimation from the top of the mobile platform [mm]
- 'Jf_pos', [0, 0, 30] ... % Position of the Jacobian for force location from the top of the mobile platform [mm]
- );
-
-if exist('opts_param','var')
- for opt = fieldnames(opts_param)'
- opts.(opt{1}) = opts_param.(opt{1});
- end
-end
-
-leg_length = zeros(6, 1); % [mm]
-leg_vectors = zeros(6, 3);
-
-legs = stewart.Ab - stewart.Aa;
-
-for i = 1:6
- leg_length(i) = norm(legs(i,:));
- leg_vectors(i,:) = legs(i,:) / leg_length(i);
-end
-
-stewart.Rm = struct('R', eye(3));
-
-for i = 1:6
- sx = cross(leg_vectors(i,:), [1 0 0]);
- sx = sx/norm(sx);
-
- sy = -cross(sx, leg_vectors(i,:));
- sy = sy/norm(sy);
-
- sz = leg_vectors(i,:);
- sz = sz/norm(sz);
-
- stewart.Rm(i).R = [sx', sy', sz'];
-end
-
-Jd = zeros(6);
-
-for i = 1:6
- Jd(i, 1:3) = leg_vectors(i, :);
- Jd(i, 4:6) = cross(0.001*(stewart.Bb(i, :) - opts.Jd_pos), leg_vectors(i, :));
-end
-
-stewart.Jd = Jd;
-stewart.Jd_inv = inv(Jd);
-
-Jf = zeros(6);
-
-for i = 1:6
- Jf(i, 1:3) = leg_vectors(i, :);
- Jf(i, 4:6) = cross(0.001*(stewart.Bb(i, :) - opts.Jf_pos), leg_vectors(i, :));
-end
-
-stewart.Jf = Jf;
-stewart.Jf_inv = inv(Jf);
-
-end
diff --git a/src/initializeStewartPlatform.m b/src/initializeStewartPlatform.m
deleted file mode 100644
index 0d48c10..0000000
--- a/src/initializeStewartPlatform.m
+++ /dev/null
@@ -1,94 +0,0 @@
-function [stewart] = initializeStewartPlatform(stewart, opts_param)
-
-opts = struct(...
- 'thickness', 10, ... % Thickness of the base and platform [mm]
- 'density', 1000, ... % Density of the material used for the hexapod [kg/m3]
- 'k_ax', 1e8, ... % Stiffness of each actuator [N/m]
- 'c_ax', 1000, ... % Damping of each actuator [N/(m/s)]
- 'stroke', 50e-6 ... % Maximum stroke of each actuator [m]
- );
-
-if exist('opts_param','var')
- for opt = fieldnames(opts_param)'
- opts.(opt{1}) = opts_param.(opt{1});
- end
-end
-
-BP = struct();
-
-BP.Rint = 0; % Internal Radius [mm]
-BP.Rext = 150; % External Radius [mm]
-
-BP.H = opts.thickness; % Thickness of the Bottom Plate [mm]
-
-BP.density = opts.density; % Density of the material [kg/m3]
-
-BP.color = [0.7 0.7 0.7]; % Color [RGB]
-
-BP.shape = [BP.Rint BP.H; BP.Rint 0; BP.Rext 0; BP.Rext BP.H]; % [mm]
-
-stewart.BP = BP;
-
-TP = struct();
-
-TP.Rint = 0; % [mm]
-TP.Rext = 100; % [mm]
-
-TP.H = 10; % [mm]
-
-TP.density = opts.density; % Density of the material [kg/m3]
-
-TP.color = [0.7 0.7 0.7]; % Color [RGB]
-
-TP.shape = [TP.Rint TP.H; TP.Rint 0; TP.Rext 0; TP.Rext TP.H];
-
-stewart.TP = TP;
-
-Leg = struct();
-
-Leg.stroke = opts.stroke; % [m]
-
-Leg.k_ax = opts.k_ax; % Stiffness of each leg [N/m]
-Leg.c_ax = opts.c_ax; % Damping of each leg [N/(m/s)]
-
-Leg.Rtop = 10; % Radius of the cylinder of the top part of the leg[mm]
-Leg.Rbot = 12; % Radius of the cylinder of the bottom part of the leg [mm]
-
-Leg.density = opts.density; % Density of the material used for the legs [kg/m3]
-
-Leg.color = [0.5 0.5 0.5]; % Color of the top part of the leg [RGB]
-
-Leg.R = 1.3*Leg.Rbot; % Size of the sphere at the extremity of the leg [mm]
-
-legs = stewart.Ab - stewart.Aa;
-Leg.lenght = norm(legs(1,:))/1.5;
-
-Leg.shape.bot = ...
- [0 0; ...
- Leg.Rbot 0; ...
- Leg.Rbot Leg.lenght; ...
- Leg.Rtop Leg.lenght; ...
- Leg.Rtop 0.2*Leg.lenght; ...
- 0 0.2*Leg.lenght];
-
-stewart.Leg = Leg;
-
-SP = struct();
-
-SP.k = 0; % [N*m/deg]
-SP.c = 0; % [N*m/deg]
-
-SP.H = stewart.Aa(1, 3) - BP.H; % [mm]
-
-SP.R = Leg.R; % [mm]
-
-SP.section = [0 SP.H-SP.R;
- 0 0;
- SP.R 0;
- SP.R SP.H];
-
-SP.density = opts.density; % [kg/m^3]
-
-SP.color = [0.7 0.7 0.7]; % [RGB]
-
-stewart.SP = SP;
diff --git a/src/initializeStrutDynamics.m b/src/initializeStrutDynamics.m
index e4ba57f..6863fd0 100644
--- a/src/initializeStrutDynamics.m
+++ b/src/initializeStrutDynamics.m
@@ -16,7 +16,7 @@ function [stewart] = initializeStrutDynamics(stewart, args)
arguments
stewart
args.Ki (6,1) double {mustBeNumeric, mustBePositive} = 1e6*ones(6,1)
- args.Ci (6,1) double {mustBeNumeric, mustBePositive} = 1e3*ones(6,1)
+ args.Ci (6,1) double {mustBeNumeric, mustBePositive} = 1e1*ones(6,1)
end
stewart.Ki = args.Ki;
diff --git a/static-analysis.org b/static-analysis.org
new file mode 100644
index 0000000..9069f8e
--- /dev/null
+++ b/static-analysis.org
@@ -0,0 +1,87 @@
+#+TITLE: Stewart Platform - Static Analysis
+:DRAWER:
+#+HTML_LINK_HOME: ./index.html
+#+HTML_LINK_UP: ./index.html
+
+#+HTML_HEAD:
+#+HTML_HEAD:
+#+HTML_HEAD:
+#+HTML_HEAD:
+#+HTML_HEAD:
+#+HTML_HEAD:
+
+#+PROPERTY: header-args:matlab :session *MATLAB*
+#+PROPERTY: header-args:matlab+ :comments org
+#+PROPERTY: header-args:matlab+ :exports both
+#+PROPERTY: header-args:matlab+ :results none
+#+PROPERTY: header-args:matlab+ :eval no-export
+#+PROPERTY: header-args:matlab+ :noweb yes
+#+PROPERTY: header-args:matlab+ :mkdirp yes
+#+PROPERTY: header-args:matlab+ :output-dir figs
+:END:
+
+* Jacobian
+** Relation to platform parameters
+A Jacobian is defined by:
+- the orientations of the struts $\hat{s}_i$ expressed in a frame $\{A\}$ linked to the fixed platform.
+- the vectors from $O_B$ to $b_i$ expressed in the frame $\{A\}$
+
+Then, the choice of $O_B$ changes the Jacobian.
+
+** Jacobian for displacement
+\[ \dot{q} = J \dot{X} \]
+With:
+- $q = [q_1\ q_2\ q_3\ q_4\ q_5\ q_6]$ vector of linear displacement of actuated joints
+- $X = [x\ y\ z\ \theta_x\ \theta_y\ \theta_z]$ position and orientation of $O_B$ expressed in the frame $\{A\}$
+
+For very small displacements $\delta q$ and $\delta X$, we have $\delta q = J \delta X$.
+
+** Jacobian for forces
+\[ F = J^T \tau \]
+With:
+- $\tau = [\tau_1\ \tau_2\ \tau_3\ \tau_4\ \tau_5\ \tau_6]$ vector of actuator forces
+- $F = [f_x\ f_y\ f_z\ n_x\ n_y\ n_z]$ force and torque acting on point $O_B$
+
+* Stiffness matrix $K$
+
+\[ K = J^T \text{diag}(k_i) J \]
+
+If all the struts have the same stiffness $k$, then $K = k J^T J$
+
+$K$ only depends of the geometry of the stewart platform: it depends on the Jacobian, that is on the orientations of the struts, position of the joints and choice of frame $\{B\}$.
+
+\[ F = K X \]
+
+With $F$ forces and torques applied to the moving platform at the origin of $\{B\}$ and $X$ the translations and rotations of $\{B\}$ with respect to $\{A\}$.
+
+\[ C = K^{-1} \]
+
+The compliance element $C_{ij}$ is then the stiffness
+\[ X_i = C_{ij} F_j \]
+
+* Coupling
+What causes the coupling from $F_i$ to $X_i$ ?
+
+#+begin_src latex :file coupling.pdf :post pdf2svg(file=*this*, ext="png") :exports both
+ \begin{tikzpicture}
+ \node[block] (Jt) at (0, 0) {$J^{-T}$};
+ \node[block, right= of Jt] (G) {$G$};
+ \node[block, right= of G] (J) {$J^{-1}$};
+
+ \draw[->] ($(Jt.west)+(-0.8, 0)$) -- (Jt.west) node[above left]{$F_i$};
+ \draw[->] (Jt.east) -- (G.west) node[above left]{$\tau_i$};
+ \draw[->] (G.east) -- (J.west) node[above left]{$q_i$};
+ \draw[->] (J.east) -- ++(0.8, 0) node[above left]{$X_i$};
+ \end{tikzpicture}
+#+end_src
+
+#+name: fig:block_diag_coupling
+#+caption: Block diagram to control an hexapod
+#+RESULTS:
+[[file:figs/coupling.png]]
+
+There is no coupling from $F_i$ to $X_j$ if $J^{-1} G J^{-T}$ is diagonal.
+
+If $G$ is diagonal (cubic configuration), then $J^{-1} G J^{-T} = G J^{-1} J^{-T} = G (J^{T} J)^{-1} = G K^{-1}$
+
+Thus, the system is uncoupled if $G$ and $K$ are diagonal.
diff --git a/stewart-architecture.html b/stewart-architecture.html
new file mode 100644
index 0000000..1cb20d3
--- /dev/null
+++ b/stewart-architecture.html
@@ -0,0 +1,1622 @@
+
+
+
+
+
+
+
+
+
+Stewart Platform - Definition of the Architecture
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Stewart platforms are generated in multiple steps.
+
+
+
+We define 4 important frames:
+
+
+
\(\{F\}\): Frame fixed to the Fixed base and located at the center of its bottom surface.
+This is used to fix the Stewart platform to some support.
+
\(\{M\}\): Frame fixed to the Moving platform and located at the center of its top surface.
+This is used to place things on top of the Stewart platform.
+
\(\{A\}\): Frame fixed to the fixed base.
+It defined the center of rotation of the moving platform.
+
\(\{B\}\): Frame fixed to the moving platform.
+The motion of the moving platforms and forces applied to it are defined with respect to this frame \(\{B\}\).
+
+
+
+Then, we define the location of the spherical joints:
+
+
+
\(\bm{a}_{i}\) are the position of the spherical joints fixed to the fixed base
+
\(\bm{b}_{i}\) are the position of the spherical joints fixed to the moving platform
+
+
+
+We define the rest position of the Stewart platform:
+
+
+
For simplicity, we suppose that the fixed base and the moving platform are parallel and aligned with the vertical axis at their rest position.
+
Thus, to define the rest position of the Stewart platform, we just have to defined its total height \(H\).
+\(H\) corresponds to the distance from the bottom of the fixed base to the top of the moving platform.
+
+
+
+From \(\bm{a}_{i}\) and \(\bm{b}_{i}\), we can determine the length and orientation of each strut:
+
+
+
\(l_{i}\) is the length of the strut
+
\({}^{A}\hat{\bm{s}}_{i}\) is the unit vector align with the strut
+
+
+
+The position of the Spherical joints can be computed using various methods:
+
+
+
Cubic configuration
+
Circular configuration
+
Arbitrary position
+
These methods should be easily scriptable and corresponds to specific functions that returns \({}^{F}\bm{a}_{i}\) and \({}^{M}\bm{b}_{i}\).
+The input of these functions are the parameters corresponding to the wanted geometry.
+
+
+
+For Simscape, we need:
+
+
+
The position and orientation of each spherical joint fixed to the fixed base: \({}^{F}\bm{a}_{i}\) and \({}^{F}\bm{R}_{a_{i}}\)
+
The position and orientation of each spherical joint fixed to the moving platform: \({}^{M}\bm{b}_{i}\) and \({}^{M}\bm{R}_{b_{i}}\)
+
The rest length of each strut: \(l_{i}\)
+
The stiffness and damping of each actuator: \(k_{i}\) and \(c_{i}\)
+
The position of the frame \(\{A\}\) with respect to the frame \(\{F\}\): \({}^{F}\bm{O}_{A}\)
+
The position of the frame \(\{B\}\) with respect to the frame \(\{M\}\): \({}^{M}\bm{O}_{B}\)
+
+
+
+
+
1 Procedure
+
+
+The procedure to define the Stewart platform is the following:
+
+
+
Define the initial position of frames {A}, {B}, {F} and {M}.
+We do that using the initializeFramesPositions function.
+We have to specify the total height of the Stewart platform \(H\) and the position \({}^{M}O_{B}\) of {B} with respect to {M}.
+
Compute the positions of joints \({}^{F}a_{i}\) and \({}^{M}b_{i}\).
+We can do that using various methods depending on the wanted architecture:
+
+
generateCubicConfiguration permits to generate a cubic configuration
+
+
Compute the position and orientation of the joints with respect to the fixed base and the moving platform.
+This is done with the computeJointsPose function.
+
Define the dynamical properties of the Stewart platform.
+The output are the stiffness and damping of each strut \(k_{i}\) and \(c_{i}\).
+This can be done we simply choosing directly the stiffness and damping of each strut.
+The stiffness and damping of each actuator can also be determine from the wanted stiffness of the Stewart platform for instance.
+
Define the mass and inertia of each element of the Stewart platform.
+
+
+
+By following this procedure, we obtain a Matlab structure stewart that contains all the information for the Simscape model and for further analysis.
+
function[stewart] = initializeFramesPositions(args)
+% initializeFramesPositions - Initialize the positions of frames {A}, {B}, {F} and {M}
+%
+% Syntax: [stewart] = initializeFramesPositions(args)
+%
+% Inputs:
+% - args - Can have the following fields:
+% - H [1x1] - Total Height of the Stewart Platform (height from {F} to {M}) [m]
+% - MO_B [1x1] - Height of the frame {B} with respect to {M} [m]
+%
+% Outputs:
+% - stewart - A structure with the following fields:
+% - H [1x1] - Total Height of the Stewart Platform [m]
+% - FO_M [3x1] - Position of {M} with respect to {F} [m]
+% - MO_B [3x1] - Position of {B} with respect to {M} [m]
+% - FO_A [3x1] - Position of {A} with respect to {F} [m]
+
+
+
+
+
+
+
3.2 Documentation
+
+
+
+
+
+
Figure 1: Definition of the position of the frames
stewart.H = args.H; % Total Height of the Stewart Platform [m]
+
+stewart.FO_M = [0; 0; stewart.H]; % Position of {M} with respect to {F} [m]
+
+stewart.MO_B = [0; 0; args.MO_B]; % Position of {B} with respect to {M} [m]
+
+stewart.FO_A = stewart.MO_B + stewart.FO_M; % Position of {A} with respect to {F} [m]
+
+
+
+
+
+
+
+
4 Initialize the position of the Joints
+
+
+
+
4.1generateCubicConfiguration: Generate a Cubic Configuration
function[stewart] = generateCubicConfiguration(stewart, args)
+% generateCubicConfiguration - Generate a Cubic Configuration
+%
+% Syntax: [stewart] = generateCubicConfiguration(stewart, args)
+%
+% Inputs:
+% - stewart - A structure with the following fields
+% - H [1x1] - Total height of the platform [m]
+% - args - Can have the following fields:
+% - Hc [1x1] - Height of the "useful" part of the cube [m]
+% - FOc [1x1] - Height of the center of the cube with respect to {F} [m]
+% - FHa [1x1] - Height of the plane joining the points ai with respect to the frame {F} [m]
+% - MHb [1x1] - Height of the plane joining the points bi with respect to the frame {M} [m]
+%
+% Outputs:
+% - stewart - updated Stewart structure with the added fields:
+% - Fa [3x6] - Its i'th column is the position vector of joint ai with respect to {F}
+% - Mb [3x6] - Its i'th column is the position vector of joint bi with respect to {M}
+
+We define the useful points of the cube with respect to the Cube’s center.
+\({}^{C}C\) are the 6 vertices of the cubes expressed in a frame {C} which is
+located at the center of the cube and aligned with {F} and {M}.
+
+
+
+
sx = [ 2; -1; -1];
+sy = [ 0; 1; -1];
+sz = [ 1; 1; 1];
+
+R = [sx, sy, sz]./vecnorm([sx, sy, sz]);
+
+L = args.Hc*sqrt(3);
+
+Cc = R'*[[0;0;L],[L;0;L],[L;0;0],[L;L;0],[0;L;0],[0;L;L]] - [0;0;1.5*args.Hc];
+
+CCf = [Cc(:,1), Cc(:,3), Cc(:,3), Cc(:,5), Cc(:,5), Cc(:,1)]; % CCf(:,i) corresponds to the bottom cube's vertice corresponding to the i'th leg
+CCm = [Cc(:,2), Cc(:,2), Cc(:,4), Cc(:,4), Cc(:,6), Cc(:,6)]; % CCm(:,i) corresponds to the top cube's vertice corresponding to the i'th leg
+
+
+
+
+
+
+
4.1.5 Compute the pose
+
+
+We can compute the vector of each leg \({}^{C}\hat{\bm{s}}_{i}\) (unit vector from \({}^{C}C_{f}\) to \({}^{C}C_{m}\)).
+
+
+
CSi = (CCm - CCf)./vecnorm(CCm - CCf);
+
+
+
+
+We now which to compute the position of the joints \(a_{i}\) and \(b_{i}\).
+
function[stewart] = generateGeneralConfiguration(stewart, args)
+% generateGeneralConfiguration - Generate a Very General Configuration
+%
+% Syntax: [stewart] = generateGeneralConfiguration(stewart, args)
+%
+% Inputs:
+% - args - Can have the following fields:
+% - FH [1x1] - Height of the position of the fixed joints with respect to the frame {F} [m]
+% - FR [1x1] - Radius of the position of the fixed joints in the X-Y [m]
+% - FTh [6x1] - Angles of the fixed joints in the X-Y plane with respect to the X axis [rad]
+% - MH [1x1] - Height of the position of the mobile joints with respect to the frame {M} [m]
+% - FR [1x1] - Radius of the position of the mobile joints in the X-Y [m]
+% - MTh [6x1] - Angles of the mobile joints in the X-Y plane with respect to the X axis [rad]
+%
+% Outputs:
+% - stewart - updated Stewart structure with the added fields:
+% - Fa [3x6] - Its i'th column is the position vector of joint ai with respect to {F}
+% - Mb [3x6] - Its i'th column is the position vector of joint bi with respect to {M}
+
+
+
+
+
+
+
4.2.2 Documentation
+
+
+Joints are positions on a circle centered with the Z axis of {F} and {M} and at a chosen distance from {F} and {M}.
+The radius of the circles can be chosen as well as the angles where the joints are located.
+
function[stewart] = computeJointsPose(stewart)
+% computeJointsPose -
+%
+% Syntax: [stewart] = computeJointsPose(stewart)
+%
+% Inputs:
+% - stewart - A structure with the following fields
+% - Fa [3x6] - Its i'th column is the position vector of joint ai with respect to {F}
+% - Mb [3x6] - Its i'th column is the position vector of joint bi with respect to {M}
+% - FO_A [3x1] - Position of {A} with respect to {F}
+% - MO_B [3x1] - Position of {B} with respect to {M}
+% - FO_M [3x1] - Position of {M} with respect to {F}
+%
+% Outputs:
+% - stewart - A structure with the following added fields
+% - Aa [3x6] - The i'th column is the position of ai with respect to {A}
+% - Ab [3x6] - The i'th column is the position of bi with respect to {A}
+% - Ba [3x6] - The i'th column is the position of ai with respect to {B}
+% - Bb [3x6] - The i'th column is the position of bi with respect to {B}
+% - l [6x1] - The i'th element is the initial length of strut i
+% - As [3x6] - The i'th column is the unit vector of strut i expressed in {A}
+% - Bs [3x6] - The i'th column is the unit vector of strut i expressed in {B}
+% - FRa [3x3x6] - The i'th 3x3 array is the rotation matrix to orientate the bottom of the i'th strut from {F}
+% - MRb [3x3x6] - The i'th 3x3 array is the rotation matrix to orientate the top of the i'th strut from {M}
+
function[stewart] = initializeStrutDynamics(stewart, args)
+% initializeStrutDynamics - Add Stiffness and Damping properties of each strut
+%
+% Syntax: [stewart] = initializeStrutDynamics(args)
+%
+% Inputs:
+% - args - Structure with the following fields:
+% - Ki [6x1] - Stiffness of each strut [N/m]
+% - Ci [6x1] - Damping of each strut [N/(m/s)]
+%
+% Outputs:
+% - stewart - updated Stewart structure with the added fields:
+% - Ki [6x1] - Stiffness of each strut [N/m]
+% - Ci [6x1] - Damping of each strut [N/(m/s)]
+
function[stewart] = computeJacobian(stewart)
+% computeJacobian -
+%
+% Syntax: [stewart] = computeJacobian(stewart)
+%
+% Inputs:
+% - stewart - With at least the following fields:
+% - As [3x6] - The 6 unit vectors for each strut expressed in {A}
+% - Ab [3x6] - The 6 position of the joints bi expressed in {A}
+%
+% Outputs:
+% - stewart - With the 3 added field:
+% - J [6x6] - The Jacobian Matrix
+% - K [6x6] - The Stiffness Matrix
+% - C [6x6] - The Compliance Matrix
+
function[stewart] = initializeCylindricalStruts(stewart, args)
+% initializeCylindricalStruts - Define the mass and moment of inertia of cylindrical struts
+%
+% Syntax: [stewart] = initializeCylindricalStruts(args)
+%
+% Inputs:
+% - args - Structure with the following fields:
+% - Fsm [1x1] - Mass of the Fixed part of the struts [kg]
+% - Fsh [1x1] - Height of cylinder for the Fixed part of the struts [m]
+% - Fsr [1x1] - Radius of cylinder for the Fixed part of the struts [m]
+% - Msm [1x1] - Mass of the Mobile part of the struts [kg]
+% - Msh [1x1] - Height of cylinder for the Mobile part of the struts [m]
+% - Msr [1x1] - Radius of cylinder for the Mobile part of the struts [m]
+%
+% Outputs:
+% - stewart - updated Stewart structure with the added fields:
+% - struts [struct] - structure with the following fields:
+% - Fsm [6x1] - Mass of the Fixed part of the struts [kg]
+% - Fsi [3x3x6] - Moment of Inertia for the Fixed part of the struts [kg*m^2]
+% - Msm [6x1] - Mass of the Mobile part of the struts [kg]
+% - Msi [3x3x6] - Moment of Inertia for the Mobile part of the struts [kg*m^2]
+% - Fsh [6x1] - Height of cylinder for the Fixed part of the struts [m]
+% - Fsr [6x1] - Radius of cylinder for the Fixed part of the struts [m]
+% - Msh [6x1] - Height of cylinder for the Mobile part of the struts [m]
+% - Msr [6x1] - Radius of cylinder for the Mobile part of the struts [m]
+
function[stewart] = initializeStewartPose(stewart, args)
+% initializeStewartPose - Determine the initial stroke in each leg to have the wanted pose
+% It uses the inverse kinematic
+%
+% Syntax: [stewart] = initializeStewartPose(stewart, args)
+%
+% Inputs:
+% - stewart - A structure with the following fields
+% - Aa [3x6] - The positions ai expressed in {A}
+% - Bb [3x6] - The positions bi expressed in {B}
+% - args - Can have the following fields:
+% - AP [3x1] - The wanted position of {B} with respect to {A}
+% - ARB [3x3] - The rotation matrix that gives the wanted orientation of {B} with respect to {A}
+%
+% Outputs:
+% - stewart - updated Stewart structure with the added fields:
+% - dLi[6x1] - The 6 needed displacement of the struts from the initial position in [m] to have the wanted pose of {B} w.r.t. {A}
+
function[Li, dLi] = inverseKinematics(stewart, args)
+% inverseKinematics - Compute the needed length of each strut to have the wanted position and orientation of {B} with respect to {A}
+%
+% Syntax: [stewart] = inverseKinematics(stewart)
+%
+% Inputs:
+% - stewart - A structure with the following fields
+% - Aa [3x6] - The positions ai expressed in {A}
+% - Bb [3x6] - The positions bi expressed in {B}
+% - args - Can have the following fields:
+% - AP [3x1] - The wanted position of {B} with respect to {A}
+% - ARB [3x3] - The rotation matrix that gives the wanted orientation of {B} with respect to {A}
+%
+% Outputs:
+% - Li [6x1] - The 6 needed length of the struts in [m] to have the wanted pose of {B} w.r.t. {A}
+% - dLi [6x1] - The 6 needed displacement of the struts from the initial position in [m] to have the wanted pose of {B} w.r.t. {A}
+
+For inverse kinematic analysis, it is assumed that the position \({}^A\bm{P}\) and orientation of the moving platform \({}^A\bm{R}_B\) are given and the problem is to obtain the joint variables, namely, \(\bm{L} = [l_1, l_2, \dots, l_6]^T\).
+
+
+
+From the geometry of the manipulator, the loop closure for each limb, \(i = 1, 2, \dots, 6\) can be written as
+
+If the position and orientation of the moving platform lie in the feasible workspace of the manipulator, one unique solution to the limb length is determined by the above equation.
+Otherwise, when the limbs’ lengths derived yield complex numbers, then the position or orientation of the moving platform is not reachable.
+
function[P, R] = forwardKinematicsApprox(stewart, args)
+% forwardKinematicsApprox - Computed the approximate pose of {B} with respect to {A} from the length of each strut and using
+% the Jacobian Matrix
+%
+% Syntax: [P, R] = forwardKinematicsApprox(stewart, args)
+%
+% Inputs:
+% - stewart - A structure with the following fields
+% - J [6x6] - The Jacobian Matrix
+% - args - Can have the following fields:
+% - dL [6x1] - Displacement of each strut [m]
+%
+% Outputs:
+% - P [3x1] - The estimated position of {B} with respect to {A}
+% - R [3x3] - The estimated rotation matrix that gives the orientation of {B} with respect to {A}
+
+From a small displacement of each strut \(d\bm{\mathcal{L}}\), we can compute the
+position and orientation of {B} with respect to {A} using the following formula:
+\[ d \bm{\mathcal{X}} = \bm{J}^{-1} d\bm{\mathcal{L}} \]
+
+
+
X = stewart.J\args.dL;
+
+
+
+
+The position vector corresponds to the first 3 elements.
+
+
+
P = X(1:3);
+
+
+
+
+The next 3 elements are the orientation of {B} with respect to {A} expressed
+using the screw axis.
+
+
+
theta = norm(X(4:6));
+s = X(4:6)/theta;
+
+
+
+
+We then compute the corresponding rotation matrix.
+
function[accelerometer] = initializeZAxisAccelerometer(args)
+ arguments
+ args.mass (1,1) double {mustBeNumeric, mustBePositive} = 1e-3 % [kg]
+ args.freq (1,1) double {mustBeNumeric, mustBePositive} = 5e3 % [Hz]
+ end
+
+ %%
+ accelerometer.m = args.mass;
+
+ %% The Stiffness is set to have the damping resonance frequency
+ accelerometer.k = accelerometer.m * (2*pi*args.freq)^2;
+
+ %% We set the damping value to have critical damping
+ accelerometer.c = 2*sqrt(accelerometer.m * accelerometer.k);
+
+ %% Gain correction of the accelerometer to have a unity gain until the resonance
+ accelerometer.gain = -accelerometer.k/accelerometer.m;
+
+ %% Save
+ save('./mat/accelerometer_z_axis.mat', 'accelerometer');
+end
+
+
+
+
+
+
+
+
Author: Dehaeze Thomas
+
Created: 2020-01-27 lun. 17:41
+
+
+
diff --git a/stewart-architecture.org b/stewart-architecture.org
new file mode 100644
index 0000000..2b2bcb0
--- /dev/null
+++ b/stewart-architecture.org
@@ -0,0 +1,1615 @@
+#+TITLE: Stewart Platform - Definition of the Architecture
+:DRAWER:
+#+HTML_LINK_HOME: ./index.html
+#+HTML_LINK_UP: ./index.html
+
+#+HTML_HEAD:
+#+HTML_HEAD:
+#+HTML_HEAD:
+#+HTML_HEAD:
+#+HTML_HEAD:
+#+HTML_HEAD:
+
+#+PROPERTY: header-args:matlab :session *MATLAB*
+#+PROPERTY: header-args:matlab+ :comments org
+#+PROPERTY: header-args:matlab+ :exports both
+#+PROPERTY: header-args:matlab+ :results none
+#+PROPERTY: header-args:matlab+ :eval no-export
+#+PROPERTY: header-args:matlab+ :noweb yes
+#+PROPERTY: header-args:matlab+ :mkdirp yes
+#+PROPERTY: header-args:matlab+ :output-dir figs
+:END:
+
+* Introduction :ignore:
+Stewart platforms are generated in multiple steps.
+
+We define 4 important *frames*:
+- $\{F\}$: Frame fixed to the *Fixed* base and located at the center of its bottom surface.
+ This is used to fix the Stewart platform to some support.
+- $\{M\}$: Frame fixed to the *Moving* platform and located at the center of its top surface.
+ This is used to place things on top of the Stewart platform.
+- $\{A\}$: Frame fixed to the fixed base.
+ It defined the center of rotation of the moving platform.
+- $\{B\}$: Frame fixed to the moving platform.
+ The motion of the moving platforms and forces applied to it are defined with respect to this frame $\{B\}$.
+
+Then, we define the *location of the spherical joints*:
+- $\bm{a}_{i}$ are the position of the spherical joints fixed to the fixed base
+- $\bm{b}_{i}$ are the position of the spherical joints fixed to the moving platform
+
+We define the *rest position* of the Stewart platform:
+- For simplicity, we suppose that the fixed base and the moving platform are parallel and aligned with the vertical axis at their rest position.
+- Thus, to define the rest position of the Stewart platform, we just have to defined its total height $H$.
+ $H$ corresponds to the distance from the bottom of the fixed base to the top of the moving platform.
+
+From $\bm{a}_{i}$ and $\bm{b}_{i}$, we can determine the *length and orientation of each strut*:
+- $l_{i}$ is the length of the strut
+- ${}^{A}\hat{\bm{s}}_{i}$ is the unit vector align with the strut
+
+The position of the Spherical joints can be computed using various methods:
+- Cubic configuration
+- Circular configuration
+- Arbitrary position
+- These methods should be easily scriptable and corresponds to specific functions that returns ${}^{F}\bm{a}_{i}$ and ${}^{M}\bm{b}_{i}$.
+ The input of these functions are the parameters corresponding to the wanted geometry.
+
+For Simscape, we need:
+- The position and orientation of each spherical joint fixed to the fixed base: ${}^{F}\bm{a}_{i}$ and ${}^{F}\bm{R}_{a_{i}}$
+- The position and orientation of each spherical joint fixed to the moving platform: ${}^{M}\bm{b}_{i}$ and ${}^{M}\bm{R}_{b_{i}}$
+- The rest length of each strut: $l_{i}$
+- The stiffness and damping of each actuator: $k_{i}$ and $c_{i}$
+- The position of the frame $\{A\}$ with respect to the frame $\{F\}$: ${}^{F}\bm{O}_{A}$
+- The position of the frame $\{B\}$ with respect to the frame $\{M\}$: ${}^{M}\bm{O}_{B}$
+
+
+* Procedure
+The procedure to define the Stewart platform is the following:
+1. Define the initial position of frames {A}, {B}, {F} and {M}.
+ We do that using the =initializeFramesPositions= function.
+ We have to specify the total height of the Stewart platform $H$ and the position ${}^{M}O_{B}$ of {B} with respect to {M}.
+2. Compute the positions of joints ${}^{F}a_{i}$ and ${}^{M}b_{i}$.
+ We can do that using various methods depending on the wanted architecture:
+ - =generateCubicConfiguration= permits to generate a cubic configuration
+3. Compute the position and orientation of the joints with respect to the fixed base and the moving platform.
+ This is done with the =computeJointsPose= function.
+4. Define the dynamical properties of the Stewart platform.
+ The output are the stiffness and damping of each strut $k_{i}$ and $c_{i}$.
+ This can be done we simply choosing directly the stiffness and damping of each strut.
+ The stiffness and damping of each actuator can also be determine from the wanted stiffness of the Stewart platform for instance.
+5. Define the mass and inertia of each element of the Stewart platform.
+
+By following this procedure, we obtain a Matlab structure =stewart= that contains all the information for the Simscape model and for further analysis.
+
+* Matlab Code
+** Matlab Init :noexport:ignore:
+#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name)
+ <>
+#+end_src
+
+#+begin_src matlab :exports none :results silent :noweb yes
+ <>
+#+end_src
+
+#+begin_src matlab
+ simulinkproject('./');
+#+end_src
+
+** Simscape Model
+#+begin_src matlab
+ open('stewart_platform.slx')
+#+end_src
+
+** Test the functions
+#+begin_src matlab
+ stewart = initializeFramesPositions('H', 90e-3, 'MO_B', 45e-3);
+ % stewart = generateCubicConfiguration(stewart, 'Hc', 60e-3, 'FOc', 45e-3, 'FHa', 5e-3, 'MHb', 5e-3);
+ stewart = generateGeneralConfiguration(stewart);
+ stewart = computeJointsPose(stewart);
+ stewart = initializeStrutDynamics(stewart, 'Ki', 1e6*ones(6,1), 'Ci', 1e2*ones(6,1));
+ stewart = initializeCylindricalPlatforms(stewart);
+ stewart = initializeCylindricalStruts(stewart);
+ stewart = computeJacobian(stewart);
+ stewart = initializeStewartPose(stewart, 'AP', [0;0;0.01], 'ARB', eye(3));
+
+ [Li, dLi] = inverseKinematics(stewart, 'AP', [0;0;0.00001], 'ARB', eye(3));
+ [P, R] = forwardKinematicsApprox(stewart, 'dL', dLi);
+#+end_src
+
+* =initializeFramesPositions=: Initialize the positions of frames {A}, {B}, {F} and {M}
+:PROPERTIES:
+:header-args:matlab+: :tangle src/initializeFramesPositions.m
+:header-args:matlab+: :comments none :mkdirp yes :eval no
+:END:
+<>
+
+This Matlab function is accessible [[file:src/initializeFramesPositions.m][here]].
+
+** Function description
+#+begin_src matlab
+ function [stewart] = initializeFramesPositions(args)
+ % initializeFramesPositions - Initialize the positions of frames {A}, {B}, {F} and {M}
+ %
+ % Syntax: [stewart] = initializeFramesPositions(args)
+ %
+ % Inputs:
+ % - args - Can have the following fields:
+ % - H [1x1] - Total Height of the Stewart Platform (height from {F} to {M}) [m]
+ % - MO_B [1x1] - Height of the frame {B} with respect to {M} [m]
+ %
+ % Outputs:
+ % - stewart - A structure with the following fields:
+ % - H [1x1] - Total Height of the Stewart Platform [m]
+ % - FO_M [3x1] - Position of {M} with respect to {F} [m]
+ % - MO_B [3x1] - Position of {B} with respect to {M} [m]
+ % - FO_A [3x1] - Position of {A} with respect to {F} [m]
+#+end_src
+
+** Documentation
+
+#+name: fig:stewart-frames-position
+#+caption: Definition of the position of the frames
+[[file:figs/stewart-frames-position.png]]
+
+** Optional Parameters
+#+begin_src matlab
+ arguments
+ args.H (1,1) double {mustBeNumeric, mustBePositive} = 90e-3
+ args.MO_B (1,1) double {mustBeNumeric} = 50e-3
+ end
+#+end_src
+
+** Initialize the Stewart structure
+#+begin_src matlab
+ stewart = struct();
+#+end_src
+
+** Compute the position of each frame
+#+begin_src matlab
+ stewart.H = args.H; % Total Height of the Stewart Platform [m]
+
+ stewart.FO_M = [0; 0; stewart.H]; % Position of {M} with respect to {F} [m]
+
+ stewart.MO_B = [0; 0; args.MO_B]; % Position of {B} with respect to {M} [m]
+
+ stewart.FO_A = stewart.MO_B + stewart.FO_M; % Position of {A} with respect to {F} [m]
+#+end_src
+
+* Initialize the position of the Joints
+** =generateCubicConfiguration=: Generate a Cubic Configuration
+:PROPERTIES:
+:header-args:matlab+: :tangle src/generateCubicConfiguration.m
+:header-args:matlab+: :comments none :mkdirp yes :eval no
+:END:
+<>
+
+This Matlab function is accessible [[file:src/generateCubicConfiguration.m][here]].
+
+*** Function description
+#+begin_src matlab
+ function [stewart] = generateCubicConfiguration(stewart, args)
+ % generateCubicConfiguration - Generate a Cubic Configuration
+ %
+ % Syntax: [stewart] = generateCubicConfiguration(stewart, args)
+ %
+ % Inputs:
+ % - stewart - A structure with the following fields
+ % - H [1x1] - Total height of the platform [m]
+ % - args - Can have the following fields:
+ % - Hc [1x1] - Height of the "useful" part of the cube [m]
+ % - FOc [1x1] - Height of the center of the cube with respect to {F} [m]
+ % - FHa [1x1] - Height of the plane joining the points ai with respect to the frame {F} [m]
+ % - MHb [1x1] - Height of the plane joining the points bi with respect to the frame {M} [m]
+ %
+ % Outputs:
+ % - stewart - updated Stewart structure with the added fields:
+ % - Fa [3x6] - Its i'th column is the position vector of joint ai with respect to {F}
+ % - Mb [3x6] - Its i'th column is the position vector of joint bi with respect to {M}
+#+end_src
+
+*** Documentation
+#+name: fig:cubic-configuration-definition
+#+caption: Cubic Configuration
+[[file:figs/cubic-configuration-definition.png]]
+
+*** Optional Parameters
+#+begin_src matlab
+ arguments
+ stewart
+ args.Hc (1,1) double {mustBeNumeric, mustBePositive} = 60e-3
+ args.FOc (1,1) double {mustBeNumeric} = 50e-3
+ args.FHa (1,1) double {mustBeNumeric, mustBePositive} = 15e-3
+ args.MHb (1,1) double {mustBeNumeric, mustBePositive} = 15e-3
+ end
+#+end_src
+
+*** Position of the Cube
+We define the useful points of the cube with respect to the Cube's center.
+${}^{C}C$ are the 6 vertices of the cubes expressed in a frame {C} which is
+located at the center of the cube and aligned with {F} and {M}.
+
+#+begin_src matlab
+ sx = [ 2; -1; -1];
+ sy = [ 0; 1; -1];
+ sz = [ 1; 1; 1];
+
+ R = [sx, sy, sz]./vecnorm([sx, sy, sz]);
+
+ L = args.Hc*sqrt(3);
+
+ Cc = R'*[[0;0;L],[L;0;L],[L;0;0],[L;L;0],[0;L;0],[0;L;L]] - [0;0;1.5*args.Hc];
+
+ CCf = [Cc(:,1), Cc(:,3), Cc(:,3), Cc(:,5), Cc(:,5), Cc(:,1)]; % CCf(:,i) corresponds to the bottom cube's vertice corresponding to the i'th leg
+ CCm = [Cc(:,2), Cc(:,2), Cc(:,4), Cc(:,4), Cc(:,6), Cc(:,6)]; % CCm(:,i) corresponds to the top cube's vertice corresponding to the i'th leg
+#+end_src
+
+*** Compute the pose
+We can compute the vector of each leg ${}^{C}\hat{\bm{s}}_{i}$ (unit vector from ${}^{C}C_{f}$ to ${}^{C}C_{m}$).
+#+begin_src matlab
+ CSi = (CCm - CCf)./vecnorm(CCm - CCf);
+#+end_src
+
+We now which to compute the position of the joints $a_{i}$ and $b_{i}$.
+#+begin_src matlab
+ stewart.Fa = CCf + [0; 0; args.FOc] + ((args.FHa-(args.FOc-args.Hc/2))./CSi(3,:)).*CSi;
+ stewart.Mb = CCf + [0; 0; args.FOc-stewart.H] + ((stewart.H-args.MHb-(args.FOc-args.Hc/2))./CSi(3,:)).*CSi;
+#+end_src
+
+** =generateGeneralConfiguration=: Generate a Very General Configuration
+:PROPERTIES:
+:header-args:matlab+: :tangle src/generateGeneralConfiguration.m
+:header-args:matlab+: :comments none :mkdirp yes :eval no
+:END:
+<>
+
+This Matlab function is accessible [[file:src/generateGeneralConfiguration.m][here]].
+
+*** Function description
+#+begin_src matlab
+ function [stewart] = generateGeneralConfiguration(stewart, args)
+ % generateGeneralConfiguration - Generate a Very General Configuration
+ %
+ % Syntax: [stewart] = generateGeneralConfiguration(stewart, args)
+ %
+ % Inputs:
+ % - args - Can have the following fields:
+ % - FH [1x1] - Height of the position of the fixed joints with respect to the frame {F} [m]
+ % - FR [1x1] - Radius of the position of the fixed joints in the X-Y [m]
+ % - FTh [6x1] - Angles of the fixed joints in the X-Y plane with respect to the X axis [rad]
+ % - MH [1x1] - Height of the position of the mobile joints with respect to the frame {M} [m]
+ % - FR [1x1] - Radius of the position of the mobile joints in the X-Y [m]
+ % - MTh [6x1] - Angles of the mobile joints in the X-Y plane with respect to the X axis [rad]
+ %
+ % Outputs:
+ % - stewart - updated Stewart structure with the added fields:
+ % - Fa [3x6] - Its i'th column is the position vector of joint ai with respect to {F}
+ % - Mb [3x6] - Its i'th column is the position vector of joint bi with respect to {M}
+#+end_src
+
+*** Documentation
+Joints are positions on a circle centered with the Z axis of {F} and {M} and at a chosen distance from {F} and {M}.
+The radius of the circles can be chosen as well as the angles where the joints are located.
+
+*** Optional Parameters
+#+begin_src matlab
+ arguments
+ stewart
+ args.FH (1,1) double {mustBeNumeric, mustBePositive} = 15e-3
+ args.FR (1,1) double {mustBeNumeric, mustBePositive} = 115e-3;
+ args.FTh (6,1) double {mustBeNumeric} = [-10, 10, 120-10, 120+10, 240-10, 240+10]*(pi/180);
+ args.MH (1,1) double {mustBeNumeric, mustBePositive} = 15e-3
+ args.MR (1,1) double {mustBeNumeric, mustBePositive} = 90e-3;
+ args.MTh (6,1) double {mustBeNumeric} = [-60+10, 60-10, 60+10, 180-10, 180+10, -60-10]*(pi/180);
+ end
+#+end_src
+
+*** Compute the pose
+#+begin_src matlab
+ stewart.Fa = zeros(3,6);
+ stewart.Mb = zeros(3,6);
+#+end_src
+
+#+begin_src matlab
+ for i = 1:6
+ stewart.Fa(:,i) = [args.FR*cos(args.FTh(i)); args.FR*sin(args.FTh(i)); args.FH];
+ stewart.Mb(:,i) = [args.MR*cos(args.MTh(i)); args.MR*sin(args.MTh(i)); -args.MH];
+ end
+#+end_src
+
+* =computeJointsPose=: Compute the Pose of the Joints
+:PROPERTIES:
+:header-args:matlab+: :tangle src/computeJointsPose.m
+:header-args:matlab+: :comments none :mkdirp yes :eval no
+:END:
+<>
+
+This Matlab function is accessible [[file:src/computeJointsPose.m][here]].
+
+** Function description
+#+begin_src matlab
+ function [stewart] = computeJointsPose(stewart)
+ % computeJointsPose -
+ %
+ % Syntax: [stewart] = computeJointsPose(stewart)
+ %
+ % Inputs:
+ % - stewart - A structure with the following fields
+ % - Fa [3x6] - Its i'th column is the position vector of joint ai with respect to {F}
+ % - Mb [3x6] - Its i'th column is the position vector of joint bi with respect to {M}
+ % - FO_A [3x1] - Position of {A} with respect to {F}
+ % - MO_B [3x1] - Position of {B} with respect to {M}
+ % - FO_M [3x1] - Position of {M} with respect to {F}
+ %
+ % Outputs:
+ % - stewart - A structure with the following added fields
+ % - Aa [3x6] - The i'th column is the position of ai with respect to {A}
+ % - Ab [3x6] - The i'th column is the position of bi with respect to {A}
+ % - Ba [3x6] - The i'th column is the position of ai with respect to {B}
+ % - Bb [3x6] - The i'th column is the position of bi with respect to {B}
+ % - l [6x1] - The i'th element is the initial length of strut i
+ % - As [3x6] - The i'th column is the unit vector of strut i expressed in {A}
+ % - Bs [3x6] - The i'th column is the unit vector of strut i expressed in {B}
+ % - FRa [3x3x6] - The i'th 3x3 array is the rotation matrix to orientate the bottom of the i'th strut from {F}
+ % - MRb [3x3x6] - The i'th 3x3 array is the rotation matrix to orientate the top of the i'th strut from {M}
+#+end_src
+
+** Documentation
+
+#+name: fig:stewart-struts
+#+caption: Position and orientation of the struts
+[[file:figs/stewart-struts.png]]
+
+** Compute the position of the Joints
+#+begin_src matlab
+ stewart.Aa = stewart.Fa - repmat(stewart.FO_A, [1, 6]);
+ stewart.Bb = stewart.Mb - repmat(stewart.MO_B, [1, 6]);
+
+ stewart.Ab = stewart.Bb - repmat(-stewart.MO_B-stewart.FO_M+stewart.FO_A, [1, 6]);
+ stewart.Ba = stewart.Aa - repmat( stewart.MO_B+stewart.FO_M-stewart.FO_A, [1, 6]);
+#+end_src
+
+** Compute the strut length and orientation
+#+begin_src matlab
+ stewart.As = (stewart.Ab - stewart.Aa)./vecnorm(stewart.Ab - stewart.Aa); % As_i is the i'th vector of As
+
+ stewart.l = vecnorm(stewart.Ab - stewart.Aa)';
+#+end_src
+
+#+begin_src matlab
+ stewart.Bs = (stewart.Bb - stewart.Ba)./vecnorm(stewart.Bb - stewart.Ba);
+#+end_src
+
+** Compute the orientation of the Joints
+#+begin_src matlab
+ stewart.FRa = zeros(3,3,6);
+ stewart.MRb = zeros(3,3,6);
+
+ for i = 1:6
+ stewart.FRa(:,:,i) = [cross([0;1;0], stewart.As(:,i)) , cross(stewart.As(:,i), cross([0;1;0], stewart.As(:,i))) , stewart.As(:,i)];
+ stewart.FRa(:,:,i) = stewart.FRa(:,:,i)./vecnorm(stewart.FRa(:,:,i));
+
+ stewart.MRb(:,:,i) = [cross([0;1;0], stewart.Bs(:,i)) , cross(stewart.Bs(:,i), cross([0;1;0], stewart.Bs(:,i))) , stewart.Bs(:,i)];
+ stewart.MRb(:,:,i) = stewart.MRb(:,:,i)./vecnorm(stewart.MRb(:,:,i));
+ end
+#+end_src
+
+* =initializeStrutDynamics=: Add Stiffness and Damping properties of each strut
+:PROPERTIES:
+:header-args:matlab+: :tangle src/initializeStrutDynamics.m
+:header-args:matlab+: :comments none :mkdirp yes :eval no
+:END:
+<>
+
+This Matlab function is accessible [[file:src/initializeStrutDynamics.m][here]].
+
+** Function description
+#+begin_src matlab
+ function [stewart] = initializeStrutDynamics(stewart, args)
+ % initializeStrutDynamics - Add Stiffness and Damping properties of each strut
+ %
+ % Syntax: [stewart] = initializeStrutDynamics(args)
+ %
+ % Inputs:
+ % - args - Structure with the following fields:
+ % - Ki [6x1] - Stiffness of each strut [N/m]
+ % - Ci [6x1] - Damping of each strut [N/(m/s)]
+ %
+ % Outputs:
+ % - stewart - updated Stewart structure with the added fields:
+ % - Ki [6x1] - Stiffness of each strut [N/m]
+ % - Ci [6x1] - Damping of each strut [N/(m/s)]
+#+end_src
+
+** Optional Parameters
+#+begin_src matlab
+ arguments
+ stewart
+ args.Ki (6,1) double {mustBeNumeric, mustBePositive} = 1e6*ones(6,1)
+ args.Ci (6,1) double {mustBeNumeric, mustBePositive} = 1e1*ones(6,1)
+ end
+#+end_src
+
+** Add Stiffness and Damping properties of each strut
+#+begin_src matlab
+ stewart.Ki = args.Ki;
+ stewart.Ci = args.Ci;
+#+end_src
+
+* =computeJacobian=: Compute the Jacobian Matrix
+:PROPERTIES:
+:header-args:matlab+: :tangle src/computeJacobian.m
+:header-args:matlab+: :comments none :mkdirp yes :eval no
+:END:
+<>
+
+This Matlab function is accessible [[file:src/computeJacobian.m][here]].
+
+** Function description
+#+begin_src matlab
+ function [stewart] = computeJacobian(stewart)
+ % computeJacobian -
+ %
+ % Syntax: [stewart] = computeJacobian(stewart)
+ %
+ % Inputs:
+ % - stewart - With at least the following fields:
+ % - As [3x6] - The 6 unit vectors for each strut expressed in {A}
+ % - Ab [3x6] - The 6 position of the joints bi expressed in {A}
+ %
+ % Outputs:
+ % - stewart - With the 3 added field:
+ % - J [6x6] - The Jacobian Matrix
+ % - K [6x6] - The Stiffness Matrix
+ % - C [6x6] - The Compliance Matrix
+#+end_src
+
+** Compute Jacobian Matrix
+#+begin_src matlab
+ stewart.J = [stewart.As' , cross(stewart.Ab, stewart.As)'];
+#+end_src
+
+** Compute Stiffness Matrix
+#+begin_src matlab
+ stewart.K = stewart.J'*diag(stewart.Ki)*stewart.J;
+#+end_src
+
+** Compute Compliance Matrix
+#+begin_src matlab
+ stewart.C = inv(stewart.K);
+#+end_src
+
+* Initialize the Geometry of the Mechanical Elements
+** =initializeCylindricalPlatforms=: Initialize the geometry of the Fixed and Mobile Platforms
+:PROPERTIES:
+:header-args:matlab+: :tangle src/initializeCylindricalPlatforms.m
+:header-args:matlab+: :comments none :mkdirp yes :eval no
+:END:
+<>
+
+This Matlab function is accessible [[file:src/initializeCylindricalPlatforms.m][here]].
+
+*** Function description
+#+begin_src matlab
+ function [stewart] = initializeCylindricalPlatforms(stewart, args)
+ % initializeCylindricalPlatforms - Initialize the geometry of the Fixed and Mobile Platforms
+ %
+ % Syntax: [stewart] = initializeCylindricalPlatforms(args)
+ %
+ % Inputs:
+ % - args - Structure with the following fields:
+ % - Fpm [1x1] - Fixed Platform Mass [kg]
+ % - Fph [1x1] - Fixed Platform Height [m]
+ % - Fpr [1x1] - Fixed Platform Radius [m]
+ % - Mpm [1x1] - Mobile Platform Mass [kg]
+ % - Mph [1x1] - Mobile Platform Height [m]
+ % - Mpr [1x1] - Mobile Platform Radius [m]
+ %
+ % Outputs:
+ % - stewart - updated Stewart structure with the added fields:
+ % - platforms [struct] - structure with the following fields:
+ % - Fpm [1x1] - Fixed Platform Mass [kg]
+ % - Msi [3x3] - Mobile Platform Inertia matrix [kg*m^2]
+ % - Fph [1x1] - Fixed Platform Height [m]
+ % - Fpr [1x1] - Fixed Platform Radius [m]
+ % - Mpm [1x1] - Mobile Platform Mass [kg]
+ % - Fsi [3x3] - Fixed Platform Inertia matrix [kg*m^2]
+ % - Mph [1x1] - Mobile Platform Height [m]
+ % - Mpr [1x1] - Mobile Platform Radius [m]
+#+end_src
+
+*** Optional Parameters
+#+begin_src matlab
+ arguments
+ stewart
+ args.Fpm (1,1) double {mustBeNumeric, mustBePositive} = 1
+ args.Fph (1,1) double {mustBeNumeric, mustBePositive} = 10e-3
+ args.Fpr (1,1) double {mustBeNumeric, mustBePositive} = 125e-3
+ args.Mpm (1,1) double {mustBeNumeric, mustBePositive} = 1
+ args.Mph (1,1) double {mustBeNumeric, mustBePositive} = 10e-3
+ args.Mpr (1,1) double {mustBeNumeric, mustBePositive} = 100e-3
+ end
+#+end_src
+
+*** Create the =platforms= struct
+#+begin_src matlab
+ platforms = struct();
+
+ platforms.Fpm = args.Fpm;
+ platforms.Fph = args.Fph;
+ platforms.Fpr = args.Fpr;
+ platforms.Fpi = diag([1/12 * platforms.Fpm * (3*platforms.Fpr^2 + platforms.Fph^2), ...
+ 1/12 * platforms.Fpm * (3*platforms.Fpr^2 + platforms.Fph^2), ...
+ 1/2 * platforms.Fpm * platforms.Fpr^2]);
+
+ platforms.Mpm = args.Mpm;
+ platforms.Mph = args.Mph;
+ platforms.Mpr = args.Mpr;
+ platforms.Mpi = diag([1/12 * platforms.Mpm * (3*platforms.Mpr^2 + platforms.Mph^2), ...
+ 1/12 * platforms.Mpm * (3*platforms.Mpr^2 + platforms.Mph^2), ...
+ 1/2 * platforms.Mpm * platforms.Mpr^2]);
+#+end_src
+
+*** Save the =platforms= struct
+#+begin_src matlab
+ stewart.platforms = platforms;
+#+end_src
+
+** =initializeCylindricalStruts=: Define the mass and moment of inertia of cylindrical struts
+:PROPERTIES:
+:header-args:matlab+: :tangle src/initializeCylindricalStruts.m
+:header-args:matlab+: :comments none :mkdirp yes :eval no
+:END:
+<>
+
+This Matlab function is accessible [[file:src/initializeCylindricalStruts.m][here]].
+
+*** Function description
+#+begin_src matlab
+ function [stewart] = initializeCylindricalStruts(stewart, args)
+ % initializeCylindricalStruts - Define the mass and moment of inertia of cylindrical struts
+ %
+ % Syntax: [stewart] = initializeCylindricalStruts(args)
+ %
+ % Inputs:
+ % - args - Structure with the following fields:
+ % - Fsm [1x1] - Mass of the Fixed part of the struts [kg]
+ % - Fsh [1x1] - Height of cylinder for the Fixed part of the struts [m]
+ % - Fsr [1x1] - Radius of cylinder for the Fixed part of the struts [m]
+ % - Msm [1x1] - Mass of the Mobile part of the struts [kg]
+ % - Msh [1x1] - Height of cylinder for the Mobile part of the struts [m]
+ % - Msr [1x1] - Radius of cylinder for the Mobile part of the struts [m]
+ %
+ % Outputs:
+ % - stewart - updated Stewart structure with the added fields:
+ % - struts [struct] - structure with the following fields:
+ % - Fsm [6x1] - Mass of the Fixed part of the struts [kg]
+ % - Fsi [3x3x6] - Moment of Inertia for the Fixed part of the struts [kg*m^2]
+ % - Msm [6x1] - Mass of the Mobile part of the struts [kg]
+ % - Msi [3x3x6] - Moment of Inertia for the Mobile part of the struts [kg*m^2]
+ % - Fsh [6x1] - Height of cylinder for the Fixed part of the struts [m]
+ % - Fsr [6x1] - Radius of cylinder for the Fixed part of the struts [m]
+ % - Msh [6x1] - Height of cylinder for the Mobile part of the struts [m]
+ % - Msr [6x1] - Radius of cylinder for the Mobile part of the struts [m]
+#+end_src
+
+*** Optional Parameters
+#+begin_src matlab
+ arguments
+ stewart
+ args.Fsm (1,1) double {mustBeNumeric, mustBePositive} = 0.1
+ args.Fsh (1,1) double {mustBeNumeric, mustBePositive} = 50e-3
+ args.Fsr (1,1) double {mustBeNumeric, mustBePositive} = 5e-3
+ args.Msm (1,1) double {mustBeNumeric, mustBePositive} = 0.1
+ args.Msh (1,1) double {mustBeNumeric, mustBePositive} = 50e-3
+ args.Msr (1,1) double {mustBeNumeric, mustBePositive} = 5e-3
+ end
+#+end_src
+
+*** Create the =struts= structure
+#+begin_src matlab
+ struts = struct();
+
+ struts.Fsm = ones(6,1).*args.Fsm;
+ struts.Msm = ones(6,1).*args.Msm;
+
+ struts.Fsh = ones(6,1).*args.Fsh;
+ struts.Fsr = ones(6,1).*args.Fsr;
+ struts.Msh = ones(6,1).*args.Msh;
+ struts.Msr = ones(6,1).*args.Msr;
+
+ struts.Fsi = zeros(3, 3, 6);
+ struts.Msi = zeros(3, 3, 6);
+ for i = 1:6
+ struts.Fsi(:,:,i) = diag([1/12 * struts.Fsm(i) * (3*struts.Fsr(i)^2 + struts.Fsh(i)^2), ...
+ 1/12 * struts.Fsm(i) * (3*struts.Fsr(i)^2 + struts.Fsh(i)^2), ...
+ 1/2 * struts.Fsm(i) * struts.Fsr(i)^2]);
+ struts.Msi(:,:,i) = diag([1/12 * struts.Msm(i) * (3*struts.Msr(i)^2 + struts.Msh(i)^2), ...
+ 1/12 * struts.Msm(i) * (3*struts.Msr(i)^2 + struts.Msh(i)^2), ...
+ 1/2 * struts.Msm(i) * struts.Msr(i)^2]);
+ end
+#+end_src
+
+#+begin_src matlab
+ stewart.struts = struts;
+#+end_src
+
+* =initializeStewartPose=: Determine the initial stroke in each leg to have the wanted pose
+:PROPERTIES:
+:header-args:matlab+: :tangle src/initializeStewartPose.m
+:header-args:matlab+: :comments none :mkdirp yes :eval no
+:END:
+<>
+
+This Matlab function is accessible [[file:src/initializeStewartPose.m][here]].
+
+** Function description
+#+begin_src matlab
+ function [stewart] = initializeStewartPose(stewart, args)
+ % initializeStewartPose - Determine the initial stroke in each leg to have the wanted pose
+ % It uses the inverse kinematic
+ %
+ % Syntax: [stewart] = initializeStewartPose(stewart, args)
+ %
+ % Inputs:
+ % - stewart - A structure with the following fields
+ % - Aa [3x6] - The positions ai expressed in {A}
+ % - Bb [3x6] - The positions bi expressed in {B}
+ % - args - Can have the following fields:
+ % - AP [3x1] - The wanted position of {B} with respect to {A}
+ % - ARB [3x3] - The rotation matrix that gives the wanted orientation of {B} with respect to {A}
+ %
+ % Outputs:
+ % - stewart - updated Stewart structure with the added fields:
+ % - dLi[6x1] - The 6 needed displacement of the struts from the initial position in [m] to have the wanted pose of {B} w.r.t. {A}
+#+end_src
+
+** Optional Parameters
+#+begin_src matlab
+ arguments
+ stewart
+ args.AP (3,1) double {mustBeNumeric} = zeros(3,1)
+ args.ARB (3,3) double {mustBeNumeric} = eye(3)
+ end
+#+end_src
+
+** Use the Inverse Kinematic function
+#+begin_src matlab
+ [Li, dLi] = inverseKinematics(stewart, 'AP', args.AP, 'ARB', args.ARB);
+
+ stewart.dLi = dLi;
+#+end_src
+
+* Utility Functions
+** =inverseKinematics=: Compute Inverse Kinematics
+:PROPERTIES:
+:header-args:matlab+: :tangle src/inverseKinematics.m
+:header-args:matlab+: :comments none :mkdirp yes :eval no
+:END:
+<>
+
+This Matlab function is accessible [[file:src/inverseKinematics.m][here]].
+
+*** Function description
+#+begin_src matlab
+ function [Li, dLi] = inverseKinematics(stewart, args)
+ % inverseKinematics - Compute the needed length of each strut to have the wanted position and orientation of {B} with respect to {A}
+ %
+ % Syntax: [stewart] = inverseKinematics(stewart)
+ %
+ % Inputs:
+ % - stewart - A structure with the following fields
+ % - Aa [3x6] - The positions ai expressed in {A}
+ % - Bb [3x6] - The positions bi expressed in {B}
+ % - args - Can have the following fields:
+ % - AP [3x1] - The wanted position of {B} with respect to {A}
+ % - ARB [3x3] - The rotation matrix that gives the wanted orientation of {B} with respect to {A}
+ %
+ % Outputs:
+ % - Li [6x1] - The 6 needed length of the struts in [m] to have the wanted pose of {B} w.r.t. {A}
+ % - dLi [6x1] - The 6 needed displacement of the struts from the initial position in [m] to have the wanted pose of {B} w.r.t. {A}
+#+end_src
+
+*** Optional Parameters
+#+begin_src matlab
+ arguments
+ stewart
+ args.AP (3,1) double {mustBeNumeric} = zeros(3,1)
+ args.ARB (3,3) double {mustBeNumeric} = eye(3)
+ end
+#+end_src
+
+*** Theory
+For inverse kinematic analysis, it is assumed that the position ${}^A\bm{P}$ and orientation of the moving platform ${}^A\bm{R}_B$ are given and the problem is to obtain the joint variables, namely, $\bm{L} = [l_1, l_2, \dots, l_6]^T$.
+
+From the geometry of the manipulator, the loop closure for each limb, $i = 1, 2, \dots, 6$ can be written as
+\begin{align*}
+ l_i {}^A\hat{\bm{s}}_i &= {}^A\bm{A} + {}^A\bm{b}_i - {}^A\bm{a}_i \\
+ &= {}^A\bm{A} + {}^A\bm{R}_b {}^B\bm{b}_i - {}^A\bm{a}_i
+\end{align*}
+
+To obtain the length of each actuator and eliminate $\hat{\bm{s}}_i$, it is sufficient to dot multiply each side by itself:
+\begin{equation}
+ l_i^2 \left[ {}^A\hat{\bm{s}}_i^T {}^A\hat{\bm{s}}_i \right] = \left[ {}^A\bm{P} + {}^A\bm{R}_B {}^B\bm{b}_i - {}^A\bm{a}_i \right]^T \left[ {}^A\bm{P} + {}^A\bm{R}_B {}^B\bm{b}_i - {}^A\bm{a}_i \right]
+\end{equation}
+
+Hence, for $i = 1, 2, \dots, 6$, each limb length can be uniquely determined by:
+\begin{equation}
+ l_i = \sqrt{{}^A\bm{P}^T {}^A\bm{P} + {}^B\bm{b}_i^T {}^B\bm{b}_i + {}^A\bm{a}_i^T {}^A\bm{a}_i - 2 {}^A\bm{P}^T {}^A\bm{a}_i + 2 {}^A\bm{P}^T \left[{}^A\bm{R}_B {}^B\bm{b}_i\right] - 2 \left[{}^A\bm{R}_B {}^B\bm{b}_i\right]^T {}^A\bm{a}_i}
+\end{equation}
+
+If the position and orientation of the moving platform lie in the feasible workspace of the manipulator, one unique solution to the limb length is determined by the above equation.
+Otherwise, when the limbs' lengths derived yield complex numbers, then the position or orientation of the moving platform is not reachable.
+
+*** Compute
+#+begin_src matlab
+ Li = sqrt(args.AP'*args.AP + diag(stewart.Bb'*stewart.Bb) + diag(stewart.Aa'*stewart.Aa) - (2*args.AP'*stewart.Aa)' + (2*args.AP'*(args.ARB*stewart.Bb))' - diag(2*(args.ARB*stewart.Bb)'*stewart.Aa));
+#+end_src
+
+#+begin_src matlab
+ dLi = Li-stewart.l;
+#+end_src
+
+** =forwardKinematicsApprox=: Compute the Forward Kinematics
+:PROPERTIES:
+:header-args:matlab+: :tangle src/forwardKinematicsApprox.m
+:header-args:matlab+: :comments none :mkdirp yes :eval no
+:END:
+<>
+
+This Matlab function is accessible [[file:src/forwardKinematicsApprox.m][here]].
+
+*** Function description
+#+begin_src matlab
+ function [P, R] = forwardKinematicsApprox(stewart, args)
+ % forwardKinematicsApprox - Computed the approximate pose of {B} with respect to {A} from the length of each strut and using
+ % the Jacobian Matrix
+ %
+ % Syntax: [P, R] = forwardKinematicsApprox(stewart, args)
+ %
+ % Inputs:
+ % - stewart - A structure with the following fields
+ % - J [6x6] - The Jacobian Matrix
+ % - args - Can have the following fields:
+ % - dL [6x1] - Displacement of each strut [m]
+ %
+ % Outputs:
+ % - P [3x1] - The estimated position of {B} with respect to {A}
+ % - R [3x3] - The estimated rotation matrix that gives the orientation of {B} with respect to {A}
+#+end_src
+
+*** Optional Parameters
+#+begin_src matlab
+ arguments
+ stewart
+ args.dL (6,1) double {mustBeNumeric} = zeros(6,1)
+ end
+#+end_src
+
+*** Computation
+From a small displacement of each strut $d\bm{\mathcal{L}}$, we can compute the
+position and orientation of {B} with respect to {A} using the following formula:
+\[ d \bm{\mathcal{X}} = \bm{J}^{-1} d\bm{\mathcal{L}} \]
+#+begin_src matlab
+ X = stewart.J\args.dL;
+#+end_src
+
+The position vector corresponds to the first 3 elements.
+#+begin_src matlab
+ P = X(1:3);
+#+end_src
+
+The next 3 elements are the orientation of {B} with respect to {A} expressed
+using the screw axis.
+#+begin_src matlab
+ theta = norm(X(4:6));
+ s = X(4:6)/theta;
+#+end_src
+
+We then compute the corresponding rotation matrix.
+#+begin_src matlab
+ R = [s(1)^2*(1-cos(theta)) + cos(theta) , s(1)*s(2)*(1-cos(theta)) - s(3)*sin(theta), s(1)*s(3)*(1-cos(theta)) + s(2)*sin(theta);
+ s(2)*s(1)*(1-cos(theta)) + s(3)*sin(theta), s(2)^2*(1-cos(theta)) + cos(theta), s(2)*s(3)*(1-cos(theta)) - s(1)*sin(theta);
+ s(3)*s(1)*(1-cos(theta)) - s(2)*sin(theta), s(3)*s(2)*(1-cos(theta)) + s(1)*sin(theta), s(3)^2*(1-cos(theta)) + cos(theta)];
+#+end_src
+
+* Other Elements
+** Z-Axis Geophone
+:PROPERTIES:
+:header-args:matlab+: :tangle ./src/initializeZAxisGeophone.m
+:header-args:matlab+: :comments none :mkdirp yes :eval no
+:END:
+<>
+
+This Matlab function is accessible [[file:../src/initializeZAxisGeophone.m][here]].
+
+#+begin_src matlab
+ function [geophone] = initializeZAxisGeophone(args)
+ arguments
+ args.mass (1,1) double {mustBeNumeric, mustBePositive} = 1e-3 % [kg]
+ args.freq (1,1) double {mustBeNumeric, mustBePositive} = 1 % [Hz]
+ end
+
+ %%
+ geophone.m = args.mass;
+
+ %% The Stiffness is set to have the damping resonance frequency
+ geophone.k = geophone.m * (2*pi*args.freq)^2;
+
+ %% We set the damping value to have critical damping
+ geophone.c = 2*sqrt(geophone.m * geophone.k);
+
+ %% Save
+ save('./mat/geophone_z_axis.mat', 'geophone');
+ end
+#+end_src
+
+** Z-Axis Accelerometer
+:PROPERTIES:
+:header-args:matlab+: :tangle ./src/initializeZAxisAccelerometer.m
+:header-args:matlab+: :comments none :mkdirp yes :eval no
+:END:
+<>
+
+This Matlab function is accessible [[file:../src/initializeZAxisAccelerometer.m][here]].
+
+#+begin_src matlab
+ function [accelerometer] = initializeZAxisAccelerometer(args)
+ arguments
+ args.mass (1,1) double {mustBeNumeric, mustBePositive} = 1e-3 % [kg]
+ args.freq (1,1) double {mustBeNumeric, mustBePositive} = 5e3 % [Hz]
+ end
+
+ %%
+ accelerometer.m = args.mass;
+
+ %% The Stiffness is set to have the damping resonance frequency
+ accelerometer.k = accelerometer.m * (2*pi*args.freq)^2;
+
+ %% We set the damping value to have critical damping
+ accelerometer.c = 2*sqrt(accelerometer.m * accelerometer.k);
+
+ %% Gain correction of the accelerometer to have a unity gain until the resonance
+ accelerometer.gain = -accelerometer.k/accelerometer.m;
+
+ %% Save
+ save('./mat/accelerometer_z_axis.mat', 'accelerometer');
+ end
+#+end_src
+
+* OLD :noexport:
+** Define the Height of the Platform :noexport:
+#+begin_src matlab
+ %% 1. Height of the platform. Location of {F} and {M}
+ H = 90e-3; % [m]
+ FO_M = [0; 0; H];
+#+end_src
+
+** Define the location of {A} and {B} :noexport:
+#+begin_src matlab
+ %% 2. Location of {A} and {B}
+ FO_A = [0; 0; 100e-3] + FO_M;% [m,m,m]
+ MO_B = [0; 0; 100e-3];% [m,m,m]
+#+end_src
+
+** Define the position of $a_{i}$ and $b_{i}$ :noexport:
+#+begin_src matlab
+ %% 3. Position of ai and bi
+ Fa = zeros(3, 6); % Fa_i is the i'th vector of Fa
+ Mb = zeros(3, 6); % Mb_i is the i'th vector of Mb
+#+end_src
+
+#+begin_src matlab
+ Aa = Fa - repmat(FO_A, [1, 6]);
+ Bb = Mb - repmat(MO_B, [1, 6]);
+
+ Ab = Bb - repmat(-MO_B-FO_M+FO_A, [1, 6]);
+ Ba = Aa - repmat( MO_B+FO_M-FO_A, [1, 6]);
+
+ As = (Ab - Aa)./vecnorm(Ab - Aa); % As_i is the i'th vector of As
+ l = vecnorm(Ab - Aa);
+
+ Bs = (Bb - Ba)./vecnorm(Bb - Ba);
+
+ FRa = zeros(3,3,6);
+ MRb = zeros(3,3,6);
+
+ for i = 1:6
+ FRa(:,:,i) = [cross([0;1;0],As(:,i)) , cross(As(:,i), cross([0;1;0], As(:,i))) , As(:,i)];
+ FRa(:,:,i) = FRa(:,:,i)./vecnorm(FRa(:,:,i));
+
+ MRb(:,:,i) = [cross([0;1;0],Bs(:,i)) , cross(Bs(:,i), cross([0;1;0], Bs(:,i))) , Bs(:,i)];
+ MRb(:,:,i) = MRb(:,:,i)./vecnorm(MRb(:,:,i));
+ end
+#+end_src
+
+** Define the dynamical properties of each strut :noexport:
+#+begin_src matlab
+ %% 4. Stiffness and Damping of each strut
+ Ki = 1e6*ones(6,1);
+ Ci = 1e2*ones(6,1);
+#+end_src
+
+** Old Introduction :noexport:
+First, geometrical parameters are defined:
+- ${}^A\bm{a}_i$ - Position of the joints fixed to the fixed base w.r.t $\{A\}$
+- ${}^A\bm{b}_i$ - Position of the joints fixed to the mobile platform w.r.t $\{A\}$
+- ${}^B\bm{b}_i$ - Position of the joints fixed to the mobile platform w.r.t $\{B\}$
+- $H$ - Total height of the mobile platform
+
+These parameter are enough to determine all the kinematic properties of the platform like the Jacobian, stroke, stiffness, ...
+These geometrical parameters can be generated using different functions: =initializeCubicConfiguration= for cubic configuration or =initializeGeneralConfiguration= for more general configuration.
+
+A function =computeGeometricalProperties= is then used to compute:
+- $\bm{J}_f$ - Jacobian matrix for the force location
+- $\bm{J}_d$ - Jacobian matrix for displacement estimation
+- $\bm{R}_m$ - Rotation matrices to position the leg vectors
+
+Then, geometrical parameters are computed for all the mechanical elements with the function =initializeMechanicalElements=:
+- Shape of the platforms
+ - External Radius
+ - Internal Radius
+ - Density
+ - Thickness
+- Shape of the Legs
+ - Radius
+ - Size of ball joint
+ - Density
+
+Other Parameters are defined for the Simscape simulation:
+- Sample mass, volume and position (=initializeSample= function)
+- Location of the inertial sensor
+- Location of the point for the differential measurements
+- Location of the Jacobian point for velocity/displacement computation
+
+** Cubic Configuration :noexport:
+To define the cubic configuration, we need to define 4 parameters:
+- The size of the cube
+- The location of the cube
+- The position of the plane joint the points $a_{i}$
+- The position of the plane joint the points $b_{i}$
+
+To do so, we specify the following parameters:
+- $H_{C}$ the height of the useful part of the cube
+- ${}^{F}O_{C}$ the position of the center of the cube with respect to $\{F\}$
+- ${}^{F}H_{A}$: the height of the plane joining the points $a_{i}$ with respect to the frame $\{F\}$
+- ${}^{M}H_{B}$: the height of the plane joining the points $b_{i}$ with respect to the frame $\{M\}$
+
+We define the parameters
+#+begin_src matlab
+ Hc = 60e-3; % [m]
+ FOc = 50e-3; % [m]
+ FHa = 15e-3; % [m]
+ MHb = 15e-3; % [m]
+#+end_src
+
+We define the useful points of the cube with respect to the Cube's center.
+${}^{C}C$ are the 6 vertices of the cubes expressed in a frame {C} which is located at the center of the cube and aligned with {F} and {M}.
+#+begin_src matlab
+ sx = [ 2; -1; -1];
+ sy = [ 0; 1; -1];
+ sz = [ 1; 1; 1];
+
+ R = [sx, sy, sz]./vecnorm([sx, sy, sz]);
+
+ L = Hc*sqrt(3);
+
+ Cc = R'*[[0;0;L],[L;0;L],[L;0;0],[L;L;0],[0;L;0],[0;L;L]] - [0;0;1.5*Hc];
+
+ CCf = [Cc(:,1), Cc(:,3), Cc(:,3), Cc(:,5), Cc(:,5), Cc(:,1)]; % CCf(:,i) corresponds to the bottom cube's vertice corresponding to the i'th leg
+ CCm = [Cc(:,2), Cc(:,2), Cc(:,4), Cc(:,4), Cc(:,6), Cc(:,6)]; % CCm(:,i) corresponds to the top cube's vertice corresponding to the i'th leg
+#+end_src
+
+We can compute the vector of each leg ${}^{C}\hat{\bm{s}}_{i}$ (unit vector from ${}^{C}C_{f}$ to ${}^{C}C_{m}$).
+#+begin_src matlab
+ CSi = (CCm - CCf)./vecnorm(CCm - CCf);
+#+end_src
+
+We now which to compute the position of the joints $a_{i}$ and $b_{i}$.
+#+begin_src matlab
+ Fa = zeros(3, 6); % Fa_i is the i'th vector of Fa
+ Mb = zeros(3, 6); % Mb_i is the i'th vector of Mb
+#+end_src
+
+#+begin_src matlab
+ Fa = CCf + [0; 0; FOc] + ((FHa-(FOc-Hc/2))./CSi(3,:)).*CSi;
+ Mb = CCf + [0; 0; FOc-H] + ((H-MHb-(FOc-Hc/2))./CSi(3,:)).*CSi; % TODO
+#+end_src
+
+** initializeGeneralConfiguration :noexport:
+:PROPERTIES:
+:HEADER-ARGS:matlab+: :exports code
+:HEADER-ARGS:matlab+: :comments no
+:HEADER-ARGS:matlab+: :eval no
+:HEADER-ARGS:matlab+: :tangle src/initializeGeneralConfiguration.m
+:END:
+
+*** Function description
+The =initializeGeneralConfiguration= function takes one structure that contains configurations for the hexapod and returns one structure representing the Hexapod.
+
+#+begin_src matlab
+ function [stewart] = initializeGeneralConfiguration(opts_param)
+#+end_src
+
+*** Optional Parameters
+Default values for opts.
+#+begin_src matlab
+ opts = struct(...
+ 'H_tot', 90, ... % Height of the platform [mm]
+ 'H_joint', 15, ... % Height of the joints [mm]
+ 'H_plate', 10, ... % Thickness of the fixed and mobile platforms [mm]
+ 'R_bot', 100, ... % Radius where the legs articulations are positionned [mm]
+ 'R_top', 80, ... % Radius where the legs articulations are positionned [mm]
+ 'a_bot', 10, ... % Angle Offset [deg]
+ 'a_top', 40, ... % Angle Offset [deg]
+ 'da_top', 0 ... % Angle Offset from 0 position [deg]
+ );
+#+end_src
+
+Populate opts with input parameters
+#+begin_src matlab
+ if exist('opts_param','var')
+ for opt = fieldnames(opts_param)'
+ opts.(opt{1}) = opts_param.(opt{1});
+ end
+ end
+#+end_src
+
+*** Geometry Description
+#+name: fig:stewart_bottom_plate
+#+caption: Schematic of the bottom plates with all the parameters
+[[file:./figs/stewart_bottom_plate.png]]
+
+*** Compute Aa and Ab
+We compute $[a_1, a_2, a_3, a_4, a_5, a_6]^T$ and $[b_1, b_2, b_3, b_4, b_5, b_6]^T$.
+
+#+begin_src matlab
+ Aa = zeros(6, 3); % [mm]
+ Ab = zeros(6, 3); % [mm]
+ Bb = zeros(6, 3); % [mm]
+#+end_src
+
+#+begin_src matlab
+ for i = 1:3
+ Aa(2*i-1,:) = [opts.R_bot*cos( pi/180*(120*(i-1) - opts.a_bot) ), ...
+ opts.R_bot*sin( pi/180*(120*(i-1) - opts.a_bot) ), ...
+ opts.H_plate+opts.H_joint];
+ Aa(2*i,:) = [opts.R_bot*cos( pi/180*(120*(i-1) + opts.a_bot) ), ...
+ opts.R_bot*sin( pi/180*(120*(i-1) + opts.a_bot) ), ...
+ opts.H_plate+opts.H_joint];
+
+ Ab(2*i-1,:) = [opts.R_top*cos( pi/180*(120*(i-1) + opts.da_top - opts.a_top) ), ...
+ opts.R_top*sin( pi/180*(120*(i-1) + opts.da_top - opts.a_top) ), ...
+ opts.H_tot - opts.H_plate - opts.H_joint];
+ Ab(2*i,:) = [opts.R_top*cos( pi/180*(120*(i-1) + opts.da_top + opts.a_top) ), ...
+ opts.R_top*sin( pi/180*(120*(i-1) + opts.da_top + opts.a_top) ), ...
+ opts.H_tot - opts.H_plate - opts.H_joint];
+ end
+
+ Bb = Ab - opts.H_tot*[0,0,1];
+#+end_src
+
+*** Returns Stewart Structure
+#+begin_src matlab :results none
+ stewart = struct();
+ stewart.Aa = Aa;
+ stewart.Ab = Ab;
+ stewart.Bb = Bb;
+ stewart.H_tot = opts.H_tot;
+end
+#+end_src
+
+** initializeCubicConfiguration :noexport:
+:PROPERTIES:
+:HEADER-ARGS:matlab+: :exports code
+:HEADER-ARGS:matlab+: :comments no
+:HEADER-ARGS:matlab+: :eval no
+:HEADER-ARGS:matlab+: :tangle src/initializeCubicConfiguration.m
+:END:
+<>
+
+*** Function description
+#+begin_src matlab
+ function [stewart] = initializeCubicConfiguration(opts_param)
+#+end_src
+
+*** Optional Parameters
+Default values for opts.
+#+begin_src matlab
+ opts = struct(...
+ 'H_tot', 90, ... % Total height of the Hexapod [mm]
+ 'L', 110, ... % Size of the Cube [mm]
+ 'H', 40, ... % Height between base joints and platform joints [mm]
+ 'H0', 75 ... % Height between the corner of the cube and the plane containing the base joints [mm]
+ );
+#+end_src
+
+Populate opts with input parameters
+#+begin_src matlab
+ if exist('opts_param','var')
+ for opt = fieldnames(opts_param)'
+ opts.(opt{1}) = opts_param.(opt{1});
+ end
+ end
+#+end_src
+
+*** Cube Creation
+#+begin_src matlab :results none
+ points = [0, 0, 0; ...
+ 0, 0, 1; ...
+ 0, 1, 0; ...
+ 0, 1, 1; ...
+ 1, 0, 0; ...
+ 1, 0, 1; ...
+ 1, 1, 0; ...
+ 1, 1, 1];
+ points = opts.L*points;
+#+end_src
+
+We create the rotation matrix to rotate the cube
+#+begin_src matlab :results none
+ sx = cross([1, 1, 1], [1 0 0]);
+ sx = sx/norm(sx);
+
+ sy = -cross(sx, [1, 1, 1]);
+ sy = sy/norm(sy);
+
+ sz = [1, 1, 1];
+ sz = sz/norm(sz);
+
+ R = [sx', sy', sz']';
+#+end_src
+
+We use to rotation matrix to rotate the cube
+#+begin_src matlab :results none
+ cube = zeros(size(points));
+ for i = 1:size(points, 1)
+ cube(i, :) = R * points(i, :)';
+ end
+#+end_src
+
+*** Vectors of each leg
+#+begin_src matlab :results none
+ leg_indices = [3, 4; ...
+ 2, 4; ...
+ 2, 6; ...
+ 5, 6; ...
+ 5, 7; ...
+ 3, 7];
+#+end_src
+
+Vectors are:
+#+begin_src matlab :results none
+ legs = zeros(6, 3);
+ legs_start = zeros(6, 3);
+
+ for i = 1:6
+ legs(i, :) = cube(leg_indices(i, 2), :) - cube(leg_indices(i, 1), :);
+ legs_start(i, :) = cube(leg_indices(i, 1), :);
+ end
+#+end_src
+
+*** Verification of Height of the Stewart Platform
+If the Stewart platform is not contained in the cube, throw an error.
+
+#+begin_src matlab :results none
+ Hmax = cube(4, 3) - cube(2, 3);
+ if opts.H0 < cube(2, 3)
+ error(sprintf('H0 is not high enought. Minimum H0 = %.1f', cube(2, 3)));
+ else if opts.H0 + opts.H > cube(4, 3)
+ error(sprintf('H0+H is too high. Maximum H0+H = %.1f', cube(4, 3)));
+ error('H0+H is too high');
+ end
+#+end_src
+
+*** Determinate the location of the joints
+We now determine the location of the joints on the fixed platform w.r.t the fixed frame $\{A\}$.
+$\{A\}$ is fixed to the bottom of the base.
+#+begin_src matlab :results none
+ Aa = zeros(6, 3);
+ for i = 1:6
+ t = (opts.H0-legs_start(i, 3))/(legs(i, 3));
+ Aa(i, :) = legs_start(i, :) + t*legs(i, :);
+ end
+#+end_src
+
+And the location of the joints on the mobile platform with respect to $\{A\}$.
+#+begin_src matlab :results none
+ Ab = zeros(6, 3);
+ for i = 1:6
+ t = (opts.H0+opts.H-legs_start(i, 3))/(legs(i, 3));
+ Ab(i, :) = legs_start(i, :) + t*legs(i, :);
+ end
+#+end_src
+
+And the location of the joints on the mobile platform with respect to $\{B\}$.
+#+begin_src matlab :results none
+ Bb = zeros(6, 3);
+ Bb = Ab - (opts.H0 + opts.H_tot/2 + opts.H/2)*[0, 0, 1];
+#+end_src
+
+#+begin_src matlab :results none
+ h = opts.H0 + opts.H/2 - opts.H_tot/2;
+ Aa = Aa - h*[0, 0, 1];
+ Ab = Ab - h*[0, 0, 1];
+#+end_src
+
+*** Returns Stewart Structure
+#+begin_src matlab :results none
+ stewart = struct();
+ stewart.Aa = Aa;
+ stewart.Ab = Ab;
+ stewart.Bb = Bb;
+ stewart.H_tot = opts.H_tot;
+end
+#+end_src
+
+** computeGeometricalProperties :noexport:
+:PROPERTIES:
+:HEADER-ARGS:matlab+: :exports code
+:HEADER-ARGS:matlab+: :comments no
+:HEADER-ARGS:matlab+: :eval no
+:HEADER-ARGS:matlab+: :tangle src/computeGeometricalProperties.m
+:END:
+
+*** Function description
+#+begin_src matlab
+ function [stewart] = computeGeometricalProperties(stewart, opts_param)
+#+end_src
+
+*** Optional Parameters
+Default values for opts.
+#+begin_src matlab
+ opts = struct(...
+ 'Jd_pos', [0, 0, 30], ... % Position of the Jacobian for displacement estimation from the top of the mobile platform [mm]
+ 'Jf_pos', [0, 0, 30] ... % Position of the Jacobian for force location from the top of the mobile platform [mm]
+ );
+#+end_src
+
+Populate opts with input parameters
+#+begin_src matlab
+ if exist('opts_param','var')
+ for opt = fieldnames(opts_param)'
+ opts.(opt{1}) = opts_param.(opt{1});
+ end
+ end
+#+end_src
+
+*** Rotation matrices
+We initialize $l_i$ and $\hat{s}_i$
+#+begin_src matlab
+ leg_length = zeros(6, 1); % [mm]
+ leg_vectors = zeros(6, 3);
+#+end_src
+
+We compute $b_i - a_i$, and then:
+\begin{align*}
+ l_i &= \left|b_i - a_i\right| \\
+ \hat{s}_i &= \frac{b_i - a_i}{l_i}
+\end{align*}
+
+#+begin_src matlab
+ legs = stewart.Ab - stewart.Aa;
+
+ for i = 1:6
+ leg_length(i) = norm(legs(i,:));
+ leg_vectors(i,:) = legs(i,:) / leg_length(i);
+ end
+#+end_src
+
+We compute rotation matrices to have the orientation of the legs.
+The rotation matrix transforms the $z$ axis to the axis of the leg. The other axis are not important here.
+#+begin_src matlab
+ stewart.Rm = struct('R', eye(3));
+
+ for i = 1:6
+ sx = cross(leg_vectors(i,:), [1 0 0]);
+ sx = sx/norm(sx);
+
+ sy = -cross(sx, leg_vectors(i,:));
+ sy = sy/norm(sy);
+
+ sz = leg_vectors(i,:);
+ sz = sz/norm(sz);
+
+ stewart.Rm(i).R = [sx', sy', sz'];
+ end
+#+end_src
+
+*** Jacobian matrices
+Compute Jacobian Matrix
+#+begin_src matlab
+ Jd = zeros(6);
+
+ for i = 1:6
+ Jd(i, 1:3) = leg_vectors(i, :);
+ Jd(i, 4:6) = cross(0.001*(stewart.Bb(i, :) - opts.Jd_pos), leg_vectors(i, :));
+ end
+
+ stewart.Jd = Jd;
+ stewart.Jd_inv = inv(Jd);
+#+end_src
+
+#+begin_src matlab
+ Jf = zeros(6);
+
+ for i = 1:6
+ Jf(i, 1:3) = leg_vectors(i, :);
+ Jf(i, 4:6) = cross(0.001*(stewart.Bb(i, :) - opts.Jf_pos), leg_vectors(i, :));
+ end
+
+ stewart.Jf = Jf;
+ stewart.Jf_inv = inv(Jf);
+#+end_src
+
+#+begin_src matlab
+ end
+#+end_src
+
+** initializeMechanicalElements :noexport:
+:PROPERTIES:
+:HEADER-ARGS:matlab+: :exports code
+:HEADER-ARGS:matlab+: :comments no
+:HEADER-ARGS:matlab+: :eval no
+:HEADER-ARGS:matlab+: :tangle src/initializeMechanicalElements.m
+:END:
+
+*** Function description
+#+begin_src matlab
+ function [stewart] = initializeMechanicalElements(stewart, opts_param)
+#+end_src
+
+*** Optional Parameters
+Default values for opts.
+#+begin_src matlab
+ opts = struct(...
+ 'thickness', 10, ... % Thickness of the base and platform [mm]
+ 'density', 1000, ... % Density of the material used for the hexapod [kg/m3]
+ 'k_ax', 1e8, ... % Stiffness of each actuator [N/m]
+ 'c_ax', 1000, ... % Damping of each actuator [N/(m/s)]
+ 'stroke', 50e-6 ... % Maximum stroke of each actuator [m]
+ );
+#+end_src
+
+Populate opts with input parameters
+#+begin_src matlab
+ if exist('opts_param','var')
+ for opt = fieldnames(opts_param)'
+ opts.(opt{1}) = opts_param.(opt{1});
+ end
+ end
+#+end_src
+
+*** Bottom Plate
+#+name: fig:stewart_bottom_plate
+#+caption: Schematic of the bottom plates with all the parameters
+[[file:./figs/stewart_bottom_plate.png]]
+
+The bottom plate structure is initialized.
+#+begin_src matlab
+ BP = struct();
+#+end_src
+
+We defined its internal radius (if there is a hole in the bottom plate) and its outer radius.
+#+begin_src matlab
+ BP.Rint = 0; % Internal Radius [mm]
+ BP.Rext = 150; % External Radius [mm]
+#+end_src
+
+We define its thickness.
+#+begin_src matlab
+ BP.H = opts.thickness; % Thickness of the Bottom Plate [mm]
+#+end_src
+
+We defined the density of the material of the bottom plate.
+#+begin_src matlab
+ BP.density = opts.density; % Density of the material [kg/m3]
+#+end_src
+
+And its color.
+#+begin_src matlab
+ BP.color = [0.7 0.7 0.7]; % Color [RGB]
+#+end_src
+
+Then the profile of the bottom plate is computed and will be used by Simscape
+#+begin_src matlab
+ BP.shape = [BP.Rint BP.H; BP.Rint 0; BP.Rext 0; BP.Rext BP.H]; % [mm]
+#+end_src
+
+The structure is added to the stewart structure
+#+begin_src matlab
+ stewart.BP = BP;
+#+end_src
+
+*** Top Plate
+The top plate structure is initialized.
+#+begin_src matlab
+ TP = struct();
+#+end_src
+
+We defined the internal and external radius of the top plate.
+#+begin_src matlab
+ TP.Rint = 0; % [mm]
+ TP.Rext = 100; % [mm]
+#+end_src
+
+The thickness of the top plate.
+#+begin_src matlab
+ TP.H = 10; % [mm]
+#+end_src
+
+The density of its material.
+#+begin_src matlab
+ TP.density = opts.density; % Density of the material [kg/m3]
+#+end_src
+
+Its color.
+#+begin_src matlab
+ TP.color = [0.7 0.7 0.7]; % Color [RGB]
+#+end_src
+
+Then the shape of the top plate is computed
+#+begin_src matlab
+ TP.shape = [TP.Rint TP.H; TP.Rint 0; TP.Rext 0; TP.Rext TP.H];
+#+end_src
+
+The structure is added to the stewart structure
+#+begin_src matlab
+ stewart.TP = TP;
+#+end_src
+
+*** Legs
+#+name: fig:stewart_legs
+#+caption: Schematic for the legs of the Stewart platform
+[[file:./figs/stewart_legs.png]]
+
+The leg structure is initialized.
+#+begin_src matlab
+ Leg = struct();
+#+end_src
+
+The maximum Stroke of each leg is defined.
+#+begin_src matlab
+ Leg.stroke = opts.stroke; % [m]
+#+end_src
+
+The stiffness and damping of each leg are defined
+#+begin_src matlab
+ Leg.k_ax = opts.k_ax; % Stiffness of each leg [N/m]
+ Leg.c_ax = opts.c_ax; % Damping of each leg [N/(m/s)]
+#+end_src
+
+The radius of the legs are defined
+#+begin_src matlab
+ Leg.Rtop = 10; % Radius of the cylinder of the top part of the leg[mm]
+ Leg.Rbot = 12; % Radius of the cylinder of the bottom part of the leg [mm]
+#+end_src
+
+The density of its material.
+#+begin_src matlab
+ Leg.density = opts.density; % Density of the material used for the legs [kg/m3]
+#+end_src
+
+Its color.
+#+begin_src matlab
+ Leg.color = [0.5 0.5 0.5]; % Color of the top part of the leg [RGB]
+#+end_src
+
+The radius of spheres representing the ball joints are defined.
+#+begin_src matlab
+ Leg.R = 1.3*Leg.Rbot; % Size of the sphere at the extremity of the leg [mm]
+#+end_src
+
+We estimate the length of the legs.
+#+begin_src matlab
+ legs = stewart.Ab - stewart.Aa;
+ Leg.lenght = norm(legs(1,:))/1.5;
+#+end_src
+
+Then the shape of the bottom leg is estimated
+#+begin_src matlab
+ Leg.shape.bot = ...
+ [0 0; ...
+ Leg.Rbot 0; ...
+ Leg.Rbot Leg.lenght; ...
+ Leg.Rtop Leg.lenght; ...
+ Leg.Rtop 0.2*Leg.lenght; ...
+ 0 0.2*Leg.lenght];
+#+end_src
+
+The structure is added to the stewart structure
+#+begin_src matlab
+ stewart.Leg = Leg;
+#+end_src
+
+*** Ball Joints
+#+name: fig:stewart_ball_joints
+#+caption: Schematic of the support for the ball joints
+[[file:./figs/stewart_ball_joints.png]]
+
+=SP= is the structure representing the support for the ball joints at the extremity of each leg.
+
+The =SP= structure is initialized.
+#+begin_src matlab
+ SP = struct();
+#+end_src
+
+We can define its rotational stiffness and damping. For now, we use perfect joints.
+#+begin_src matlab
+ SP.k = 0; % [N*m/deg]
+ SP.c = 0; % [N*m/deg]
+#+end_src
+
+Its height is defined
+#+begin_src matlab
+ SP.H = stewart.Aa(1, 3) - BP.H; % [mm]
+#+end_src
+
+Its radius is based on the radius on the sphere at the end of the legs.
+#+begin_src matlab
+ SP.R = Leg.R; % [mm]
+#+end_src
+
+#+begin_src matlab
+ SP.section = [0 SP.H-SP.R;
+ 0 0;
+ SP.R 0;
+ SP.R SP.H];
+#+end_src
+
+The density of its material is defined.
+#+begin_src matlab
+ SP.density = opts.density; % [kg/m^3]
+#+end_src
+
+Its color is defined.
+#+begin_src matlab
+ SP.color = [0.7 0.7 0.7]; % [RGB]
+#+end_src
+
+The structure is added to the Hexapod structure
+#+begin_src matlab
+ stewart.SP = SP;
+#+end_src
+
+** initializeSample :noexport:
+:PROPERTIES:
+:HEADER-ARGS:matlab+: :exports code
+:HEADER-ARGS:matlab+: :comments no
+:HEADER-ARGS:matlab+: :eval no
+:HEADER-ARGS:matlab+: :tangle src/initializeSample.m
+:END:
+
+*** Function description
+#+begin_src matlab
+ function [] = initializeSample(opts_param)
+#+end_src
+
+*** Optional Parameters
+Default values for opts.
+#+begin_src matlab
+ sample = struct( ...
+ 'radius', 100, ... % radius of the cylinder [mm]
+ 'height', 100, ... % height of the cylinder [mm]
+ 'mass', 10, ... % mass of the cylinder [kg]
+ 'measheight', 50, ... % measurement point z-offset [mm]
+ 'offset', [0, 0, 0], ... % offset position of the sample [mm]
+ 'color', [0.9 0.1 0.1] ...
+ );
+#+end_src
+
+Populate opts with input parameters
+#+begin_src matlab
+ if exist('opts_param','var')
+ for opt = fieldnames(opts_param)'
+ sample.(opt{1}) = opts_param.(opt{1});
+ end
+ end
+#+end_src
+
+*** Save the Sample structure
+#+begin_src matlab
+ save('./mat/sample.mat', 'sample');
+#+end_src
+
+#+begin_src matlab
+ end
+#+end_src