#+TITLE: Stewart Platform - Simscape Model
:DRAWER:
#+STARTUP: overview

#+LANGUAGE: en
#+EMAIL: dehaeze.thomas@gmail.com
#+AUTHOR: Dehaeze Thomas

#+HTML_LINK_HOME: ./index.html
#+HTML_LINK_UP: ./index.html

#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="./css/htmlize.css"/>
#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="./css/readtheorg.css"/>
#+HTML_HEAD: <script src="./js/jquery.min.js"></script>
#+HTML_HEAD: <script src="./js/bootstrap.min.js"></script>
#+HTML_HEAD: <script src="./js/jquery.stickytableheaders.min.js"></script>
#+HTML_HEAD: <script src="./js/readtheorg.js"></script>

#+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

#+PROPERTY: header-args:latex  :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/tikz/org/}{config.tex}")
#+PROPERTY: header-args:latex+ :imagemagick t :fit yes
#+PROPERTY: header-args:latex+ :iminoptions -scale 100% -density 150
#+PROPERTY: header-args:latex+ :imoutoptions -quality 100
#+PROPERTY: header-args:latex+ :results file raw replace
#+PROPERTY: header-args:latex+ :buffer no
#+PROPERTY: header-args:latex+ :eval no-export
#+PROPERTY: header-args:latex+ :exports results
#+PROPERTY: header-args:latex+ :mkdirp yes
#+PROPERTY: header-args:latex+ :output-dir figs
#+PROPERTY: header-args:latex+ :post pdf2svg(file=*this*, ext="png")
:END:

* Introduction                                                        :ignore:
In this document is explained how the Simscape model of the Stewart Platform is implemented.

It is divided in the following sections:
- section [[sec:simscape_parameters]]: is explained how the parameters of the Stewart platform are set for the Simscape model
- section [[sec:simulink_configuration]]: the Simulink configuration (solver, simulation time, ...) is shared among all the Simulink files. It is explain how this is done.
- section [[sec:subsystem_reference]]: All the elements (platforms, struts, sensors, ...) are saved in separate files and imported in Simulink files using "subsystem referenced".
- section [[sec:fixed_mobile_platforms]]: The simscape model for the fixed base and mobile platform are described in this section.
- section [[sec:struts]]: The simscape model for the Stewart platform struts is described in this section.

* Parameters used for the Simscape Model
<<sec:simscape_parameters>>
The Simscape Model of the Stewart Platform is working with the =stewart= structure generated using the functions described [[file:stewart-architecture.org][here]].

All the geometry and inertia of the mechanical elements are defined in the =stewart= structure.

By updating the =stewart= structure in the workspace, the Simscape model will be automatically updated.

Thus, nothing should be changed by hand inside the Simscape model.

The main advantage to have all the parameters defined in one structure (and not hard-coded in some simulink blocs) it that we can easily change the Stewart architecture/parameters in a Matlab script to perform some parametric study for instance.

* Simulation Configuration - Configuration reference
<<sec:simulink_configuration>>
As multiple simulink files will be used for simulation and tests, it is very useful to determine good simulation configuration that will be *shared* among all the simulink files.

