#+TITLE: Stewart Platform - Simscape Model :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 ** Simscape Model #+begin_src matlab open('stewart_platform.slx') #+end_src ** Test the functions #+begin_src matlab stewart = initializeFramesPositions(struct('H', 90e-3, 'MO_B', 50e-3)); stewart = generateCubicConfiguration(stewart, struct('Hc', 60e-3, 'FOc', 50e-3, 'FHa', 15e-3, 'MHb', 15e-3)); stewart = computeJointsPose(stewart); stewart = initializeStrutDynamics(stewart, struct('Ki', 1e6*ones(6,1), 'Ci', 1e2*ones(6,1))); #+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(opts_param) % initializeFramesPositions - Initialize the positions of frames {A}, {B}, {F} and {M} % % Syntax: [stewart] = initializeFramesPositions(H, MO_B) % % Inputs: % - opts_param - Structure with the following fields: % - H [1x1] - Total Height of the Stewart Platform [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 ** Optional Parameters Default values for opts. #+begin_src matlab opts = struct( ... 'H', 90e-3, ... % [m] 'MO_B', 50e-3 ... % [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 ** Initialize the Stewart structure #+begin_src matlab stewart = struct(); #+end_src ** Compute the position of each frame #+begin_src matlab stewart.H = opts.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; opts.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 * =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, opts_param) % generateCubicConfiguration - Generate a Cubic Configuration % % Syntax: [stewart] = generateCubicConfiguration(stewart, opts_param) % % Inputs: % - stewart - A structure with the following fields % - H [1x1] - Total height of the platform [m] % - opts_param - Structure with the following fields: % - Hc [1x1] - Height of the "useful" part of the cube [m] % - FOc [1x1] - Height of the center of the cute 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 ** Optional Parameters Default values for opts. #+begin_src matlab opts = struct( ... 'Hc', 60e-3, ... % [m] 'FOc', 50e-3, ... % [m] 'FHa', 15e-3, ... % [m] 'MHb', 15e-3 ... % [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 ** 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 = opts.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*opts.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; opts.FOc] + ((opts.FHa-(opts.FOc-opts.Hc/2))./CSi(3,:)).*CSi; stewart.Mb = CCf + [0; 0; opts.FOc-stewart.H] + ((stewart.H-opts.MHb-(opts.FOc-opts.Hc/2))./CSi(3,:)).*CSi; #+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, opts_param) % % Inputs: % - stewart - A structure with the following fields % - 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 ** 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, opts_param) % initializeStrutDynamics - Add Stiffness and Damping properties of each strut % % Syntax: [stewart] = initializeStrutDynamics(opts_param) % % Inputs: % - opts_param - 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 Default values for opts. #+begin_src matlab opts = struct( ... 'Ki', 1e6*ones(6,1), ... % [N/m] 'Ci', 1e2*ones(6,1) ... % [N/(m/s)] ); #+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 ** Add Stiffness and Damping properties of each strut #+begin_src matlab stewart.Ki = opts.Ki; stewart.Ci = opts.Ci; #+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