nass-fem/nass-fem.org

1992 lines
75 KiB
Org Mode
Raw Permalink Normal View History

2020-11-13 08:56:54 +01:00
#+TITLE: NASS - Finite Element Models with Simscape
2020-06-14 12:23:45 +02:00
:DRAWER:
#+LANGUAGE: en
#+EMAIL: dehaeze.thomas@gmail.com
#+AUTHOR: Dehaeze Thomas
2020-10-29 13:37:06 +01:00
#+HTML_LINK_HOME: ../index.html
#+HTML_LINK_UP: ../index.html
2020-06-14 12:23:45 +02:00
2020-11-12 10:34:47 +01:00
#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="https://research.tdehaeze.xyz/css/style.css"/>
#+HTML_HEAD: <script type="text/javascript" src="https://research.tdehaeze.xyz/js/script.js"></script>
2020-06-14 12:23:45 +02:00
2024-03-19 15:33:09 +01:00
#+BIND: org-latex-image-default-option "scale=1"
#+BIND: org-latex-image-default-width ""
#+LaTeX_CLASS: scrreprt
#+LaTeX_CLASS_OPTIONS: [a4paper, 10pt, DIV=12, parskip=full, bibliography=totoc]
#+LaTeX_HEADER_EXTRA: \input{preamble.tex}
#+LATEX_HEADER_EXTRA: \bibliography{nass-fem.bib}
#+BIND: org-latex-bib-compiler "biber"
2020-06-14 12:23:45 +02:00
#+PROPERTY: header-args:matlab :session *MATLAB*
#+PROPERTY: header-args:matlab+ :comments org
2024-03-19 15:33:09 +01:00
#+PROPERTY: header-args:matlab+ :exports none
2020-06-14 12:23:45 +02:00
#+PROPERTY: header-args:matlab+ :results none
#+PROPERTY: header-args:matlab+ :eval no-export
2024-03-19 15:33:09 +01:00
#+PROPERTY: header-args:matlab+ :noweb yes
#+PROPERTY: header-args:matlab+ :mkdirp yes
2020-06-14 12:23:45 +02:00
#+PROPERTY: header-args:matlab+ :output-dir figs
#+PROPERTY: header-args:matlab+ :tangle no
#+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
2024-03-19 15:33:09 +01:00
#+PROPERTY: header-args:latex+ :results file raw replace
#+PROPERTY: header-args:latex+ :buffer no
#+PROPERTY: header-args:latex+ :tangle no
2020-06-14 12:23:45 +02:00
#+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
2024-03-19 15:33:09 +01:00
#+PROPERTY: header-args:latex+ :post pdf2svg(file=*this*, ext="png")
2020-06-14 12:23:45 +02:00
:END:
2024-03-19 15:33:09 +01:00
#+begin_export html
<hr>
<p>This report is also available as a <a href="./nass-fem.pdf">pdf</a>.</p>
<hr>
#+end_export
#+latex: \clearpage
* Build :noexport:
#+NAME: startblock
#+BEGIN_SRC emacs-lisp :results none :tangle no
(add-to-list 'org-latex-classes
'("scrreprt"
"\\documentclass{scrreprt}"
("\\chapter{%s}" . "\\chapter*{%s}")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\paragraph{%s}" . "\\paragraph*{%s}")
))
;; Remove automatic org heading labels
(defun my-latex-filter-removeOrgAutoLabels (text backend info)
"Org-mode automatically generates labels for headings despite explicit use of `#+LABEL`. This filter forcibly removes all automatically generated org-labels in headings."
(when (org-export-derived-backend-p backend 'latex)
(replace-regexp-in-string "\\\\label{sec:org[a-f0-9]+}\n" "" text)))
(add-to-list 'org-export-filter-headline-functions
'my-latex-filter-removeOrgAutoLabels)
;; Remove all org comments in the output LaTeX file
(defun delete-org-comments (backend)
(loop for comment in (reverse (org-element-map (org-element-parse-buffer)
'comment 'identity))
do
(setf (buffer-substring (org-element-property :begin comment)
(org-element-property :end comment))
"")))
(add-hook 'org-export-before-processing-hook 'delete-org-comments)
;; Use no package by default
(setq org-latex-packages-alist nil)
(setq org-latex-default-packages-alist nil)
;; Do not include the subtitle inside the title
(setq org-latex-subtitle-separate t)
(setq org-latex-subtitle-format "\\subtitle{%s}")
(setq org-export-before-parsing-hook '(org-ref-glossary-before-parsing
org-ref-acronyms-before-parsing))
#+END_SRC
* Notes :noexport:
- [ ] Convert this into a standard report
- [ ] look at the [[file:~/Cloud/research/papers/published/brumund21_multib_simul_reduc_order_flexib_bodies_fea/paper/brumund21_multib_simul_reduc_order_flexib_bodies_fea.pdf][published paper]]
2020-11-12 17:33:52 +01:00
* Introduction :ignore:
2020-10-29 13:37:06 +01:00
2020-11-12 17:33:52 +01:00
In this document, Finite Element Models (FEM) of parts of the Nano-Hexapod are developed and integrated into Simscape for dynamical analysis.
2020-10-29 13:37:06 +01:00
2020-11-13 08:56:54 +01:00
It is divided in the following sections:
2020-11-12 17:33:52 +01:00
- Section [[sec:APA300ML]]:
A super-element of the Amplified Piezoelectric Actuator APA300ML used for the NASS is exported using Ansys and imported in Simscape.
The static and dynamical properties of the APA300ML are then estimated using the Simscape model.
2020-11-12 17:46:28 +01:00
- Section [[sec:flexor_ID16]]:
2020-11-12 17:33:52 +01:00
A first geometry of a Flexible joint is modelled and its characteristics are identified from the Stiffness matrix as well as from the Simscape model.
2020-11-12 17:46:28 +01:00
- Section [[sec:flexor_025]]:
2020-11-12 17:33:52 +01:00
An optimized flexible joint is developed for the Nano-Hexapod and is then imported in a Simscape model.
2020-11-12 18:49:34 +01:00
- Section [[sec:strut_encoder]]:
2020-11-13 08:56:54 +01:00
A super element of a complete strut is studied.
2020-07-31 13:57:13 +02:00
2020-07-28 18:13:08 +02:00
* APA300ML
2020-11-12 17:33:52 +01:00
:PROPERTIES:
:header-args:matlab+: :tangle matlab/APA300ML.m
:END:
<<sec:APA300ML>>
2020-08-03 15:37:17 +02:00
** Introduction :ignore:
2020-11-12 17:33:52 +01:00
In this section, the Amplified Piezoelectric Actuator APA300ML ([[file:doc/APA300ML.pdf][doc]]) is modeled using a Finite Element Software.
Then a /super element/ is exported and imported in Simscape where its dynamic is studied.
A 3D view of the Amplified Piezoelectric Actuator (APA300ML) is shown in Figure [[fig:apa300ml_ansys]].
The remote point used are also shown in this figure.
2020-08-03 15:37:17 +02:00
#+name: fig:apa300ml_ansys
#+caption: Ansys FEM of the APA300ML
2024-03-19 15:33:09 +01:00
#+attr_latex: :width 0.7\linewidth
2020-08-03 15:37:17 +02:00
[[file:figs/apa300ml_ansys.jpg]]
2020-07-28 18:13:08 +02:00
** Matlab Init :noexport:ignore:
#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name)
2024-03-19 15:33:09 +01:00
<<matlab-dir>>
2020-07-28 18:13:08 +02:00
#+end_src
#+begin_src matlab :exports none :results silent :noweb yes
2024-03-19 15:33:09 +01:00
<<matlab-init>>
2020-07-28 18:13:08 +02:00
#+end_src
2020-11-12 17:33:52 +01:00
#+begin_src matlab :tangle no
2024-03-19 15:33:09 +01:00
addpath('matlab/');
addpath('matlab/APA300ML/');
2020-07-28 18:13:08 +02:00
#+end_src
2020-11-12 17:33:52 +01:00
#+begin_src matlab :eval no
2024-03-19 15:33:09 +01:00
addpath('APA300ML/');
2020-11-12 17:33:52 +01:00
#+end_src
#+begin_src matlab
2024-03-19 15:33:09 +01:00
% open('APA300ML.slx');
2020-07-28 18:13:08 +02:00
#+end_src
** Import Mass Matrix, Stiffness Matrix, and Interface Nodes Coordinates
We first extract the stiffness and mass matrices.
2020-07-31 13:57:13 +02:00
#+begin_src matlab
2024-03-19 15:33:09 +01:00
K = readmatrix('APA300ML_mat_K.CSV');
M = readmatrix('APA300ML_mat_M.CSV');
2020-07-28 18:13:08 +02:00
#+end_src
#+begin_src matlab :exports results :results value table replace :tangle no
2024-03-19 15:33:09 +01:00
data2orgtable(K(1:10, 1:10), {}, {}, ' %.1g ');
2020-07-28 18:13:08 +02:00
#+end_src
2024-03-19 15:33:09 +01:00
#+name: tab:APA300ML_mat_K
2020-07-28 18:13:08 +02:00
#+caption: First 10x10 elements of the Stiffness matrix
2024-03-19 15:33:09 +01:00
#+attr_latex: :environment tabularx :width \linewidth :align XXXXXXXXXX
#+attr_latex: :center t :booktabs t :font \tiny
2020-07-28 18:13:08 +02:00
#+RESULTS:
2024-03-19 15:33:09 +01:00
| 200000000 | 30000 | -20000 | -70 | 300000 | 40 | 10000000 | 10000 | -6000 | 30 |
| 30000 | 30000000 | 2000 | -200000 | 60 | -10 | 4000 | 2000000 | -500 | 9000 |
| -20000 | 2000 | 7000000 | -10 | -30 | 10 | 6000 | 900 | -500000 | 3 |
| -70 | -200000 | -10 | 1000 | -0.1 | 08 | -20 | -9000 | 3 | -30 |
| 300000 | 60 | -30 | -0.1 | 900 | 0.1 | 30000 | 20 | -10 | 06 |
| 40 | -10 | 10 | 08 | 0.1 | 10000 | 20 | 9 | -5 | 03 |
| 10000000 | 4000 | 6000 | -20 | 30000 | 20 | 200000000 | 10000 | 9000 | 50 |
| 10000 | 2000000 | 900 | -9000 | 20 | 9 | 10000 | 30000000 | -500 | 200000 |
| -6000 | -500 | -500000 | 3 | -10 | -5 | 9000 | -500 | 7000000 | -2 |
| 30 | 9000 | 3 | -30 | 06 | 03 | 50 | 200000 | -2 | 1000 |
2020-07-28 18:13:08 +02:00
#+begin_src matlab :exports results :results value table replace :tangle no
2024-03-19 15:33:09 +01:00
data2orgtable(M(1:10, 1:10), {}, {}, ' %.1g ');
2020-07-28 18:13:08 +02:00
#+end_src
2024-03-19 15:33:09 +01:00
#+name: tab:APA300ML_mat_M
2020-07-28 18:13:08 +02:00
#+caption: First 10x10 elements of the Mass matrix
2024-03-19 15:33:09 +01:00
#+attr_latex: :environment tabularx :width \linewidth :align XXXXXXXXXX
#+attr_latex: :center t :booktabs t :font \tiny
2020-07-28 18:13:08 +02:00
#+RESULTS:
2020-10-29 13:37:06 +01:00
| 0.01 | -2e-06 | 1e-06 | 6e-09 | 5e-05 | -5e-09 | -0.0005 | -7e-07 | 6e-07 | -3e-09 |
| -2e-06 | 0.01 | 8e-07 | -2e-05 | -8e-09 | 2e-09 | -9e-07 | -0.0002 | 1e-08 | -9e-07 |
| 1e-06 | 8e-07 | 0.009 | 5e-10 | 1e-09 | -1e-09 | -5e-07 | 3e-08 | 6e-05 | 1e-10 |
| 6e-09 | -2e-05 | 5e-10 | 3e-07 | 2e-11 | -3e-12 | 3e-09 | 9e-07 | -4e-10 | 3e-09 |
| 5e-05 | -8e-09 | 1e-09 | 2e-11 | 6e-07 | -4e-11 | -1e-06 | -2e-09 | 1e-09 | -8e-12 |
| -5e-09 | 2e-09 | -1e-09 | -3e-12 | -4e-11 | 1e-07 | -2e-09 | -1e-09 | -4e-10 | -5e-12 |
| -0.0005 | -9e-07 | -5e-07 | 3e-09 | -1e-06 | -2e-09 | 0.01 | 1e-07 | -3e-07 | -2e-08 |
| -7e-07 | -0.0002 | 3e-08 | 9e-07 | -2e-09 | -1e-09 | 1e-07 | 0.01 | -4e-07 | 2e-05 |
| 6e-07 | 1e-08 | 6e-05 | -4e-10 | 1e-09 | -4e-10 | -3e-07 | -4e-07 | 0.009 | -2e-10 |
| -3e-09 | -9e-07 | 1e-10 | 3e-09 | -8e-12 | -5e-12 | -2e-08 | 2e-05 | -2e-10 | 3e-07 |
2020-07-28 18:13:08 +02:00
2020-11-12 17:33:52 +01:00
Then, we extract the coordinates of the interface nodes.
2020-07-28 18:13:08 +02:00
#+begin_src matlab
2020-11-12 18:40:48 +01:00
[int_xyz, int_i, n_xyz, n_i, nodes] = extractNodes('APA300ML_out_nodes_3D.txt');
2020-11-12 17:33:52 +01:00
#+end_src
#+begin_src matlab :exports results :results value table replace :tangle no :post addhdr(*this*)
data2orgtable([[1:length(int_i)]', int_i, int_xyz], {}, {'Node i', 'Node Number', 'x [m]', 'y [m]', 'z [m]'}, ' %f ');
#+end_src
2024-03-19 15:33:09 +01:00
#+name: tab:coordinate_nodes
2020-11-12 17:33:52 +01:00
#+caption: Coordinates of the interface nodes
2024-03-19 15:33:09 +01:00
#+attr_latex: :environment tabularx :width 0.6\linewidth :align ccccc
#+attr_latex: :center t :booktabs t
2020-11-12 17:33:52 +01:00
#+RESULTS:
| Node i | Node Number | x [m] | y [m] | z [m] |
|--------+-------------+---------+-------+--------|
2024-03-19 15:33:09 +01:00
| 1.0 | 697783 | 0.0 | 0.0 | -0.015 |
| 2.0 | 697784 | 0.0 | 0.0 | 0.015 |
| 3.0 | 697785 | -0.0325 | 0.0 | 0.0 |
| 4.0 | 697786 | -0.0125 | 0.0 | 0.0 |
| 5.0 | 697787 | -0.0075 | 0.0 | 0.0 |
| 6.0 | 697788 | 0.0125 | 0.0 | 0.0 |
| 7.0 | 697789 | 0.0325 | 0.0 | 0.0 |
2020-11-12 17:33:52 +01:00
#+begin_src matlab :exports results :results value table replace :tangle no
data2orgtable([length(n_i); length(int_i); size(M,1) - 6*length(int_i); size(M,1)], {'Total number of Nodes', 'Number of interface Nodes', 'Number of Modes', 'Size of M and K matrices'}, {}, ' %.0f ');
2020-07-28 18:13:08 +02:00
#+end_src
2024-03-19 15:33:09 +01:00
#+name: tab:parameters_fem
2020-11-12 17:33:52 +01:00
#+caption: Some extracted parameters of the FEM
2024-03-19 15:33:09 +01:00
#+attr_latex: :environment tabularx :width 0.4\linewidth :align lc
#+attr_latex: :center t :booktabs t
2020-11-12 17:33:52 +01:00
#+RESULTS:
| Total number of Nodes | 7 |
| Number of interface Nodes | 7 |
| Number of Modes | 120 |
| Size of M and K matrices | 162 |
Using =K=, =M= and =int_xyz=, we can now use the =Reduced Order Flexible Solid= simscape block.
** Piezoelectric parameters
In order to make the conversion from applied voltage to generated force or from the strain to the generated voltage, we need to defined some parameters corresponding to the piezoelectric material:
2020-07-28 18:13:08 +02:00
#+begin_src matlab
2021-01-04 13:58:12 +01:00
d33 = 600e-12; % Strain constant [m/V]
2020-11-12 17:33:52 +01:00
n = 80; % Number of layers per stack
eT = 1.6e-8; % Permittivity under constant stress [F/m]
sD = 1e-11; % Compliance under constant electric displacement [m2/N]
ka = 235e6; % Stack stiffness [N/m]
C = 5e-6; % Stack capactiance [F]
2020-07-28 18:13:08 +02:00
#+end_src
2021-01-04 13:58:12 +01:00
PZT-4
#+begin_src matlab
d33 = 300e-12; % Strain constant [m/V]
n = 80; % Number of layers per stack
eT = 5.3e-9; % Permittivity under constant stress [F/m]
sD = 1e-11; % Compliance under constant electric displacement [m2/N]
ka = 235e6; % Stack stiffness [N/m]
C = 5e-6; % Stack capactiance [F]
#+end_src
2020-11-12 17:33:52 +01:00
The ratio of the developed force to applied voltage is:
#+name: eq:piezo_voltage_to_force
\begin{equation}
F_a = g_a V_a, \quad g_a = d_{33} n k_a
\end{equation}
where:
- $F_a$: developed force in [N]
- $n$: number of layers of the actuator stack
- $d_{33}$: strain constant in [m/V]
- $k_a$: actuator stack stiffness in [N/m]
- $V_a$: applied voltage in [V]
If we take the numerical values, we obtain:
2020-07-28 18:13:08 +02:00
#+begin_src matlab :results replace value
2020-11-12 17:33:52 +01:00
d33*n*ka % [N/V]
2020-07-28 18:13:08 +02:00
#+end_src
#+RESULTS:
2020-11-12 17:33:52 +01:00
: 5.64
2020-07-28 18:13:08 +02:00
2024-03-19 15:33:09 +01:00
From [[cite:&fleming14_desig_model_contr_nanop_system]] (page 123), the relation between relative displacement of the sensor stack and generated voltage is:
2020-11-12 17:33:52 +01:00
#+name: eq:piezo_strain_to_voltage
\begin{equation}
V_s = \frac{d_{33}}{\epsilon^T s^D n} \Delta h
\end{equation}
2020-07-28 18:13:08 +02:00
where:
2020-11-12 17:33:52 +01:00
- $V_s$: measured voltage in [V]
- $d_{33}$: strain constant in [m/V]
- $\epsilon^T$: permittivity under constant stress in [F/m]
- $s^D$: elastic compliance under constant electric displacement in [m^2/N]
- $n$: number of layers of the sensor stack
- $\Delta h$: relative displacement in [m]
If we take the numerical values, we obtain:
2020-07-28 18:13:08 +02:00
#+begin_src matlab :results replace value
2020-11-12 17:33:52 +01:00
1e-6*d33/(eT*sD*n) % [V/um]
2020-07-28 18:13:08 +02:00
#+end_src
#+RESULTS:
2020-11-12 17:33:52 +01:00
: 23.438
** Simscape Model
The flexible element is imported using the =Reduced Order Flexible Solid= simscape block.
Let's say we use two stacks as a force sensor and one stack as an actuator:
- A =Relative Motion Sensor= block is added between the nodes A and C
- An =Internal Force= block is added between the remote points E and B
The interface nodes are shown in Figure [[fig:apa300ml_ansys]].
One mass is fixed at one end of the piezo-electric stack actuator (remove point F), the other end is fixed to the world frame (remote point G).
2020-07-28 18:13:08 +02:00
2020-08-03 15:37:17 +02:00
** Identification of the APA Characteristics
*** Stiffness
#+begin_src matlab :exports none
2021-01-04 13:58:12 +01:00
m = 0.0001;
2020-08-03 15:37:17 +02:00
#+end_src
The transfer function from vertical external force to the relative vertical displacement is identified.
#+begin_src matlab :exports none
%% Name of the Simulink File
2020-11-12 17:33:52 +01:00
mdl = 'APA300ML';
2020-08-03 15:37:17 +02:00
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/Fd'], 1, 'openinput'); io_i = io_i + 1;
2020-11-12 17:33:52 +01:00
io(io_i) = linio([mdl, '/z'], 1, 'openoutput'); io_i = io_i + 1;
2020-08-03 15:37:17 +02:00
G = linearize(mdl, io);
#+end_src
The inverse of its DC gain is the axial stiffness of the APA:
#+begin_src matlab :results replace value
1e-6/dcgain(G) % [N/um]
#+end_src
#+RESULTS:
2020-10-29 13:37:06 +01:00
: 1.753
2020-08-03 15:37:17 +02:00
The specified stiffness in the datasheet is $k = 1.8\, [N/\mu m]$.
*** Resonance Frequency
The resonance frequency is specified to be between 650Hz and 840Hz.
This is also the case for the FEM model (Figure [[fig:apa300ml_resonance]]).
#+begin_src matlab :exports none
freqs = logspace(2, 4, 5000);
figure;
hold on;
plot(freqs, abs(squeeze(freqresp(G, freqs, 'Hz'))));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xlabel('Frequency [Hz]'); ylabel('Amplitude');
hold off;
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/apa300ml_resonance.pdf', 'width', 'wide', 'height', 'normal');
#+end_src
#+name: fig:apa300ml_resonance
#+caption: First resonance is around 800Hz
#+RESULTS:
[[file:figs/apa300ml_resonance.png]]
*** Amplification factor
2020-11-12 17:33:52 +01:00
The amplification factor is the ratio of the vertical displacement to the stack displacement.
2020-08-03 15:37:17 +02:00
#+begin_src matlab :exports none
%% Name of the Simulink File
2020-11-12 17:33:52 +01:00
mdl = 'APA300ML';
2020-08-03 15:37:17 +02:00
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/F'], 1, 'openinput'); io_i = io_i + 1;
2020-10-29 13:37:06 +01:00
io(io_i) = linio([mdl, '/z'], 1, 'openoutput'); io_i = io_i + 1;
2020-08-03 15:37:17 +02:00
io(io_i) = linio([mdl, '/d'], 1, 'openoutput'); io_i = io_i + 1;
G = linearize(mdl, io);
#+end_src
The ratio of the two displacement is computed from the FEM model.
#+begin_src matlab :results replace value
2020-10-29 13:37:06 +01:00
abs(dcgain(G(1,1))./dcgain(G(2,1)))
2020-08-03 15:37:17 +02:00
#+end_src
#+RESULTS:
2020-10-29 13:37:06 +01:00
: 5.0749
2020-08-03 15:37:17 +02:00
2020-11-12 17:33:52 +01:00
This is actually correct and approximately corresponds to the ratio of the piezo height and length:
2020-08-03 15:37:17 +02:00
#+begin_src matlab :results replace value
75/15
#+end_src
#+RESULTS:
: 5
*** Stroke
Estimation of the actuator stroke:
\[ \Delta H = A n \Delta L \]
with:
- $\Delta H$ Axial Stroke of the APA
- $A$ Amplification factor (5 for the APA300ML)
- $n$ Number of stack used
- $\Delta L$ Stroke of the stack (0.1% of its length)
#+begin_src matlab :results replace value
1e6 * 5 * 3 * 20e-3 * 0.1e-2
#+end_src
#+RESULTS:
: 300
This is exactly the specified stroke in the data-sheet.
2021-01-04 13:58:12 +01:00
*** TODO Stroke BIS
- [ ] Identified the stroke form the transfer function from V to z
#+begin_src matlab :exports none
%% Name of the Simulink File
mdl = 'APA300ML';
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/V'], 1, 'openinput'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/d'], 1, 'openoutput'); io_i = io_i + 1;
G = linearize(mdl, io);
1e6*170*abs(dcgain(G))
#+end_src
2020-11-12 17:33:52 +01:00
** Identification of the Dynamics from actuator to replace displacement
We first set the mass to be approximately zero.
2020-08-03 15:37:17 +02:00
#+begin_src matlab :exports none
2020-07-28 18:13:08 +02:00
m = 0.01;
#+end_src
The dynamics is identified from the applied force to the measured relative displacement.
2020-08-03 15:37:17 +02:00
#+begin_src matlab :exports none
2020-07-28 18:13:08 +02:00
%% Name of the Simulink File
2020-11-12 17:33:52 +01:00
mdl = 'APA300ML';
2020-07-28 18:13:08 +02:00
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/F'], 1, 'openinput'); io_i = io_i + 1;
2020-10-29 13:37:06 +01:00
io(io_i) = linio([mdl, '/z'], 1, 'openoutput'); io_i = io_i + 1;
2020-07-28 18:13:08 +02:00
Gh = -linearize(mdl, io);
#+end_src
2020-08-03 15:37:17 +02:00
The same dynamics is identified for a payload mass of 10Kg.
2020-07-28 18:13:08 +02:00
#+begin_src matlab
m = 10;
#+end_src
2020-08-03 15:37:17 +02:00
#+begin_src matlab :exports none
2020-07-28 18:13:08 +02:00
%% Name of the Simulink File
2020-11-12 17:33:52 +01:00
mdl = 'APA300ML';
2020-07-28 18:13:08 +02:00
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/F'], 1, 'openinput'); io_i = io_i + 1;
2020-10-29 13:37:06 +01:00
io(io_i) = linio([mdl, '/z'], 1, 'openoutput'); io_i = io_i + 1;
2020-07-28 18:13:08 +02:00
Ghm = -linearize(mdl, io);
#+end_src
#+begin_src matlab :exports none
freqs = logspace(0, 4, 5000);
figure;
2020-11-12 17:33:52 +01:00
tiledlayout(3, 1, 'TileSpacing', 'None', 'Padding', 'None');
2020-07-28 18:13:08 +02:00
2020-11-12 17:33:52 +01:00
ax1 = nexttile([2,1]);
2020-07-28 18:13:08 +02:00
hold on;
plot(freqs, abs(squeeze(freqresp(Gh, freqs, 'Hz'))), '-');
plot(freqs, abs(squeeze(freqresp(Ghm, freqs, 'Hz'))), '-');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude'); set(gca, 'XTickLabel',[]);
hold off;
2020-11-12 17:33:52 +01:00
ax2 = nexttile;
2020-07-28 18:13:08 +02:00
hold on;
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Gh, freqs, 'Hz')))), '-', ...
'DisplayName', '$m = 0kg$');
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Ghm, freqs, 'Hz')))), '-', ...
2020-11-12 17:33:52 +01:00
'DisplayName', '$m = 10kg$');
2020-07-28 18:13:08 +02:00
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
yticks(-360:90:360);
ylim([-360 0]);
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
hold off;
linkaxes([ax1,ax2],'x');
xlim([freqs(1), freqs(end)]);
2020-11-12 17:33:52 +01:00
legend('location', 'southwest');
2020-07-28 18:13:08 +02:00
#+end_src
2020-08-03 15:37:17 +02:00
#+begin_src matlab :tangle no :exports results :results file replace
2020-11-12 17:33:52 +01:00
exportFig('figs/apa300ml_plant_dynamics.pdf', 'width', 'wide', 'height', 'tall');
2020-08-03 15:37:17 +02:00
#+end_src
2020-11-12 17:33:52 +01:00
#+name: fig:apa300ml_plant_dynamics
#+caption: Transfer function from forces applied by the stack to the axial displacement of the APA
2020-08-03 15:37:17 +02:00
#+RESULTS:
2020-11-12 17:33:52 +01:00
[[file:figs/apa300ml_plant_dynamics.png]]
2020-08-03 15:37:17 +02:00
2020-11-12 17:33:52 +01:00
The root locus corresponding to Direct Velocity Feedback with a mass of 10kg is shown in Figure [[fig:apa300ml_dvf_root_locus]].
2020-08-03 15:37:17 +02:00
#+begin_src matlab :exports none
2020-07-28 18:13:08 +02:00
figure;
gains = logspace(0, 5, 500);
hold on;
2020-11-12 17:33:52 +01:00
plot(real(pole(Ghm)), imag(pole(G)), 'kx');
plot(real(tzero(Ghm)), imag(tzero(G)), 'ko');
2020-07-28 18:13:08 +02:00
for k = 1:length(gains)
2020-11-12 17:33:52 +01:00
cl_poles = pole(feedback(Ghm, gains(k)*s));
2020-07-28 18:13:08 +02:00
plot(real(cl_poles), imag(cl_poles), 'k.');
end
hold off;
axis square;
xlim([-500, 10]); ylim([0, 510]);
xlabel('Real Part'); ylabel('Imaginary Part');
#+end_src
2020-08-03 15:37:17 +02:00
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/apa300ml_dvf_root_locus.pdf', 'width', 'wide', 'height', 'tall');
#+end_src
#+name: fig:apa300ml_dvf_root_locus
#+caption: Root Locus for Direct Velocity Feedback
#+RESULTS:
[[file:figs/apa300ml_dvf_root_locus.png]]
2020-11-12 17:33:52 +01:00
** Identification of the Dynamics from actuator to force sensor
Let's use 2 stacks as a force sensor and 1 stack as force actuator.
2020-07-31 13:57:13 +02:00
2020-11-12 17:33:52 +01:00
The transfer function from actuator voltage to sensor voltage is identified and shown in Figure [[fig:apa300ml_iff_plant]].
#+begin_src matlab :exports none
2020-07-31 13:57:13 +02:00
m = 10;
#+end_src
2020-11-12 17:33:52 +01:00
#+begin_src matlab :exports none
2020-07-31 13:57:13 +02:00
%% Name of the Simulink File
2020-11-12 17:33:52 +01:00
mdl = 'APA300ML';
2020-07-31 13:57:13 +02:00
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/Va'], 1, 'openinput'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/Vs'], 1, 'openoutput'); io_i = io_i + 1;
2020-11-12 17:33:52 +01:00
Giff = -linearize(mdl, io);
2020-07-31 13:57:13 +02:00
#+end_src
#+begin_src matlab :exports none
2020-11-12 17:33:52 +01:00
freqs = logspace(0, 4, 5000);
2020-07-31 13:57:13 +02:00
figure;
2020-11-12 17:33:52 +01:00
tiledlayout(3, 1, 'TileSpacing', 'None', 'Padding', 'None');
2020-07-31 13:57:13 +02:00
2020-11-12 17:33:52 +01:00
ax1 = nexttile([2,1]);
2020-07-31 13:57:13 +02:00
hold on;
2020-11-12 17:33:52 +01:00
plot(freqs, abs(squeeze(freqresp(Giff, freqs, 'Hz'))), '-');
2020-07-31 13:57:13 +02:00
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude'); set(gca, 'XTickLabel',[]);
hold off;
2020-11-12 17:33:52 +01:00
ax2 = nexttile;
2020-07-31 13:57:13 +02:00
hold on;
2020-11-12 17:33:52 +01:00
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Giff, freqs, 'Hz')))), '-');
2020-07-31 13:57:13 +02:00
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
yticks(-360:90:360);
2020-11-12 17:33:52 +01:00
ylim([-180 180]);
2020-07-31 13:57:13 +02:00
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
hold off;
linkaxes([ax1,ax2],'x');
xlim([freqs(1), freqs(end)]);
#+end_src
2020-11-12 17:33:52 +01:00
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/apa300ml_iff_plant.pdf', 'width', 'wide', 'height', 'tall');
2020-07-31 13:57:13 +02:00
#+end_src
2020-11-12 17:33:52 +01:00
#+name: fig:apa300ml_iff_plant
#+caption: Transfer function from actuator to force sensor
#+RESULTS:
[[file:figs/apa300ml_iff_plant.png]]
2020-07-31 13:57:13 +02:00
2020-11-12 17:33:52 +01:00
For root locus corresponding to IFF is shown in Figure [[fig:apa300ml_iff_root_locus]].
2020-07-31 13:57:13 +02:00
#+begin_src matlab :exports none
figure;
2020-11-12 17:33:52 +01:00
gains = logspace(0, 5, 500);
2020-07-31 13:57:13 +02:00
hold on;
2020-11-12 17:33:52 +01:00
plot(real(pole(Giff)), imag(pole(Giff)), 'kx');
plot(real(tzero(Giff)), imag(tzero(Giff)), 'ko');
2020-07-31 13:57:13 +02:00
for k = 1:length(gains)
2020-11-12 17:33:52 +01:00
cl_poles = pole(feedback(Giff, gains(k)/s));
2020-07-31 13:57:13 +02:00
plot(real(cl_poles), imag(cl_poles), 'k.');
end
hold off;
axis square;
xlim([-500, 10]); ylim([0, 510]);
xlabel('Real Part'); ylabel('Imaginary Part');
#+end_src
2020-11-12 17:33:52 +01:00
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/apa300ml_iff_root_locus.pdf', 'width', 'wide', 'height', 'tall');
#+end_src
#+name: fig:apa300ml_iff_root_locus
#+caption: Root Locus for IFF
#+RESULTS:
[[file:figs/apa300ml_iff_root_locus.png]]
** Identification for a simpler model
The goal in this section is to identify the parameters of a simple APA model from the FEM.
This can be useful is a lower order model is to be used for simulations.
The presented model is based on cite:souleille18_concep_activ_mount_space_applic.
The model represents the Amplified Piezo Actuator (APA) from Cedrat-Technologies (Figure [[fig:souleille18_model_piezo]]).
The parameters are shown in the table below.
#+name: fig:souleille18_model_piezo
#+caption: Picture of an APA100M from Cedrat Technologies. Simplified model of a one DoF payload mounted on such isolator
2024-03-19 15:33:09 +01:00
#+attr_latex: :width 0.7\linewidth
[[file:./figs/souleille18_model_piezo.png]]
2024-03-19 15:33:09 +01:00
#+name: tab:parameters_apa100m
2020-11-12 17:33:52 +01:00
#+caption:Parameters used for the model of the APA 100M
2024-03-19 15:33:09 +01:00
#+attr_latex: :environment tabularx :width 0.8\linewidth :align cl
#+attr_latex: :center t :booktabs t
| | Meaning |
|-------+----------------------------------------------------------------|
| $k_e$ | Stiffness used to adjust the pole of the isolator |
| $k_1$ | Stiffness of the metallic suspension when the stack is removed |
| $k_a$ | Stiffness of the actuator |
| $c_1$ | Added viscous damping |
The goal is to determine $k_e$, $k_a$ and $k_1$ so that the simplified model fits the FEM model.
\[ \alpha = \frac{x_1}{f}(\omega=0) = \frac{\frac{k_e}{k_e + k_a}}{k_1 + \frac{k_e k_a}{k_e + k_a}} \]
\[ \beta = \frac{x_1}{F}(\omega=0) = \frac{1}{k_1 + \frac{k_e k_a}{k_e + k_a}} \]
If we can fix $k_a$, we can determine $k_e$ and $k_1$ with:
\[ k_e = \frac{k_a}{\frac{\beta}{\alpha} - 1} \]
\[ k_1 = \frac{1}{\beta} - \frac{k_e k_a}{k_e + k_a} \]
#+begin_src matlab :exports none
m = 10;
#+end_src
#+begin_src matlab :exports none
%% Name of the Simulink File
2020-11-12 17:33:52 +01:00
mdl = 'APA300ML';
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/Fd'], 1, 'openinput'); io_i = io_i + 1; % External Vertical Force [N]
io(io_i) = linio([mdl, '/w'], 1, 'openinput'); io_i = io_i + 1; % Base Motion [m]
io(io_i) = linio([mdl, '/Fa'], 1, 'openinput'); io_i = io_i + 1; % Actuator Force [N]
2020-10-29 13:37:06 +01:00
io(io_i) = linio([mdl, '/z'], 1, 'openoutput'); io_i = io_i + 1; % Vertical Displacement [m]
io(io_i) = linio([mdl, '/Vs'], 1, 'openoutput'); io_i = io_i + 1; % Force Sensor [V]
io(io_i) = linio([mdl, '/d'], 1, 'openoutput'); io_i = io_i + 1; % Stack Displacement [m]
G = linearize(mdl, io);
G.InputName = {'Fd', 'w', 'Fa'};
G.OutputName = {'y', 'Fs', 'd'};
#+end_src
From the identified dynamics, compute $\alpha$ and $\beta$
#+begin_src matlab
alpha = abs(dcgain(G('y', 'Fa')));
beta = abs(dcgain(G('y', 'Fd')));
#+end_src
$k_a$ is estimated using the following formula:
#+begin_src matlab
ka = 0.8/abs(dcgain(G('y', 'Fa')));
#+end_src
The factor can be adjusted to better match the curves.
Then $k_e$ and $k_1$ are computed.
#+begin_src matlab
ke = ka/(beta/alpha - 1);
k1 = 1/beta - ke*ka/(ke + ka);
#+end_src
#+begin_src matlab :exports results :results value table replace :tangle no :post addhdr(*this*)
2024-03-19 15:33:09 +01:00
data2orgtable(1e-6*[ka; ke; k1], {'=ka=', '=ke=', '=k1='}, {'Value [N/um]'}, ' %.1f ');
#+end_src
2024-03-19 15:33:09 +01:00
#+name: tab:stiffnesses_apa100m
#+caption:Obtained stiffnesses of the APA 100M
#+attr_latex: :environment tabularx :width 0.3\linewidth :align cl
#+attr_latex: :center t :booktabs t
#+RESULTS:
| | Value [N/um] |
|----+--------------|
2020-10-29 13:37:06 +01:00
| ka | 40.5 |
| ke | 1.5 |
| k1 | 0.4 |
The damping in the system is adjusted to match the FEM model if necessary.
#+begin_src matlab
c1 = 1e2;
#+end_src
2020-11-12 17:33:52 +01:00
The analytical model of the simpler system is defined below:
#+begin_src matlab
Ga = 1/(m*s^2 + k1 + c1*s + ke*ka/(ke + ka)) * ...
[ 1 , k1 + c1*s + ke*ka/(ke + ka) , ke/(ke + ka) ;
-ke*ka/(ke + ka), ke*ka/(ke + ka)*m*s^2 , -ke/(ke + ka)*(m*s^2 + c1*s + k1)];
Ga.InputName = {'Fd', 'w', 'Fa'};
Ga.OutputName = {'y', 'Fs'};
#+end_src
2020-11-12 17:33:52 +01:00
And the DC gain is adjusted for the force sensor:
#+begin_src matlab
2020-10-29 13:37:06 +01:00
F_gain = dcgain(G('Fs', 'Fd'))/dcgain(Ga('Fs', 'Fd'));
#+end_src
2020-11-12 17:33:52 +01:00
The dynamics of the FEM model and the simpler model are compared in Figure [[fig:apa300ml_comp_simpler_model]].
#+begin_src matlab :exports none
freqs = logspace(0, 5, 1000);
figure;
2020-11-12 17:33:52 +01:00
tiledlayout(2, 3, 'TileSpacing', 'None', 'Padding', 'None');
2020-11-12 17:33:52 +01:00
ax1 = nexttile;
hold on;
plot(freqs, abs(squeeze(freqresp(G( 'y', 'w'), freqs, 'Hz'))));
plot(freqs, abs(squeeze(freqresp(Ga('y', 'w'), freqs, 'Hz'))));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
2020-11-12 17:33:52 +01:00
set(gca, 'XTickLabel',[]);
ylabel('$x_1/w$ [m/m]');
ylim([1e-6, 1e2]);
2020-11-12 17:33:52 +01:00
ax2 = nexttile;
hold on;
plot(freqs, abs(squeeze(freqresp(G( 'y', 'Fa'), freqs, 'Hz'))));
plot(freqs, abs(squeeze(freqresp(Ga('y', 'Fa'), freqs, 'Hz'))));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
2020-11-12 17:33:52 +01:00
set(gca, 'XTickLabel',[]);
ylabel('$x_1/f$ [m/N]');
ylim([1e-14, 1e-6]);
2020-11-12 17:33:52 +01:00
ax3 = nexttile;
hold on;
plot(freqs, abs(squeeze(freqresp(G( 'y', 'Fd'), freqs, 'Hz'))));
plot(freqs, abs(squeeze(freqresp(Ga('y', 'Fd'), freqs, 'Hz'))));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
2020-11-12 17:33:52 +01:00
set(gca, 'XTickLabel',[]);
ylabel('$x_1/F$ [m/N]');
ylim([1e-14, 1e-4]);
2020-11-12 17:33:52 +01:00
ax4 = nexttile;
hold on;
2020-10-29 13:37:06 +01:00
plot(freqs, abs(squeeze(freqresp(G( 'Fs', 'w'), freqs, 'Hz'))));
plot(freqs, abs(squeeze(freqresp(F_gain*Ga('Fs', 'w'), freqs, 'Hz'))));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
2020-11-12 17:33:52 +01:00
xlabel('Frequency [Hz]');
ylabel('$F_s/w$ [m/m]');
ylim([1e2, 1e8]);
2020-11-12 17:33:52 +01:00
ax5 = nexttile;
hold on;
2020-10-29 13:37:06 +01:00
plot(freqs, abs(squeeze(freqresp(G( 'Fs', 'Fa'), freqs, 'Hz'))));
plot(freqs, abs(squeeze(freqresp(F_gain*Ga('Fs', 'Fa'), freqs, 'Hz'))));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
2020-11-12 17:33:52 +01:00
xlabel('Frequency [Hz]');
ylabel('$F_s/f$ [m/N]');
ylim([1e-4, 1e1]);
2020-10-29 13:37:06 +01:00
2020-11-12 17:33:52 +01:00
ax6 = nexttile;
2020-10-29 13:37:06 +01:00
hold on;
2020-11-12 17:33:52 +01:00
plot(freqs, abs(squeeze(freqresp(G( 'Fs', 'Fd'), freqs, 'Hz'))));
plot(freqs, abs(squeeze(freqresp(F_gain*Ga('Fs', 'Fd'), freqs, 'Hz'))));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xlabel('Frequency [Hz]');
ylabel('$F_s/F$ [m/N]');
ylim([1e-7, 1e2]);
2020-10-29 13:37:06 +01:00
2020-11-12 17:33:52 +01:00
linkaxes([ax1,ax2,ax3,ax4,ax5,ax6],'x');
2020-07-31 13:57:13 +02:00
#+end_src
2020-11-12 17:33:52 +01:00
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/apa300ml_comp_simpler_model.pdf', 'width', 'full', 'height', 'full');
2020-07-31 13:57:13 +02:00
#+end_src
2020-11-12 17:33:52 +01:00
#+name: fig:apa300ml_comp_simpler_model
#+caption: Comparison of the Dynamics between the FEM model and the simplified one
2024-03-19 15:33:09 +01:00
#+attr_latex: :width 1.0\linewidth
2020-10-29 13:37:06 +01:00
#+RESULTS:
2020-11-12 17:33:52 +01:00
[[file:figs/apa300ml_comp_simpler_model.png]]
2020-10-29 13:37:06 +01:00
2020-11-12 17:33:52 +01:00
The simplified model has also been implemented in Simscape.
2020-07-31 13:57:13 +02:00
2020-11-12 17:33:52 +01:00
The dynamics of the Simscape simplified model is identified and compared with the FEM one in Figure [[fig:apa300ml_comp_simpler_simscape]].
2020-10-29 13:37:06 +01:00
#+begin_src matlab :exports none
%% Name of the Simulink File
2020-11-12 17:33:52 +01:00
mdl = 'APA300ML_simplified';
2020-10-29 13:37:06 +01:00
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/Fd'], 1, 'openinput'); io_i = io_i + 1; % External Vertical Force [N]
2020-11-12 17:33:52 +01:00
io(io_i) = linio([mdl, '/w'], 1, 'openinput'); io_i = io_i + 1; % Base Motion [m]
io(io_i) = linio([mdl, '/Fa'], 1, 'openinput'); io_i = io_i + 1; % Actuator Force [N]
io(io_i) = linio([mdl, '/y'], 1, 'openoutput'); io_i = io_i + 1; % Vertical Displacement [m]
io(io_i) = linio([mdl, '/Fs'], 1, 'openoutput'); io_i = io_i + 1; % Force Sensor [V]
2020-10-29 13:37:06 +01:00
2020-11-12 17:33:52 +01:00
Gs = linearize(mdl, io);
2020-10-29 13:37:06 +01:00
2020-11-12 17:33:52 +01:00
Gs.InputName = {'Fd', 'w', 'Fa'};
Gs.OutputName = {'y', 'Fs'};
2020-10-29 13:37:06 +01:00
#+end_src
2020-11-12 17:33:52 +01:00
#+begin_src matlab :exports none
freqs = logspace(0, 5, 1000);
2020-10-29 13:37:06 +01:00
figure;
2020-11-12 17:33:52 +01:00
tiledlayout(2, 3, 'TileSpacing', 'None', 'Padding', 'None');
ax1 = nexttile;
2020-10-29 13:37:06 +01:00
hold on;
2020-11-12 17:33:52 +01:00
plot(freqs, abs(squeeze(freqresp(G( 'y', 'w'), freqs, 'Hz'))));
plot(freqs, abs(squeeze(freqresp(Gs('y', 'w'), freqs, 'Hz'))));
2020-10-29 13:37:06 +01:00
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
2020-11-12 17:33:52 +01:00
set(gca, 'XTickLabel',[]);
ylabel('$x_1/w$ [m/m]');
ylim([1e-6, 1e2]);
2020-10-29 13:37:06 +01:00
2020-11-12 17:33:52 +01:00
ax2 = nexttile;
2020-10-29 13:37:06 +01:00
hold on;
2020-11-12 17:33:52 +01:00
plot(freqs, abs(squeeze(freqresp(G( 'y', 'Fa'), freqs, 'Hz'))));
plot(freqs, abs(squeeze(freqresp(Gs('y', 'Fa'), freqs, 'Hz'))));
2020-10-29 13:37:06 +01:00
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
2020-11-12 17:33:52 +01:00
set(gca, 'XTickLabel',[]);
ylabel('$x_1/f$ [m/N]');
ylim([1e-14, 1e-6]);
2020-10-29 13:37:06 +01:00
2020-11-12 17:33:52 +01:00
ax3 = nexttile;
hold on;
plot(freqs, abs(squeeze(freqresp(G( 'y', 'Fd'), freqs, 'Hz'))));
plot(freqs, abs(squeeze(freqresp(Gs('y', 'Fd'), freqs, 'Hz'))));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
set(gca, 'XTickLabel',[]);
ylabel('$x_1/F$ [m/N]');
ylim([1e-14, 1e-4]);
2020-10-29 13:37:06 +01:00
2020-11-12 17:33:52 +01:00
ax4 = nexttile;
hold on;
plot(freqs, abs(squeeze(freqresp(G( 'Fs', 'w'), freqs, 'Hz'))));
plot(freqs, abs(squeeze(freqresp(F_gain*Gs('Fs', 'w'), freqs, 'Hz'))));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xlabel('Frequency [Hz]');
ylabel('$F_s/w$ [m/m]');
ylim([1e2, 1e8]);
2020-10-29 13:37:06 +01:00
2020-11-12 17:33:52 +01:00
ax5 = nexttile;
hold on;
plot(freqs, abs(squeeze(freqresp(G( 'Fs', 'Fa'), freqs, 'Hz'))));
plot(freqs, abs(squeeze(freqresp(F_gain*Gs('Fs', 'Fa'), freqs, 'Hz'))));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xlabel('Frequency [Hz]');
ylabel('$F_s/f$ [m/N]');
ylim([1e-4, 1e1]);
2020-10-29 13:37:06 +01:00
2020-11-12 17:33:52 +01:00
ax6 = nexttile;
hold on;
plot(freqs, abs(squeeze(freqresp(G( 'Fs', 'Fd'), freqs, 'Hz'))));
plot(freqs, abs(squeeze(freqresp(F_gain*Gs('Fs', 'Fd'), freqs, 'Hz'))));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xlabel('Frequency [Hz]');
ylabel('$F_s/F$ [m/N]');
ylim([1e-7, 1e2]);
2020-10-29 13:37:06 +01:00
2020-11-12 17:33:52 +01:00
linkaxes([ax1,ax2,ax3,ax4,ax5,ax6],'x');
2020-10-29 13:37:06 +01:00
#+end_src
2020-11-12 17:33:52 +01:00
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/apa300ml_comp_simpler_simscape.pdf', 'width', 'full', 'height', 'full');
2020-10-29 13:37:06 +01:00
#+end_src
2020-11-12 17:33:52 +01:00
#+name: fig:apa300ml_comp_simpler_simscape
#+caption: Comparison of the Dynamics between the FEM model and the simplified simscape model
2020-10-29 13:37:06 +01:00
#+RESULTS:
2020-11-12 17:33:52 +01:00
[[file:figs/apa300ml_comp_simpler_simscape.png]]
2020-10-29 13:37:06 +01:00
2020-11-12 18:40:48 +01:00
** Integral Force Feedback
In this section, Integral Force Feedback control architecture is applied on the APA300ML.
First, the plant (dynamics from voltage actuator to voltage sensor is identified).
#+begin_src matlab :exports none
Kiff = tf(0);
#+end_src
The payload mass is set to 10kg.
#+begin_src matlab
m = 10;
#+end_src
#+begin_src matlab :exports none
%% Name of the Simulink File
mdl = 'APA300ML_IFF';
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/w'], 1, 'openinput'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/F'], 1, 'openinput'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/Fd'], 1, 'openinput'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/z'], 1, 'openoutput'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/APA300ML'], 1, 'openoutput'); io_i = io_i + 1;
G_ol = linearize(mdl, io);
G_ol.InputName = {'w', 'f', 'F'};
G_ol.OutputName = {'x1', 'Fs'};
G = G_ol({'Fs'}, {'f'});
#+end_src
The obtained dynamics is shown in Figure [[fig:piezo_amplified_iff_plant]].
#+begin_src matlab :exports none
freqs = logspace(1, 5, 1000);
figure;
tiledlayout(3, 1, 'TileSpacing', 'None', 'Padding', 'None');
ax1 = nexttile([2,1]);
hold on;
plot(freqs, abs(squeeze(freqresp(G, freqs, 'Hz'))));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude'); set(gca, 'XTickLabel',[]);
hold off;
ax2 = nexttile;
hold on;
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G, freqs, 'Hz')))));
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
yticks(-360:90:360);
ylim([-390 30]);
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
hold off;
linkaxes([ax1,ax2],'x');
xlim([freqs(1), freqs(end)]);
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/piezo_amplified_iff_plant.pdf', 'width', 'wide', 'height', 'tall');
#+end_src
#+name: fig:piezo_amplified_iff_plant
#+caption: IFF Plant
#+RESULTS:
[[file:figs/piezo_amplified_iff_plant.png]]
The controller is defined below and the loop gain is shown in Figure [[fig:piezo_amplified_iff_loop_gain]].
#+begin_src matlab
Kiff = -1e3/s;
#+end_src
#+begin_src matlab :exports none
freqs = logspace(1, 5, 1000);
figure;
tiledlayout(3, 1, 'TileSpacing', 'None', 'Padding', 'None');
ax1 = nexttile([2,1]);
hold on;
plot(freqs, abs(squeeze(freqresp(G*Kiff, freqs, 'Hz'))));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude'); set(gca, 'XTickLabel',[]);
hold off;
ax2 = nexttile;
hold on;
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G*Kiff, freqs, 'Hz')))));
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
yticks(-360:90:360);
ylim([-180 180]);
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
hold off;
linkaxes([ax1,ax2],'x');
xlim([freqs(1), freqs(end)]);
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/piezo_amplified_iff_loop_gain.pdf', 'width', 'wide', 'height', 'tall');
#+end_src
#+name: fig:piezo_amplified_iff_loop_gain
#+caption: IFF Loop Gain
#+RESULTS:
[[file:figs/piezo_amplified_iff_loop_gain.png]]
Now the closed-loop system is identified again and compare with the open loop system in Figure [[fig:piezo_amplified_iff_comp]].
It is the expected behavior as shown in the Figure [[fig:souleille18_results]] (from cite:souleille18_concep_activ_mount_space_applic).
#+begin_src matlab :exports none
clear io; io_i = 1;
io(io_i) = linio([mdl, '/w'], 1, 'openinput'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/F'], 1, 'openinput'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/Fd'], 1, 'openinput'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/z'], 1, 'openoutput'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/APA300ML'], 1, 'output'); io_i = io_i + 1;
Giff = linearize(mdl, io);
Giff.InputName = {'w', 'f', 'F'};
Giff.OutputName = {'x1', 'Fs'};
#+end_src
#+begin_src matlab :exports none
freqs = logspace(0, 3, 1000);
figure;
tiledlayout(2, 3, 'TileSpacing', 'None', 'Padding', 'None');
ax1 = nexttile;
hold on;
plot(freqs, abs(squeeze(freqresp(G_ol('x1', 'w'), freqs, 'Hz'))));
plot(freqs, abs(squeeze(freqresp(Giff('x1', 'w'), freqs, 'Hz'))));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
set(gca, 'XTickLabel',[]); ylabel('$x_1/w$ [m/m]')
ax2 = nexttile;
hold on;
plot(freqs, abs(squeeze(freqresp(G_ol('x1', 'f'), freqs, 'Hz'))));
plot(freqs, abs(squeeze(freqresp(Giff('x1', 'f'), freqs, 'Hz'))));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
set(gca, 'XTickLabel',[]); ylabel('$x_1/f$ [m/N]');
ax3 = nexttile;
hold on;
plot(freqs, abs(squeeze(freqresp(G_ol('x1', 'F'), freqs, 'Hz'))));
plot(freqs, abs(squeeze(freqresp(Giff('x1', 'F'), freqs, 'Hz'))));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
set(gca, 'XTickLabel',[]); ylabel('$x_1/F$ [m/N]');
ax4 = nexttile;
hold on;
plot(freqs, abs(squeeze(freqresp(G_ol('Fs', 'w'), freqs, 'Hz'))));
plot(freqs, abs(squeeze(freqresp(Giff('Fs', 'w'), freqs, 'Hz'))));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xlabel('Frequency [Hz]'); ylabel('$F_s/w$ [N/m]');
ax5 = nexttile;
hold on;
plot(freqs, abs(squeeze(freqresp(G_ol('Fs', 'f'), freqs, 'Hz'))));
plot(freqs, abs(squeeze(freqresp(Giff('Fs', 'f'), freqs, 'Hz'))));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xlabel('Frequency [Hz]'); ylabel('$F_s/f$ [N/N]');
ax6 = nexttile;
hold on;
plot(freqs, abs(squeeze(freqresp(G_ol('Fs', 'F'), freqs, 'Hz'))));
plot(freqs, abs(squeeze(freqresp(Giff('Fs', 'F'), freqs, 'Hz'))));
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xlabel('Frequency [Hz]'); ylabel('$F_s/F$ [N/N]');
linkaxes([ax1,ax2,ax3,ax4,ax5,ax6],'x');
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/piezo_amplified_iff_comp.pdf', 'width', 'full', 'height', 'full');
#+end_src
#+name: fig:piezo_amplified_iff_comp
#+caption: OL and CL transfer functions
#+RESULTS:
[[file:figs/piezo_amplified_iff_comp.png]]
#+name: fig:souleille18_results
#+caption: Results obtained in cite:souleille18_concep_activ_mount_space_applic
2024-03-19 15:33:09 +01:00
#+attr_latex: :width 1.0\linewidth
2020-11-12 18:40:48 +01:00
[[file:figs/souleille18_results.png]]
2020-11-12 17:33:52 +01:00
* First Flexible Joint Geometry
2020-11-12 17:46:28 +01:00
:PROPERTIES:
:header-args:matlab+: :tangle matlab/flexor_ID16.m
:END:
<<sec:flexor_ID16>>
2020-10-29 13:37:06 +01:00
** Introduction :ignore:
The studied flexor is shown in Figure [[fig:flexor_id16_screenshot]].
The stiffness and mass matrices representing the dynamics of the flexor are exported from a FEM.
It is then imported into Simscape.
A simplified model of the flexor is then developped.
#+name: fig:flexor_id16_screenshot
#+caption: Flexor studied
2024-03-19 15:33:09 +01:00
#+attr_latex: :width 0.3\linewidth
2020-10-29 13:37:06 +01:00
[[file:figs/flexor_id16_screenshot.png]]
** Matlab Init :noexport:ignore:
#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name)
<<matlab-dir>>
#+end_src
#+begin_src matlab :exports none :results silent :noweb yes
<<matlab-init>>
#+end_src
2020-11-12 17:46:28 +01:00
#+begin_src matlab :tangle no
addpath('matlab/');
addpath('matlab/flexor_ID16/');
2020-10-29 13:37:06 +01:00
#+end_src
2020-11-12 17:46:28 +01:00
#+begin_src matlab :eval no
addpath('flexor_ID16/');
#+end_src
#+begin_src matlab
2020-10-29 13:37:06 +01:00
open('flexor_ID16.slx');
#+end_src
** Import Mass Matrix, Stiffness Matrix, and Interface Nodes Coordinates
We first extract the stiffness and mass matrices.
#+begin_src matlab
K = extractMatrix('mat_K_6modes_2MDoF.matrix');
M = extractMatrix('mat_M_6modes_2MDoF.matrix');
#+end_src
2020-07-31 13:57:13 +02:00
#+begin_src matlab :exports results :results value table replace :tangle no
data2orgtable(K(1:10, 1:10), {}, {}, ' %.2e ');
#+end_src
2024-03-19 15:33:09 +01:00
#+name: tab:APA300ML_mat_K_2MDoF
2020-07-31 13:57:13 +02:00
#+caption: First 10x10 elements of the Stiffness matrix
2024-03-19 15:33:09 +01:00
#+attr_latex: :environment tabularx :width \linewidth :align XXXXXXXXXX
#+attr_latex: :center t :booktabs t :font \tiny
2020-07-31 13:57:13 +02:00
#+RESULTS:
2024-03-19 15:33:09 +01:00
| 11200000 | 195 | 2220 | -0.719 | -265 | 1.59 | -11200000 | -213 | -2220 | 0.147 | | 195 | 11400000 | 1290 | -148 | -0.188 | 2.41 | -212 | -11400000 | -1290 | 148 |
| 2220 | 1290 | 119000000 | 1.31 | 1.49 | 1.79 | -2220 | -1290 | -119000000 | -1.31 | | | | | | | | | | | |
| -0.719 | -148 | 1.31 | 33 | 000488 | -000977 | 0.141 | 148 | -1.31 | -33 | | | | | | | | | | | |
| -265 | -0.188 | 1.49 | 000488 | 33 | 00293 | 266 | 0.154 | -1.49 | 00026 | | | | | | | | | | | |
| 1.59 | 2.41 | 1.79 | -000977 | 00293 | 236 | -1.32 | -2.55 | -1.79 | 000379 | | | | | | | | | | | |
| -11200000 | -212 | -2220 | 0.141 | 266 | -1.32 | 11400000 | 24600 | 1640 | 120 | | | | | | | | | | | |
| -213 | -11400000 | -1290 | 148 | 0.154 | -2.55 | 24600 | 11400000 | 1290 | -72 | | | | | | | | | | | |
| -2220 | -1290 | -119000000 | -1.31 | -1.49 | -1.79 | 1640 | 1290 | 119000000 | 1.32 | | | | | | | | | | | |
| 0.147 | 148 | -1.31 | -33 | 00026 | 000379 | 120 | -72 | 1.32 | 34.7 | | | | | | | | | | | |
2020-07-31 13:57:13 +02:00
#+begin_src matlab :exports results :results value table replace :tangle no
data2orgtable(M(1:10, 1:10), {}, {}, ' %.1g ');
#+end_src
2024-03-19 15:33:09 +01:00
#+name: tab:APA300ML_mat_M_2MDoF
2020-07-31 13:57:13 +02:00
#+caption: First 10x10 elements of the Mass matrix
2024-03-19 15:33:09 +01:00
#+attr_latex: :environment tabularx :width \linewidth :align XXXXXXXXXX
#+attr_latex: :center t :booktabs t :font \tiny
2020-07-31 13:57:13 +02:00
#+RESULTS:
| 0.02 | 1e-09 | -4e-08 | -1e-10 | 0.0002 | -3e-11 | 0.004 | 5e-08 | 7e-08 | 1e-10 |
| 1e-09 | 0.02 | -3e-07 | -0.0002 | -1e-10 | -2e-09 | 2e-08 | 0.004 | 3e-07 | 1e-05 |
| -4e-08 | -3e-07 | 0.02 | 7e-10 | -2e-09 | 1e-09 | 3e-07 | 7e-08 | 0.003 | 1e-09 |
| -1e-10 | -0.0002 | 7e-10 | 4e-06 | -1e-12 | -6e-13 | 2e-10 | -7e-06 | -8e-10 | -1e-09 |
| 0.0002 | -1e-10 | -2e-09 | -1e-12 | 3e-06 | 2e-13 | 9e-06 | 4e-11 | 2e-09 | -3e-13 |
| -3e-11 | -2e-09 | 1e-09 | -6e-13 | 2e-13 | 4e-07 | 8e-11 | 9e-10 | -1e-09 | 2e-12 |
| 0.004 | 2e-08 | 3e-07 | 2e-10 | 9e-06 | 8e-11 | 0.02 | -7e-08 | -3e-07 | -2e-10 |
| 5e-08 | 0.004 | 7e-08 | -7e-06 | 4e-11 | 9e-10 | -7e-08 | 0.01 | -4e-08 | 0.0002 |
| 7e-08 | 3e-07 | 0.003 | -8e-10 | 2e-09 | -1e-09 | -3e-07 | -4e-08 | 0.02 | -1e-09 |
| 1e-10 | 1e-05 | 1e-09 | -1e-09 | -3e-13 | 2e-12 | -2e-10 | 0.0002 | -1e-09 | 2e-06 |
2024-03-19 15:33:09 +01:00
#+begin_src matlab :exports results :results value table replace :tangle no
data2orgtable([length(n_i); length(int_i); size(M,1) - 6*length(int_i); size(M,1)], {'Total number of Nodes', 'Number of interface Nodes', 'Number of Modes', 'Size of M and K matrices'}, {}, ' %.0f ');
#+end_src
#+name: tab:parameters_fem_2MDoF
#+caption: Some extracted parameters of the FEM
#+attr_latex: :environment tabularx :width 0.4\linewidth :align lc
#+attr_latex: :center t :booktabs t
#+RESULTS:
| Total number of Nodes | 2 |
| Number of interface Nodes | 2 |
| Number of Modes | 6 |
| Size of M and K matrices | 18 |
2020-11-12 17:46:28 +01:00
Then, we extract the coordinates of the interface nodes.
#+begin_src matlab
[int_xyz, int_i, n_xyz, n_i, nodes] = extractNodes('out_nodes_3D.txt');
#+end_src
2020-07-31 13:57:13 +02:00
#+begin_src matlab :exports results :results value table replace :tangle no :post addhdr(*this*)
2020-11-12 17:46:28 +01:00
data2orgtable([[1:length(int_i)]', int_i, int_xyz], {}, {'Node i', 'Node Number', 'x [m]', 'y [m]', 'z [m]'}, ' %f ');
#+end_src
2024-03-19 15:33:09 +01:00
#+name: tab:coordinate_nodes_2MDoF
2020-11-12 17:46:28 +01:00
#+caption: Coordinates of the interface nodes
2024-03-19 15:33:09 +01:00
#+attr_latex: :environment tabularx :width 0.6\linewidth :align ccccc
#+attr_latex: :center t :booktabs t
2020-11-12 17:46:28 +01:00
#+RESULTS:
| Node i | Node Number | x [m] | y [m] | z [m] |
|--------+-------------+-------+-------+-------|
| 1.0 | 181278.0 | 0.0 | 0.0 | 0.0 |
| 2.0 | 181279.0 | 0.0 | 0.0 | -0.0 |
Using =K=, =M= and =int_xyz=, we can use the =Reduced Order Flexible Solid= simscape block.
** Identification of the parameters using Simscape and looking at the Stiffness Matrix
The flexor is now imported into Simscape and its parameters are estimated using an identification.
#+begin_src matlab :exports none
m = 1;
2020-07-31 13:57:13 +02:00
#+end_src
The dynamics is identified from the applied force/torque to the measured displacement/rotation of the flexor.
#+begin_src matlab :exports none
2020-07-31 13:57:13 +02:00
%% Name of the Simulink File
mdl = 'flexor_ID16';
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/T'], 1, 'openinput'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/D'], 1, 'openoutput'); io_i = io_i + 1;
G = linearize(mdl, io);
#+end_src
And we find the same parameters as the one estimated from the Stiffness matrix.
2020-07-31 13:57:13 +02:00
#+begin_src matlab :exports results :results value table replace :tangle no :post addhdr(*this*)
2024-03-19 15:33:09 +01:00
data2orgtable([1e-6*K(3,3), K(4,4), K(5,5), K(6,6) ; 1e-6./dcgain(G(3,3)), 1./dcgain(G(4,4)), 1./dcgain(G(5,5)), 1./dcgain(G(6,6))]', {'Axial Stiffness Dz [N/um]', 'Bending Stiffness Rx [Nm/rad]', 'Bending Stiffness Ry [Nm/rad]', 'Torsion Stiffness Rz [Nm/rad]'}, {'*Characteristic*', '*Value*', '*Identification*'}, ' %0.f ');
2020-07-31 13:57:13 +02:00
#+end_src
2024-03-19 15:33:09 +01:00
#+name: tab:comp_identified_stiffnesses
#+caption: Comparison of identified and FEM stiffnesses
#+attr_latex: :environment tabularx :width 0.7\linewidth :align lcc
#+attr_latex: :center t :booktabs t
2020-07-31 13:57:13 +02:00
#+RESULTS:
2024-03-19 15:33:09 +01:00
| *Characteristic* | *Value* | *Identification* |
2020-07-31 13:57:13 +02:00
|-------------------------------+---------+------------------|
| Axial Stiffness Dz [N/um] | 119 | 119 |
2020-11-12 17:46:28 +01:00
| Bending Stiffness Rx [Nm/rad] | 33 | 33 |
| Bending Stiffness Ry [Nm/rad] | 33 | 33 |
| Torsion Stiffness Rz [Nm/rad] | 236 | 236 |
2020-07-31 13:57:13 +02:00
** Simpler Model
Let's now model the flexible joint with a "perfect" Bushing joint as shown in Figure [[fig:flexible_joint_simscape]].
2020-07-31 13:57:13 +02:00
#+name: fig:flexible_joint_simscape
#+caption: Bushing Joint used to model the flexible joint
2024-03-19 15:33:09 +01:00
#+attr_latex: :width 0.3\linewidth
[[file:figs/flexible_joint_simscape.png]]
2020-07-31 13:57:13 +02:00
The parameters of the Bushing joint (stiffnesses) are estimated from the Stiffness matrix that was computed from the FEM.
#+begin_src matlab
Kx = K(1,1); % [N/m]
Ky = K(2,2); % [N/m]
Kz = K(3,3); % [N/m]
Krx = K(4,4); % [Nm/rad]
Kry = K(5,5); % [Nm/rad]
Krz = K(6,6); % [Nm/rad]
#+end_src
The dynamics from the applied force/torque to the measured displacement/rotation of the flexor is identified again for this simpler model.
#+begin_src matlab :exports none
%% Name of the Simulink File
mdl = 'flexor_ID16_simplified';
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/T'], 1, 'openinput'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/D'], 1, 'openoutput'); io_i = io_i + 1;
Gs = linearize(mdl, io);
2020-07-31 13:57:13 +02:00
#+end_src
The two obtained dynamics are compared in Figure
2020-07-31 13:57:13 +02:00
#+begin_src matlab :exports none
freqs = logspace(0, 5, 1000);
figure;
2020-11-12 17:46:28 +01:00
tiledlayout(1, 2, 'TileSpacing', 'None', 'Padding', 'None');
2020-07-31 13:57:13 +02:00
2020-11-12 17:46:28 +01:00
ax1 = nexttile;
2020-07-31 13:57:13 +02:00
hold on;
set(gca,'ColorOrderIndex',1)
plot(freqs, abs(squeeze(freqresp(G(1,1), freqs, 'Hz'))), '-', 'DisplayName', '$D_x/F_x$');
set(gca,'ColorOrderIndex',1)
plot(freqs, abs(squeeze(freqresp(Gs(1,1), freqs, 'Hz'))), '--', 'HandleVisibility', 'off');
set(gca,'ColorOrderIndex',2)
plot(freqs, abs(squeeze(freqresp(G(2,2), freqs, 'Hz'))), '-', 'DisplayName', '$D_y/F_y$');
set(gca,'ColorOrderIndex',2)
plot(freqs, abs(squeeze(freqresp(Gs(2,2), freqs, 'Hz'))), '--', 'HandleVisibility', 'off');
set(gca,'ColorOrderIndex',3)
plot(freqs, abs(squeeze(freqresp(G(3,3), freqs, 'Hz'))), '-', 'DisplayName', '$D_z/F_z$');
set(gca,'ColorOrderIndex',3)
plot(freqs, abs(squeeze(freqresp(Gs(3,3), freqs, 'Hz'))), '--', 'HandleVisibility', 'off');
2020-07-31 13:57:13 +02:00
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xlabel('Frequency [Hz]'); ylabel('Amplitude [m/N]');
2020-07-31 13:57:13 +02:00
hold off;
2020-11-12 17:46:28 +01:00
legend('location', 'southwest');
2020-07-31 13:57:13 +02:00
2020-11-12 17:46:28 +01:00
ax2 = nexttile;
hold on;
set(gca,'ColorOrderIndex',1)
plot(freqs, abs(squeeze(freqresp(G(4,4), freqs, 'Hz'))), '-', 'DisplayName', '$R_x/M_x$');
set(gca,'ColorOrderIndex',1)
plot(freqs, abs(squeeze(freqresp(Gs(4,4), freqs, 'Hz'))), '--', 'HandleVisibility', 'off');
set(gca,'ColorOrderIndex',2)
plot(freqs, abs(squeeze(freqresp(G(5,5), freqs, 'Hz'))), '-', 'DisplayName', '$R_y/M_y$');
set(gca,'ColorOrderIndex',2)
plot(freqs, abs(squeeze(freqresp(Gs(5,5), freqs, 'Hz'))), '--', 'HandleVisibility', 'off');
set(gca,'ColorOrderIndex',3)
plot(freqs, abs(squeeze(freqresp(G(6,6), freqs, 'Hz'))), '-', 'DisplayName', '$R_z/M_z$');
set(gca,'ColorOrderIndex',3)
plot(freqs, abs(squeeze(freqresp(Gs(6,6), freqs, 'Hz'))), '--', 'HandleVisibility', 'off');
2020-07-31 13:57:13 +02:00
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xlabel('Frequency [Hz]'); ylabel('Amplitude [rad/Nm]');
hold off;
2020-11-12 17:46:28 +01:00
legend('location', 'southwest');
2020-07-31 13:57:13 +02:00
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
2020-11-12 17:46:28 +01:00
exportFig('figs/flexor_ID16_compare_bushing_joint.pdf', 'width', 'wide', 'height', 'normal');
#+end_src
#+name: fig:flexor_ID16_compare_bushing_joint
#+caption: Comparison of the Joint compliance between the FEM model and the simpler model
#+RESULTS:
[[file:figs/flexor_ID16_compare_bushing_joint.png]]
2020-11-12 17:33:52 +01:00
* Optimized Flexible Joint
2020-11-12 17:46:28 +01:00
:PROPERTIES:
:header-args:matlab+: :tangle matlab/flexor_025.m
:END:
<<sec:flexor_025>>
2020-10-29 13:37:06 +01:00
** Introduction :ignore:
2020-11-12 17:33:52 +01:00
2020-11-12 17:46:28 +01:00
The joint geometry has been optimized using Ansys to have lower bending stiffness while keeping a large axial stiffness.
The obtained geometry is shown in Figure [[fig:optimal_flexor]].
2020-10-29 13:37:06 +01:00
#+name: fig:optimal_flexor
#+caption: Flexor studied
2024-03-19 15:33:09 +01:00
#+attr_latex: :width 1.0\linewidth
2020-11-12 17:46:28 +01:00
[[file:figs/flexor_025_MDoF.jpg]]
2020-10-29 13:37:06 +01:00
2020-11-12 17:46:28 +01:00
** Matlab Init :noexport:ignore:
2020-10-29 13:37:06 +01:00
#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name)
<<matlab-dir>>
#+end_src
#+begin_src matlab :exports none :results silent :noweb yes
<<matlab-init>>
#+end_src
2020-11-12 17:46:28 +01:00
#+begin_src matlab :tangle no
addpath('matlab/');
addpath('matlab/flexor_025/');
2020-10-29 13:37:06 +01:00
#+end_src
2020-11-12 17:46:28 +01:00
#+begin_src matlab :eval no
addpath('flexor_025/');
#+end_src
#+begin_src matlab
2020-10-29 13:37:06 +01:00
open('flexor_025.slx');
#+end_src
** Import Mass Matrix, Stiffness Matrix, and Interface Nodes Coordinates
We first extract the stiffness and mass matrices.
#+begin_src matlab
2020-11-12 18:40:48 +01:00
K = readmatrix('flex025_mat_K.CSV');
M = readmatrix('flex025_mat_M.CSV');
2020-10-29 13:37:06 +01:00
#+end_src
#+begin_src matlab :exports results :results value table replace :tangle no
data2orgtable(K(1:10, 1:10), {}, {}, ' %.2e ');
#+end_src
2024-03-19 15:33:09 +01:00
#+name: tab:flex_mat_K
2020-10-29 13:37:06 +01:00
#+caption: First 10x10 elements of the Stiffness matrix
2024-03-19 15:33:09 +01:00
#+attr_latex: :environment tabularx :width \linewidth :align XXXXXXXXXX
#+attr_latex: :center t :booktabs t :font \tiny
2020-10-29 13:37:06 +01:00
#+RESULTS:
2024-03-19 15:33:09 +01:00
| 12700000 | -18.5 | -26.8 | 00162 | -4.63 | 64 | -12700000 | 18.3 | 26.7 | 00234 |
| -18.5 | 12700000 | -499 | -132 | 00414 | -0.495 | 18.4 | -12700000 | 499 | 132 |
| -26.8 | -499 | 94000000 | -470 | 00771 | -0.855 | 26.8 | 498 | -94000000 | 470 |
| 00162 | -132 | -470 | 4.83 | 2.61e-07 | 000123 | -00163 | 132 | 470 | -4.83 |
| -4.63 | 00414 | 00771 | 2.61e-07 | 4.83 | 4.43e-05 | 4.63 | -00413 | -00772 | -4.3e-07 |
| 64 | -0.495 | -0.855 | 000123 | 4.43e-05 | 260 | -64 | 0.495 | 0.855 | -000124 |
| -12700000 | 18.4 | 26.8 | -00163 | 4.63 | -64 | 12700000 | -18.2 | -26.7 | -00234 |
| 18.3 | -12700000 | 498 | 132 | -00413 | 0.495 | -18.2 | 12700000 | -498 | -132 |
| 26.7 | 499 | -94000000 | 470 | -00772 | 0.855 | -26.7 | -498 | 94000000 | -470 |
| 00234 | 132 | 470 | -4.83 | -4.3e-07 | -000124 | -00234 | -132 | -470 | 4.83 |
2020-10-29 13:37:06 +01:00
#+begin_src matlab :exports results :results value table replace :tangle no
data2orgtable(M(1:10, 1:10), {}, {}, ' %.1g ');
#+end_src
2024-03-19 15:33:09 +01:00
#+name: tab:flex_mat_M
2020-10-29 13:37:06 +01:00
#+caption: First 10x10 elements of the Mass matrix
2024-03-19 15:33:09 +01:00
#+attr_latex: :environment tabularx :width \linewidth :align XXXXXXXXXX
#+attr_latex: :center t :booktabs t :font \tiny
2020-10-29 13:37:06 +01:00
#+RESULTS:
| 0.006 | 8e-09 | -2e-08 | -1e-10 | 3e-05 | 3e-08 | 0.003 | -3e-09 | 9e-09 | 2e-12 |
| 8e-09 | 0.02 | 1e-07 | -3e-05 | 1e-11 | 6e-10 | 1e-08 | 0.003 | -5e-08 | 3e-09 |
| -2e-08 | 1e-07 | 0.01 | -6e-08 | -6e-11 | -8e-12 | -1e-07 | 1e-08 | 0.003 | -1e-08 |
| -1e-10 | -3e-05 | -6e-08 | 1e-06 | 7e-14 | 6e-13 | 1e-10 | 1e-06 | -1e-08 | 3e-10 |
| 3e-05 | 1e-11 | -6e-11 | 7e-14 | 2e-07 | 1e-10 | 3e-08 | -7e-12 | 6e-11 | -6e-16 |
| 3e-08 | 6e-10 | -8e-12 | 6e-13 | 1e-10 | 5e-07 | 1e-08 | -5e-10 | -1e-11 | 1e-13 |
| 0.003 | 1e-08 | -1e-07 | 1e-10 | 3e-08 | 1e-08 | 0.02 | -2e-08 | 1e-07 | -4e-12 |
| -3e-09 | 0.003 | 1e-08 | 1e-06 | -7e-12 | -5e-10 | -2e-08 | 0.006 | -8e-08 | 3e-05 |
| 9e-09 | -5e-08 | 0.003 | -1e-08 | 6e-11 | -1e-11 | 1e-07 | -8e-08 | 0.01 | -6e-08 |
| 2e-12 | 3e-09 | -1e-08 | 3e-10 | -6e-16 | 1e-13 | -4e-12 | 3e-05 | -6e-08 | 2e-07 |
2020-11-12 17:46:28 +01:00
Then, we extract the coordinates of the interface nodes.
#+begin_src matlab
2020-11-12 18:40:48 +01:00
[int_xyz, int_i, n_xyz, n_i, nodes] = extractNodes('flex025_out_nodes_3D.txt');
2020-11-12 17:46:28 +01:00
#+end_src
#+begin_src matlab :exports results :results value table replace :tangle no
data2orgtable([length(n_i); length(int_i); size(M,1) - 6*length(int_i); size(M,1)], {'Total number of Nodes', 'Number of interface Nodes', 'Number of Modes', 'Size of M and K matrices'}, {}, ' %.0f ');
#+end_src
2024-03-19 15:33:09 +01:00
#+name: tab:coordinate_nodes_flex
#+caption: Coordinates of the interface nodes for Flexible Joint
#+attr_latex: :environment tabularx :width 0.6\linewidth :align ccccc
#+attr_latex: :center t :booktabs t
2020-11-12 17:46:28 +01:00
#+RESULTS:
| Total number of Nodes | 2 |
| Number of interface Nodes | 2 |
| Number of Modes | 6 |
| Size of M and K matrices | 18 |
2020-10-29 13:37:06 +01:00
#+begin_src matlab :exports results :results value table replace :tangle no :post addhdr(*this*)
2020-11-12 17:46:28 +01:00
data2orgtable([[1:length(int_i)]', int_i, int_xyz], {}, {'Node i', 'Node Number', 'x [m]', 'y [m]', 'z [m]'}, ' %f ');
2020-10-29 13:37:06 +01:00
#+end_src
2024-03-19 15:33:09 +01:00
#+name: tab:coordinate_interface_nodes_flex
2020-11-12 17:46:28 +01:00
#+caption: Coordinates of the interface nodes
2024-03-19 15:33:09 +01:00
#+attr_latex: :environment tabularx :width 0.6\linewidth :align ccccc
#+attr_latex: :center t :booktabs t
2020-10-29 13:37:06 +01:00
#+RESULTS:
2020-11-12 17:46:28 +01:00
| Node i | Node Number | x [m] | y [m] | z [m] |
|--------+-------------+-------+-------+-------|
| 1.0 | 528875.0 | 0.0 | 0.0 | 0.0 |
| 2.0 | 528876.0 | 0.0 | 0.0 | -0.0 |
Using =K=, =M= and =int_xyz=, we can use the =Reduced Order Flexible Solid= simscape block.
2020-10-29 13:37:06 +01:00
** Identification of the parameters using Simscape
The flexor is now imported into Simscape and its parameters are estimated using an identification.
#+begin_src matlab :exports none
m = 1;
#+end_src
The dynamics is identified from the applied force/torque to the measured displacement/rotation of the flexor.
#+begin_src matlab :exports none
%% Name of the Simulink File
mdl = 'flexor_025';
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/T'], 1, 'openinput'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/D'], 1, 'openoutput'); io_i = io_i + 1;
G = linearize(mdl, io);
#+end_src
And we find the same parameters as the one estimated from the Stiffness matrix.
#+begin_src matlab :exports results :results value table replace :tangle no :post addhdr(*this*)
data2orgtable([1e-6*K(3,3), K(4,4), K(5,5), K(6,6) ; 1e-6./dcgain(G(3,3)), 1./dcgain(G(4,4)), 1./dcgain(G(5,5)), 1./dcgain(G(6,6))]', {'Axial Stiffness Dz [N/um]', 'Bending Stiffness Rx [Nm/rad]', 'Bending Stiffness Ry [Nm/rad]', 'Torsion Stiffness Rz [Nm/rad]'}, {'*Caracteristic*', '*Value*', '*Identification*'}, ' %.1f ');
#+end_src
2024-03-19 15:33:09 +01:00
#+name: tab:comp_identified_stiffnesses_flex
#+caption: Comparison of identified and FEM stiffnesses
#+attr_latex: :environment tabularx :width 0.7\linewidth :align lcc
#+attr_latex: :center t :booktabs t
2020-10-29 13:37:06 +01:00
#+RESULTS:
| *Caracteristic* | *Value* | *Identification* |
|-------------------------------+---------+------------------|
| Axial Stiffness Dz [N/um] | 94.0 | 93.9 |
| Bending Stiffness Rx [Nm/rad] | 4.8 | 4.8 |
| Bending Stiffness Ry [Nm/rad] | 4.8 | 4.8 |
| Torsion Stiffness Rz [Nm/rad] | 260.2 | 260.2 |
** Simpler Model
Let's now model the flexible joint with a "perfect" Bushing joint as shown in Figure [[fig:flexible_joint_simscape]].
The parameters of the Bushing joint (stiffnesses) are estimated from the Stiffness matrix that was computed from the FEM.
#+begin_src matlab
Kx = K(1,1); % [N/m]
Ky = K(2,2); % [N/m]
Kz = K(3,3); % [N/m]
Krx = K(4,4); % [Nm/rad]
Kry = K(5,5); % [Nm/rad]
Krz = K(6,6); % [Nm/rad]
#+end_src
The dynamics from the applied force/torque to the measured displacement/rotation of the flexor is identified again for this simpler model.
#+begin_src matlab :exports none
%% Name of the Simulink File
mdl = 'flexor_025_simplified';
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/T'], 1, 'openinput'); io_i = io_i + 1;
io(io_i) = linio([mdl, '/D'], 1, 'openoutput'); io_i = io_i + 1;
Gs = linearize(mdl, io);
#+end_src
The two obtained dynamics are compared in Figure
#+begin_src matlab :exports none
freqs = logspace(0, 5, 1000);
figure;
2020-11-12 17:46:28 +01:00
tiledlayout(1, 2, 'TileSpacing', 'None', 'Padding', 'None');
2020-10-29 13:37:06 +01:00
2020-11-12 17:46:28 +01:00
ax1 = nexttile;
2020-10-29 13:37:06 +01:00
hold on;
set(gca,'ColorOrderIndex',1)
plot(freqs, abs(squeeze(freqresp(G(1,1), freqs, 'Hz'))), '-', 'DisplayName', '$D_x/F_x$');
set(gca,'ColorOrderIndex',1)
plot(freqs, abs(squeeze(freqresp(Gs(1,1), freqs, 'Hz'))), '--', 'HandleVisibility', 'off');
set(gca,'ColorOrderIndex',2)
plot(freqs, abs(squeeze(freqresp(G(2,2), freqs, 'Hz'))), '-', 'DisplayName', '$D_y/F_y$');
set(gca,'ColorOrderIndex',2)
plot(freqs, abs(squeeze(freqresp(Gs(2,2), freqs, 'Hz'))), '--', 'HandleVisibility', 'off');
set(gca,'ColorOrderIndex',3)
plot(freqs, abs(squeeze(freqresp(G(3,3), freqs, 'Hz'))), '-', 'DisplayName', '$D_z/F_z$');
set(gca,'ColorOrderIndex',3)
plot(freqs, abs(squeeze(freqresp(Gs(3,3), freqs, 'Hz'))), '--', 'HandleVisibility', 'off');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xlabel('Frequency [Hz]'); ylabel('Amplitude [m/N]');
hold off;
2020-11-12 17:46:28 +01:00
legend('location', 'southwest');
2020-10-29 13:37:06 +01:00
2020-11-12 17:46:28 +01:00
ax2 = nexttile;
2020-10-29 13:37:06 +01:00
hold on;
set(gca,'ColorOrderIndex',1)
plot(freqs, abs(squeeze(freqresp(G(4,4), freqs, 'Hz'))), '-', 'DisplayName', '$R_x/M_x$');
set(gca,'ColorOrderIndex',1)
plot(freqs, abs(squeeze(freqresp(Gs(4,4), freqs, 'Hz'))), '--', 'HandleVisibility', 'off');
set(gca,'ColorOrderIndex',2)
plot(freqs, abs(squeeze(freqresp(G(5,5), freqs, 'Hz'))), '-', 'DisplayName', '$R_y/M_y$');
set(gca,'ColorOrderIndex',2)
plot(freqs, abs(squeeze(freqresp(Gs(5,5), freqs, 'Hz'))), '--', 'HandleVisibility', 'off');
set(gca,'ColorOrderIndex',3)
plot(freqs, abs(squeeze(freqresp(G(6,6), freqs, 'Hz'))), '-', 'DisplayName', '$R_z/M_z$');
set(gca,'ColorOrderIndex',3)
plot(freqs, abs(squeeze(freqresp(Gs(6,6), freqs, 'Hz'))), '--', 'HandleVisibility', 'off');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xlabel('Frequency [Hz]'); ylabel('Amplitude [rad/Nm]');
hold off;
2020-11-12 17:46:28 +01:00
legend('location', 'southwest');
2020-10-29 13:37:06 +01:00
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
2024-03-19 15:33:09 +01:00
exportFig('figs/flexor_ID16_compare_bushing_joint_optimized.pdf', 'width', 'wide', 'height', 'normal');
2020-10-29 13:37:06 +01:00
#+end_src
2024-03-19 15:33:09 +01:00
#+name: fig:flexor_ID16_compare_bushing_joint_optimized
2020-10-29 13:37:06 +01:00
#+caption: Comparison of the Joint compliance between the FEM model and the simpler model
#+RESULTS:
2024-03-19 15:33:09 +01:00
[[file:figs/flexor_ID16_compare_bushing_joint_optimized.png]]
2020-10-29 13:37:06 +01:00
2020-11-12 18:40:48 +01:00
** Comparison with a stiffer Flexible Joint
The stiffness matrix with the flexible joint with a "hinge" size of 0.50mm is loaded.
2020-06-15 09:13:55 +02:00
#+begin_src matlab
2020-11-12 18:40:48 +01:00
K_050 = readmatrix('flex050_mat_K.CSV');
2020-06-15 09:13:55 +02:00
#+end_src
2020-11-12 18:40:48 +01:00
Its parameters are compared with the Flexible Joint with a size of 0.25mm in the table below.
2020-06-15 09:13:55 +02:00
2020-11-12 18:40:48 +01:00
#+begin_src matlab :exports results :results value table replace :tangle no :post addhdr(*this*)
data2orgtable([1e-6*K(3,3), 1e-6*K(2,2), K(4,4), K(5,5), K(6,6) ; 1e-6*K_050(3,3), 1e-6*K_050(2,2), K_050(4,4), K_050(5,5), K_050(6,6)]', {'Axial Stiffness Dz [N/um]', 'Shear Stiffness [N/um]', 'Bending Stiffness Rx [Nm/rad]', 'Bending Stiffness Ry [Nm/rad]', 'Torsion Stiffness Rz [Nm/rad]'}, {'*Caracteristic*', '*0.25 mm*', '*0.50 mm*'}, ' %.1f ');
2020-06-15 09:13:55 +02:00
#+end_src
2024-03-19 15:33:09 +01:00
#+name: tab:comp_stiffnesses_flex_size
#+caption: Comparison of flexible joint stiffnesses for 0.25 and 0.5mm
#+attr_latex: :environment tabularx :width 0.7\linewidth :align lcc
#+attr_latex: :center t :booktabs t
2020-06-15 09:13:55 +02:00
#+RESULTS:
2020-11-12 18:40:48 +01:00
| *Caracteristic* | *0.25 mm* | *0.50 mm* |
|-------------------------------+-----------+-----------|
| Axial Stiffness Dz [N/um] | 94.0 | 124.7 |
| Shear Stiffness [N/um] | 12.7 | 25.8 |
| Bending Stiffness Rx [Nm/rad] | 4.8 | 26.0 |
| Bending Stiffness Ry [Nm/rad] | 4.8 | 26.0 |
| Torsion Stiffness Rz [Nm/rad] | 260.2 | 538.0 |
2020-08-03 15:46:35 +02:00
2020-10-29 13:37:06 +01:00
* Complete Strut with Encoder
2020-11-12 18:49:34 +01:00
:PROPERTIES:
:header-args:matlab+: :tangle matlab/strut_encoder.m
:END:
<<sec:strut_encoder>>
2020-10-29 13:37:06 +01:00
** Introduction
2020-11-12 18:40:48 +01:00
Now, the full nano-hexapod strut is modelled using Ansys.
The 3D as well as the interface nodes are shown in Figure [[fig:strut_encoder_points3]].
2020-10-29 13:37:06 +01:00
#+name: fig:strut_encoder_points3
#+caption: Interface points
2024-03-19 15:33:09 +01:00
#+attr_latex: :width 1.0\linewidth
2021-01-04 13:58:12 +01:00
[[file:figs/strut_fem_nodes.jpg]]
2020-11-12 18:49:34 +01:00
A side view is shown in Figure [[fig:strut_encoder_nodes_side]].
#+name: fig:strut_encoder_nodes_side
#+caption: Interface points - Side view
2024-03-19 15:33:09 +01:00
#+attr_latex: :width 1.0\linewidth
2021-01-04 13:58:12 +01:00
[[file:figs/strut_fem_nodes_side.jpg]]
2020-10-29 13:37:06 +01:00
2020-11-12 18:40:48 +01:00
The flexible joints used have a 0.25mm width size.
2020-10-29 13:37:06 +01:00
** Matlab Init :noexport:ignore:
#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name)
<<matlab-dir>>
#+end_src
#+begin_src matlab :exports none :results silent :noweb yes
<<matlab-init>>
#+end_src
2020-11-12 18:49:34 +01:00
#+begin_src matlab :tangle no
addpath('matlab/');
addpath('matlab/strut_encoder/');
#+end_src
#+begin_src matlab :eval no
addpath('strut_encoder/');
2020-10-29 13:37:06 +01:00
#+end_src
#+begin_src matlab
open('strut_encoder.slx');
#+end_src
** Import Mass Matrix, Stiffness Matrix, and Interface Nodes Coordinates
We first extract the stiffness and mass matrices.
#+begin_src matlab
2020-11-12 18:49:34 +01:00
K = readmatrix('strut_encoder_mat_K.CSV');
M = readmatrix('strut_encoder_mat_M.CSV');
2020-10-29 13:37:06 +01:00
#+end_src
#+begin_src matlab :exports results :results value table replace :tangle no
data2orgtable(K(1:10, 1:10), {}, {}, ' %.1g ');
#+end_src
2024-03-19 15:33:09 +01:00
#+name: tab:strut_mat_K
2020-10-29 13:37:06 +01:00
#+caption: First 10x10 elements of the Stiffness matrix
2024-03-19 15:33:09 +01:00
#+attr_latex: :environment tabularx :width \linewidth :align XXXXXXXXXX
#+attr_latex: :center t :booktabs t :font \tiny
2020-10-29 13:37:06 +01:00
#+RESULTS:
2024-03-19 15:33:09 +01:00
| 2000000 | 1000000 | -3000000 | -400 | 300 | 200 | -30 | 2000 | -10000 | 0.3 |
| 1000000 | 4000000 | -8000000 | -900 | 400 | -50 | -6000 | 10000 | -20000 | 3 |
| -3000000 | -8000000 | 20000000 | 2000 | -900 | 200 | -10000 | 20000 | -300000 | 7 |
| -400 | -900 | 2000 | 5 | -0.1 | 05 | 1 | -3 | 6 | -0007 |
| 300 | 400 | -900 | -0.1 | 5 | 04 | -0.1 | 0.5 | -3 | 0001 |
| 200 | -50 | 200 | 05 | 04 | 300 | 4 | -01 | -1 | 3e-05 |
| -30 | -6000 | -10000 | 1 | -0.1 | 4 | 3000000 | -1000000 | -2000000 | -300 |
| 2000 | 10000 | 20000 | -3 | 0.5 | -01 | -1000000 | 6000000 | 7000000 | 1000 |
| -10000 | -20000 | -300000 | 6 | -3 | -1 | -2000000 | 7000000 | 20000000 | 2000 |
| 0.3 | 3 | 7 | -0007 | 0001 | 3e-05 | -300 | 1000 | 2000 | 5 |
2020-10-29 13:37:06 +01:00
#+begin_src matlab :exports results :results value table replace :tangle no
data2orgtable(M(1:10, 1:10), {}, {}, ' %.1g ');
#+end_src
2024-03-19 15:33:09 +01:00
#+name: tab:strut_mat_M
2020-10-29 13:37:06 +01:00
#+caption: First 10x10 elements of the Mass matrix
2024-03-19 15:33:09 +01:00
#+attr_latex: :environment tabularx :width \linewidth :align XXXXXXXXXX
#+attr_latex: :center t :booktabs t :font \tiny
2020-10-29 13:37:06 +01:00
#+RESULTS:
| 0.04 | -0.005 | 0.007 | 2e-06 | 0.0001 | -5e-07 | -1e-05 | -9e-07 | 8e-05 | -5e-10 |
| -0.005 | 0.03 | 0.02 | -0.0001 | 1e-06 | -3e-07 | 3e-05 | -0.0001 | 8e-05 | -3e-08 |
| 0.007 | 0.02 | 0.08 | -6e-06 | -5e-06 | -7e-07 | 4e-05 | -0.0001 | 0.0005 | -3e-08 |
| 2e-06 | -0.0001 | -6e-06 | 2e-06 | -4e-10 | 2e-11 | -8e-09 | 3e-08 | -2e-08 | 6e-12 |
| 0.0001 | 1e-06 | -5e-06 | -4e-10 | 3e-06 | 2e-10 | -3e-09 | 3e-09 | -7e-09 | 6e-13 |
| -5e-07 | -3e-07 | -7e-07 | 2e-11 | 2e-10 | 5e-07 | -2e-08 | 5e-09 | -5e-09 | 1e-12 |
| -1e-05 | 3e-05 | 4e-05 | -8e-09 | -3e-09 | -2e-08 | 0.04 | 0.004 | 0.003 | 1e-06 |
| -9e-07 | -0.0001 | -0.0001 | 3e-08 | 3e-09 | 5e-09 | 0.004 | 0.02 | -0.02 | 0.0001 |
| 8e-05 | 8e-05 | 0.0005 | -2e-08 | -7e-09 | -5e-09 | 0.003 | -0.02 | 0.08 | -5e-06 |
| -5e-10 | -3e-08 | -3e-08 | 6e-12 | 6e-13 | 1e-12 | 1e-06 | 0.0001 | -5e-06 | 2e-06 |
2020-11-12 18:49:34 +01:00
Then, we extract the coordinates of the interface nodes.
#+begin_src matlab
[int_xyz, int_i, n_xyz, n_i, nodes] = extractNodes('strut_encoder_out_nodes_3D.txt');
#+end_src
#+begin_src matlab :exports results :results value table replace :tangle no
data2orgtable([length(n_i); length(int_i); size(M,1) - 6*length(int_i); size(M,1)], {'Total number of Nodes', 'Number of interface Nodes', 'Number of Modes', 'Size of M and K matrices'}, {}, ' %.0f ');
#+end_src
2024-03-19 15:33:09 +01:00
#+name: tab:parameters_fem_strut
#+caption: Some extracted parameters of the FEM
#+attr_latex: :environment tabularx :width 0.4\linewidth :align lc
#+attr_latex: :center t :booktabs t
2020-11-12 18:49:34 +01:00
#+RESULTS:
| Total number of Nodes | 8 |
| Number of interface Nodes | 8 |
| Number of Modes | 6 |
| Size of M and K matrices | 54 |
2020-10-29 13:37:06 +01:00
2020-11-12 18:49:34 +01:00
#+begin_src matlab :exports results :results value table replace :tangle no :post addhdr(*this*)
data2orgtable([[1:length(int_i)]', int_i, int_xyz], {}, {'Node i', 'Node Number', 'x [m]', 'y [m]', 'z [m]'}, ' %f ');
#+end_src
2024-03-19 15:33:09 +01:00
#+name: tab:coordinate_nodes_strut
2020-11-12 18:49:34 +01:00
#+caption: Coordinates of the interface nodes
2024-03-19 15:33:09 +01:00
#+attr_latex: :environment tabularx :width 0.6\linewidth :align ccccc
#+attr_latex: :center t :booktabs t
2020-11-12 18:49:34 +01:00
#+RESULTS:
| Node i | Node Number | x [m] | y [m] | z [m] |
|--------+-------------+---------+--------+----------|
| 1.0 | 504411.0 | 0.0 | 0.0 | 0.0405 |
| 2.0 | 504412.0 | 0.0 | 0.0 | -0.0405 |
| 3.0 | 504413.0 | -0.0325 | 0.0 | 0.0 |
| 4.0 | 504414.0 | -0.0125 | 0.0 | 0.0 |
| 5.0 | 504415.0 | -0.0075 | 0.0 | 0.0 |
| 6.0 | 504416.0 | 0.0325 | 0.0 | 0.0 |
| 7.0 | 504417.0 | 0.004 | 0.0145 | -0.00175 |
| 8.0 | 504418.0 | 0.004 | 0.0166 | -0.00175 |
2020-10-29 13:37:06 +01:00
2020-11-12 18:49:34 +01:00
Using =K=, =M= and =int_xyz=, we can use the =Reduced Order Flexible Solid= simscape block.
2020-10-29 13:37:06 +01:00
** Piezoelectric parameters
Parameters for the APA300ML:
#+begin_src matlab
2021-01-04 13:58:12 +01:00
d33 = 300e-12; % Strain constant [m/V]
n = 80; % Number of layers per stack
eT = 1.6e-8; % Permittivity under constant stress [F/m]
sD = 1e-11; % Compliance under constant electric displacement [m2/N]
ka = 235e6; % Stack stiffness [N/m]
C = 5e-6; % Stack capactiance [F]
2020-10-29 13:37:06 +01:00
#+end_src
#+begin_src matlab
na = 2; % Number of stacks used as actuator
ns = 1; % Number of stacks used as force sensor
#+end_src
** Identification of the Dynamics
#+begin_src matlab :exports none
m = 0.01;
#+end_src
The dynamics is identified from the applied force to the measured relative displacement.
#+begin_src matlab :exports none
%% Name of the Simulink File
mdl = 'strut_encoder';
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/Fa'], 1, 'openinput'); io_i = io_i + 1;
2020-11-12 18:49:34 +01:00
io(io_i) = linio([mdl, '/L'], 1, 'openoutput'); io_i = io_i + 1;
2020-10-29 13:37:06 +01:00
Gh = -linearize(mdl, io);
#+end_src
The same dynamics is identified for a payload mass of 10Kg.
#+begin_src matlab
m = 10;
#+end_src
#+begin_src matlab :exports none
Ghm = -linearize(mdl, io);
#+end_src
#+begin_src matlab :exports none
freqs = logspace(0, 4, 5000);
figure;
2020-11-12 18:49:34 +01:00
tiledlayout(3, 1, 'TileSpacing', 'None', 'Padding', 'None');
2020-10-29 13:37:06 +01:00
2020-11-12 18:49:34 +01:00
ax1 = nexttile([2,1]);
2020-10-29 13:37:06 +01:00
hold on;
plot(freqs, abs(squeeze(freqresp(Gh, freqs, 'Hz'))), '-');
plot(freqs, abs(squeeze(freqresp(Ghm, freqs, 'Hz'))), '-');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
ylabel('Amplitude'); set(gca, 'XTickLabel',[]);
axis padded 'auto x'
hold off;
ax2 = nexttile;
hold on;
plot(freqs, 180/pi*angle(squeeze(freqresp(Gh, freqs, 'Hz'))), '-', ...
'DisplayName', '$m = 0kg$');
plot(freqs, 180/pi*angle(squeeze(freqresp(Ghm, freqs, 'Hz'))), '-', ...
'DisplayName', '$m = 10kg$');
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
yticks(-360:90:360);
2020-11-12 18:49:34 +01:00
ylim([-180 180]);
2020-10-29 13:37:06 +01:00
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
hold off;
axis padded 'auto x'
2020-11-12 18:49:34 +01:00
#+end_src
2020-10-29 13:37:06 +01:00
2020-11-12 18:49:34 +01:00
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/dynamics_encoder_full_strut.pdf', 'width', 'wide', 'height', 'tall');
2020-10-29 13:37:06 +01:00
#+end_src
2020-11-12 18:49:34 +01:00
#+name: fig:dynamics_encoder_full_strut
#+caption: Dynamics from the force actuator to the measured motion by the encoder
#+RESULTS:
[[file:figs/dynamics_encoder_full_strut.png]]
2020-11-12 17:33:52 +01:00
* To Order :noexport:
2020-11-12 18:49:34 +01:00
:PROPERTIES:
:header-args:matlab+: :tangle no
:END:
2020-11-12 17:33:52 +01:00
** TODO Identification of the stiffness properties of the APA300ML
*** APA Alone
#+begin_src matlab :exports none
m = 10;
#+end_src
#+begin_src matlab :exports none
%% Name of the Simulink File
mdl = 'APA300ML_characterisation';
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/Fd'], 1, 'openinput'); io_i = io_i + 1; % External Vertical Force [N]
io(io_i) = linio([mdl, '/D'], 1, 'openoutput'); io_i = io_i + 1; % Displacement/Rotation [m]
G = linearize(mdl, io);
#+end_src
#+begin_src matlab :exports results :results value table replace :tangle no :post addhdr(*this*)
data2orgtable([1e-6./dcgain(G(1,1)), 1e-6./dcgain(G(2,2)), 1e-6./dcgain(G(3,3)), 1./dcgain(G(4,4)), 1./dcgain(G(5,5)), 1./dcgain(G(6,6))]', {'Kx [N/um]', 'Ky [N/um]', 'Kz [N/um]', 'Rx [Nm/rad]', 'Ry [Nm/rad]', 'Rz [Nm/rad]'}, {'*Caracteristics*', '*Value*'}, ' %.1f ');
#+end_src
#+RESULTS:
| *Caracteristics* | *Value* |
|------------------+---------|
| Kx [N/um] | 0.8 |
| Ky [N/um] | 1.6 |
| Kz [N/um] | 1.8 |
| Rx [Nm/rad] | 71.4 |
| Ry [Nm/rad] | 148.2 |
| Rz [Nm/rad] | 4241.8 |
*** See how the global stiffness is changing with the flexible joints
#+begin_src matlab
flex = load('./mat/flexor_ID16.mat', 'int_xyz', 'int_i', 'n_xyz', 'n_i', 'nodes', 'M', 'K');
#+end_src
#+begin_src matlab :exports none
%% Name of the Simulink File
mdl = 'APA300ML_characterisation_with_joints';
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/Fd'], 1, 'openinput'); io_i = io_i + 1; % External Vertical Force [N]
io(io_i) = linio([mdl, '/D'], 1, 'openoutput'); io_i = io_i + 1; % Displacement/Rotation [m]
Gf = linearize(mdl, io);
#+end_src
#+begin_src matlab :exports results :results value table replace :tangle no :post addhdr(*this*)
data2orgtable([1e-6./dcgain(Gf(1,1)), 1e-6./dcgain(Gf(2,2)), 1e-6./dcgain(Gf(3,3)), 1./dcgain(Gf(4,4)), 1./dcgain(Gf(5,5)), 1./dcgain(Gf(6,6))]', {'Kx [N/um]', 'Ky [N/um]', 'Kz [N/um]', 'Rx [Nm/rad]', 'Ry [Nm/rad]', 'Rz [Nm/rad]'}, {'*Caracteristic*', '*Value*'}, ' %.1f ');
#+end_src
#+RESULTS:
| *Caracteristic* | *Value* |
|-----------------+---------|
| Kx [N/um] | 0.0 |
| Ky [N/um] | 0.0 |
| Kz [N/um] | 1.8 |
| Rx [Nm/rad] | 722.9 |
| Ry [Nm/rad] | 129.6 |
| Rz [Nm/rad] | 115.3 |
#+begin_src matlab
freqs = logspace(-2, 5, 1000);
figure;
hold on;
plot(freqs, abs(squeeze(freqresp(G(2,2), freqs, 'Hz'))), '-', 'DisplayName', 'APA');
plot(freqs, abs(squeeze(freqresp(Gf(2,2), freqs, 'Hz'))), '-', 'DisplayName', 'Flex');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xlabel('Frequency [Hz]'); ylabel('Amplitude [m/N]');
hold off;
legend('location', 'northeast');
#+end_src
#+begin_src matlab
freqs = logspace(-2, 5, 1000);
figure;
hold on;
plot(freqs, abs(squeeze(freqresp(G(3,3), freqs, 'Hz'))), '-', 'DisplayName', 'APA');
plot(freqs, abs(squeeze(freqresp(Gf(3,3), freqs, 'Hz'))), '-', 'DisplayName', 'Flex');
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xlabel('Frequency [Hz]'); ylabel('Amplitude [m/N]');
hold off;
legend('location', 'northeast');
#+end_src
** TODO Effect of APA300ML in the flexibility of the leg
#+begin_src matlab :exports none
m = 10;
#+end_src
#+begin_src matlab :exports none
%% Name of the Simulink File
mdl = 'APA300ML_flex_joints';
%% Input/Output definition
clear io; io_i = 1;
io(io_i) = linio([mdl, '/Fd'], 1, 'openinput'); io_i = io_i + 1; % External Vertical Force [N]
io(io_i) = linio([mdl, '/D'], 1, 'openoutput'); io_i = io_i + 1; % Displacement/Rotation [m]
#+end_src
#+begin_src matlab :exports none
G = linearize(mdl, io);
#+end_src
#+begin_src matlab :exports none
Gf = linearize(mdl, io);
#+end_src
#+begin_src matlab :exports results :results value table replace :tangle no :post addhdr(*this*)
data2orgtable([[1e-6./dcgain(G(1,1)), 1e-6./dcgain(G(2,2)), 1e-6./dcgain(G(3,3)), 1./dcgain(G(4,4)), 1./dcgain(G(5,5)), 1./dcgain(G(6,6))]', [1e-6./dcgain(Gf(1,1)), 1e-6./dcgain(Gf(2,2)), 1e-6./dcgain(Gf(3,3)), 1./dcgain(Gf(4,4)), 1./dcgain(Gf(5,5)), 1./dcgain(Gf(6,6))]'], {'Kx [N/um]', 'Ky [N/um]', 'Kz [N/um]', 'Rx [Nm/rad]', 'Ry [Nm/rad]', 'Rz [Nm/rad]'}, {'*Caracteristic*', '*Rigid APA*', '*Flexible APA*'}, ' %.3f ');
#+end_src
#+RESULTS:
| *Caracteristic* | *Rigid APA* | *Flexible APA* |
|-----------------+-------------+----------------|
| Kx [N/um] | 0.018 | 0.019 |
| Ky [N/um] | 0.018 | 0.018 |
| Kz [N/um] | 60.0 | 2.647 |
| Rx [Nm/rad] | 16.705 | 557.682 |
| Ry [Nm/rad] | 16.535 | 185.939 |
| Rz [Nm/rad] | 118.0 | 114.803 |
2020-08-03 15:46:35 +02:00
* Bibliography :ignore:
2024-03-19 15:33:09 +01:00
#+latex: \printbibliography[heading=bibintoc,title={Bibliography}]