This is done using something called "*Configuration Reference*" ([[https://fr.mathworks.com/help/simulink/ug/more-about-configuration-references.html][documentation]]).

Basically, the configuration is stored in a mat file =conf_simscape.mat= and then loaded in the workspace for it to be accessible to all the simulink models.
It is automatically loaded when the Simulink project is open. It can be loaded manually with the command:
#+begin_src matlab :eval no
  load('mat/conf_simscape.mat');
#+end_src

It is however possible to modify specific parameters just for one simulation using the =set_param= command:
#+begin_src matlab :eval no
  set_param(conf_simscape, 'StopTime', 1);
#+end_src

* Subsystem Reference
<<sec:subsystem_reference>>
Several Stewart platform models are used, for instance one is use to study the dynamics while the other is used to apply active damping techniques.

However, all the Simscape models share some subsystems using the *Subsystem Reference* Simulink block ([[https://fr.mathworks.com/help/simulink/ug/referenced-subsystem-1.html][documentation]]).

These shared subsystems are:
- =Fixed_Based.slx= - Fixed base of the Stewart Platform
- =Mobile_Platform.slx= - Mobile platform of the Stewart Platform
- =stewart_strut.slx= - One strut containing two spherical/universal joints, the actuator as well as the included sensors. A parameter =i= is initialized to determine what it the "number" of the strut.

These subsystems are referenced from another subsystem called =Stewart_Platform.slx= shown in figure [[fig:simscape_stewart_platform]], that basically connect them correctly.
This subsystem is then referenced in other simulink models for various purposes (control, analysis, simulation, ...).

#+name: fig:simscape_stewart_platform
#+caption: Simscape Subsystem of the Stewart platform. Encapsulate the Subsystems corresponding to the fixed base, mobile platform and all the struts.
[[file:figs/simscape_stewart_platform.png]]

* Subsystem - Fixed base and Mobile Platform
<<sec:fixed_mobile_platforms>>
Both the fixed base and the mobile platform simscape models share many similarities.

Their are both composed of:
- a solid body representing the platform
- 6 rigid transform blocks to go from the frame $\{F\}$ (resp. $\{M\}$) to the location of the joints.
  These rigid transform are using ${}^F\bm{a}_i$ (resp. ${}^M\bm{b}_i$) for the position of the joint and ${}^F\bm{R}_{a_i}$ (resp. ${}^M\bm{R}_{b_i}$) for the orientation of the joint.

As always, the parameters that define the geometry are taken from the =stewart= structure.

#+name: fig:simscape_fixed_base
#+caption: Simscape Model of the Fixed base
#+attr_html: :width 1000px
[[file:figs/simscape_fixed_base.png]]

#+name: fig:simscape_mobile_platform
#+caption: Simscape Model of the Mobile platform
#+attr_html: :width 800px
[[file:figs/simscape_mobile_platform.png]]

* Subsystem - Struts
<<sec:struts>>
For the Stewart platform, the 6 struts are identical.
Thus, all the struts used in the Stewart platform are referring to the same subsystem called =stewart_strut.slx= and shown in Figure [[fig:simscape_strut]].

This strut has the following structure:
- *Universal Joint* connected on the Fixed base
- *Prismatic Joint* for the actuator
- *Spherical Joint* connected on the Mobile platform

This configuration is called *UPS*.

The other common configuration *SPS* has the disadvantage of having additional passive degrees-of-freedom corresponding to the rotation of the strut around its main axis.
This is why the *UPS* configuration is used, but other configuration can be easily implemented.

#+name: fig:simscape_strut
#+caption: Simscape model of the Stewart platform's strut
#+attr_html: :width 800px
[[file:figs/simscape_strut.png]]

Several sensors are included in the strut that may or may not be used for control:
- Relative Displacement sensor: gives the relative displacement of the strut.
- Force sensor: measure the total force applied by the force actuator, the stiffness and damping forces in the direction of the strut.
- Inertial sensor: measure the absolute motion (velocity) of the top part of the strut in the direction of the strut.

There is two main types of inertial sensor that can be used to measure the absolute motion of the top part of the strut in the direction of the strut:
- a geophone that measures the absolute velocity above some frequency
- an accelerometer that measures the absolute acceleration below some frequency

Both inertial sensors are described bellow.

* Other Elements
** Payload
:PROPERTIES:
:header-args:matlab+: :tangle ../src/initializePayload.m
:header-args:matlab+: :comments none :mkdirp yes :eval no
:END:
<<sec:initializePayload>>

This Matlab function is accessible [[file:../src/initializePayload.m][here]].

*** Function description
:PROPERTIES:
:UNNUMBERED: t
:END:
#+begin_src matlab
  function [payload] = initializePayload(args)
  % initializePayload - Initialize the Payload that can then be used for simulations and analysis
  %
  % Syntax: [payload] = initializePayload(args)
  %
  % Inputs:
  %    - args - Structure with the following fields:
  %        - type - 'none', 'rigid', 'flexible', 'cartesian'
  %        - h [1x1] - Height of the CoM of the payload w.r.t {M} [m]
  %                    This also the position where K and C are defined
  %        - K [6x1] - Stiffness of the Payload [N/m, N/rad]
  %        - C [6x1] - Damping of the Payload [N/(m/s), N/(rad/s)]
  %        - m [1x1] - Mass of the Payload [kg]
  %        - I [3x3] - Inertia matrix for the Payload [kg*m2]
  %
  % Outputs:
  %    - payload - Struture with the following properties:
  %        - type - 1 (none), 2 (rigid), 3 (flexible)
  %        - h [1x1] - Height of the CoM of the payload w.r.t {M} [m]
  %        - K [6x1] - Stiffness of the Payload [N/m, N/rad]
  %        - C [6x1] - Stiffness of the Payload [N/(m/s), N/(rad/s)]
  %        - m [1x1] - Mass of the Payload [kg]
  %        - I [3x3] - Inertia matrix for the Payload [kg*m2]
#+end_src

*** Optional Parameters
:PROPERTIES:
:UNNUMBERED: t
:END:
#+begin_src matlab
    arguments
      args.type char {mustBeMember(args.type,{'none', 'rigid', 'flexible', 'cartesian'})} = 'none'
      args.K (6,1) double {mustBeNumeric, mustBeNonnegative} = 1e8*ones(6,1)
      args.C (6,1) double {mustBeNumeric, mustBeNonnegative} = 1e1*ones(6,1)
      args.h (1,1) double {mustBeNumeric, mustBeNonnegative} = 100e-3
      args.m (1,1) double {mustBeNumeric, mustBeNonnegative} = 10
      args.I (3,3) double {mustBeNumeric, mustBeNonnegative} = 1*eye(3)
    end
#+end_src

*** Add Payload Type
:PROPERTIES:
:UNNUMBERED: t
:END:
#+begin_src matlab
  switch args.type
    case 'none'
      payload.type = 1;
    case 'rigid'
      payload.type = 2;
    case 'flexible'
      payload.type = 3;
    case 'cartesian'
      payload.type = 4;
  end
#+end_src

*** Add Stiffness, Damping and Mass properties of the Payload
:PROPERTIES:
:UNNUMBERED: t
:END:
#+begin_src matlab
  payload.K = args.K;
  payload.C = args.C;
  payload.m = args.m;
  payload.I = args.I;

  payload.h = args.h;
#+end_src

** Ground
:PROPERTIES:
:header-args:matlab+: :tangle ../src/initializeGround.m
:header-args:matlab+: :comments none :mkdirp yes :eval no
:END:
<<sec:initializeGround>>

This Matlab function is accessible [[file:../src/initializeGround.m][here]].

*** Function description
:PROPERTIES:
:UNNUMBERED: t
:END:
#+begin_src matlab
  function [ground] = initializeGround(args)
  % initializeGround - Initialize the Ground that can then be used for simulations and analysis
  %
  % Syntax: [ground] = initializeGround(args)
  %
  % Inputs:
  %    - args - Structure with the following fields:
  %        - type - 'none', 'solid', 'flexible'
  %        - rot_point [3x1] - Rotation point for the ground motion [m]
  %        - K [3x1] - Translation Stiffness of the Ground [N/m]
  %        - C [3x1] - Translation Damping of the Ground [N/(m/s)]
  %
  % Outputs:
  %    - ground - Struture with the following properties:
  %        - type - 1 (none), 2 (rigid), 3 (flexible)
  %        - K [3x1] - Translation Stiffness of the Ground [N/m]
  %        - C [3x1] - Translation Damping of the Ground [N/(m/s)]
#+end_src

*** Optional Parameters
:PROPERTIES:
:UNNUMBERED: t
:END:
#+begin_src matlab
  arguments
    args.type char {mustBeMember(args.type,{'none', 'rigid', 'flexible'})} = 'none'
    args.rot_point (3,1) double {mustBeNumeric} = zeros(3,1)
    args.K (3,1) double {mustBeNumeric, mustBeNonnegative} = 1e8*ones(3,1)
    args.C (3,1) double {mustBeNumeric, mustBeNonnegative} = 1e1*ones(3,1)
  end
#+end_src

*** Add Ground Type
:PROPERTIES:
:UNNUMBERED: t
:END:
#+begin_src matlab
  switch args.type
    case 'none'
      ground.type = 1;
    case 'rigid'
      ground.type = 2;
    case 'flexible'
      ground.type = 3;
  end
#+end_src

*** Add Stiffness and Damping properties of the Ground
:PROPERTIES:
:UNNUMBERED: t
:END:
#+begin_src matlab
  ground.K = args.K;
  ground.C = args.C;
#+end_src

*** Rotation Point
:PROPERTIES:
:UNNUMBERED: t
:END:
#+begin_src matlab
  ground.rot_point = args.rot_point;
#+end_src
* Initialize Disturbances
:PROPERTIES:
:header-args:matlab+: :tangle ../src/initializeDisturbances.m
:header-args:matlab+: :comments none :mkdirp yes
:header-args:matlab+: :eval no :results none
:END:
<<sec:initializeDisturbances>>

** Function Declaration and Documentation
:PROPERTIES:
:UNNUMBERED: t
:END:
#+begin_src matlab
  function [disturbances] = initializeDisturbances(args)
  % initializeDisturbances - Initialize the disturbances
  %
  % Syntax: [disturbances] = initializeDisturbances(args)
  %
  % Inputs:
  %    - args -

#+end_src

** Optional Parameters
:PROPERTIES:
:UNNUMBERED: t
:END:
#+begin_src matlab
  arguments
    args.Fd     double  {mustBeNumeric, mustBeReal} = zeros(6,1)
    args.Fd_t   double  {mustBeNumeric, mustBeReal} = 0
    args.Dw     double  {mustBeNumeric, mustBeReal} = zeros(6,1)
    args.Dw_t   double  {mustBeNumeric, mustBeReal} = 0
  end
#+end_src


** Structure initialization
:PROPERTIES:
:UNNUMBERED: t
:END:
#+begin_src matlab
  disturbances = struct();
#+end_src

** Ground Motion
:PROPERTIES:
:UNNUMBERED: t
:END:
#+begin_src matlab
  disturbances.Dw = timeseries([args.Dw], args.Dw_t);
#+end_src

** Direct Forces
:PROPERTIES:
:UNNUMBERED: t
:END:
#+begin_src matlab
  disturbances.Fd = timeseries([args.Fd], args.Fd_t);
#+end_src

* Initialize References
:PROPERTIES:
:header-args:matlab+: :tangle ../src/initializeReferences.m
:header-args:matlab+: :comments none :mkdirp yes
:header-args:matlab+: :eval no :results none
:END:
<<sec:initializeReferences>>

** Function Declaration and Documentation
:PROPERTIES:
:UNNUMBERED: t
:END:
#+begin_src matlab
  function [references] = initializeReferences(stewart, args)
  % initializeReferences - Initialize the references
  %
  % Syntax: [references] = initializeReferences(args)
  %
  % Inputs:
  %    - args -

#+end_src

** Optional Parameters
:PROPERTIES:
:UNNUMBERED: t
:END:
#+begin_src matlab
  arguments
    stewart
    args.t double {mustBeNumeric, mustBeReal} = 0
    args.r double {mustBeNumeric, mustBeReal} = zeros(6, 1)
  end
#+end_src

** Compute the corresponding strut length
#+begin_src matlab
  rL = zeros(6, length(args.t));

  for i = 1:length(args.t)
    R = [cos(args.r(6,i)) -sin(args.r(6,i))  0;
         sin(args.r(6,i))  cos(args.r(6,i))  0;
         0           0           1] * ...
        [cos(args.r(5,i))  0           sin(args.r(5,i));
         0           1           0;
        -sin(args.r(5,i))  0           cos(args.r(5,i))] * ...
        [1           0           0;
         0           cos(args.r(4,i)) -sin(args.r(4,i));
         0           sin(args.r(4,i))  cos(args.r(4,i))];

   [Li, dLi] = inverseKinematics(stewart, 'AP', [args.r(1,i); args.r(2,i); args.r(3,i)], 'ARB', R);
   rL(:, i) = dLi;
  end
#+end_src

** References
:PROPERTIES:
:UNNUMBERED: t
:END:
#+begin_src matlab
  references.r  = timeseries(args.r, args.t);
  references.rL = timeseries(rL, args.t);
#+end_src
