5098 lines
221 KiB
Org Mode
5098 lines
221 KiB
Org Mode
#+TITLE: Nano Hexapod - Optimal Geometry
|
||
:DRAWER:
|
||
#+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="https://research.tdehaeze.xyz/css/style.css"/>
|
||
#+HTML_HEAD: <script type="text/javascript" src="https://research.tdehaeze.xyz/js/script.js"></script>
|
||
|
||
#+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: \input{preamble.tex}
|
||
#+LATEX_HEADER_EXTRA: \input{preamble_extra.tex}
|
||
#+LATEX_HEADER_EXTRA: \bibliography{nass-geometry.bib}
|
||
|
||
#+BIND: org-latex-bib-compiler "biber"
|
||
|
||
#+PROPERTY: header-args:matlab :session *MATLAB*
|
||
#+PROPERTY: header-args:matlab+ :comments no
|
||
#+PROPERTY: header-args:matlab+ :exports none
|
||
#+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: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
|
||
#+PROPERTY: header-args:latex+ :results file raw replace
|
||
#+PROPERTY: header-args:latex+ :buffer no
|
||
#+PROPERTY: header-args:latex+ :tangle 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:
|
||
|
||
#+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:
|
||
** Notes
|
||
Prefix is =detail_kinematics=
|
||
|
||
Talk about the optimization of the nano-hexapod: geometry, stiffness, etc...
|
||
- [ ] [[file:~/Cloud/work-projects/ID31-NASS/documents/state-of-thesis-2020/index.org::*Optimal Nano-Hexapod Design][Optimal Nano-Hexapod Design]]
|
||
- [X] file:~/Cloud/work-projects/ID31-NASS/matlab/stewart-simscape/org/kinematic-study.org
|
||
- [X] file:~/Cloud/work-projects/ID31-NASS/matlab/stewart-simscape/org/flexible-stewart-platform.org
|
||
Not so interesting
|
||
|
||
- [ ] Talk about what will influence the dynamics
|
||
It will influence the mechanical design.
|
||
For instance we want to precisely position =bi= with respect to the top platform
|
||
|
||
Optimal geometry?
|
||
- [ ] *Cubic architecture*?
|
||
Cubic configuration file:~/Cloud/work-projects/ID31-NASS/matlab/stewart-simscape/org/cubic-configuration.org
|
||
https://tdehaeze.github.io/stewart-simscape/cubic-configuration.html
|
||
- [ ] Kinematics
|
||
- [ ] Trade-off for the strut orientation
|
||
- [ ] Requirements in terms of positioning of the joints
|
||
- [ ] Not a lot of differences, no specificity of cubic architecture, no specific positioning
|
||
|
||
|
||
- [ ] https://research.tdehaeze.xyz/stewart-simscape/docs/bibliography.html
|
||
- [ ] [[file:~/Cloud/work-projects/ID31-NASS/matlab/stewart-simscape/org/kinematic-study.org::*Estimated required actuator stroke from specified platform mobility][Estimated required actuator stroke from specified platform mobility]]
|
||
- [ ] [[file:~/Cloud/work-projects/ID31-NASS/matlab/stewart-simscape/org/kinematic-study.org::*Estimation of the Joint required Stroke][Estimation of the Joint required Stroke]]
|
||
|
||
** Not used
|
||
#+begin_src latex :file detail_kinematics_cubic_schematic.pdf
|
||
\begin{tikzpicture}
|
||
\begin{scope}[rotate={45}, shift={(0, 0, -4)}]
|
||
% We first define the coordinate of the points of the Cube
|
||
\coordinate[] (bot) at (0,0,4);
|
||
\coordinate[] (top) at (4,4,0);
|
||
\coordinate[] (A1) at (0,0,0);
|
||
\coordinate[] (A2) at (4,0,4);
|
||
\coordinate[] (A3) at (0,4,4);
|
||
\coordinate[] (B1) at (4,0,0);
|
||
\coordinate[] (B2) at (4,4,4);
|
||
\coordinate[] (B3) at (0,4,0);
|
||
|
||
% Center of the Cube
|
||
\node[] (cubecenter) at ($0.5*(bot) + 0.5*(top)$){$\bullet$};
|
||
% \node[above right] at (cubecenter){$C$};
|
||
|
||
% We draw parts of the cube that corresponds to the Stewart platform
|
||
\draw[] (A1)node[]{$\bullet$} -- (B1)node[]{$\bullet$} -- (A2)node[]{$\bullet$} -- (B2)node[]{$\bullet$} -- (A3)node[]{$\bullet$} -- (B3)node[]{$\bullet$} -- (A1);
|
||
\draw[opacity=0.5] (bot) -- (A1);
|
||
\draw[opacity=0.5] (bot) -- (A2);
|
||
\draw[opacity=0.5] (bot) -- (A3);
|
||
\draw[opacity=0.5] (top) -- (B1);
|
||
\draw[opacity=0.5] (top) -- (B2);
|
||
\draw[opacity=0.5] (top) -- (B3);
|
||
|
||
% ai and bi are computed
|
||
\def\lfrom{0.1}
|
||
\def\lto{0.9}
|
||
|
||
\coordinate(a1) at ($(A1) - \lfrom*(A1) + \lfrom*(B1)$);
|
||
\coordinate(b1) at ($(A1) - \lto*(A1) + \lto*(B1)$);
|
||
\coordinate(a2) at ($(A2) - \lfrom*(A2) + \lfrom*(B1)$);
|
||
\coordinate(b2) at ($(A2) - \lto*(A2) + \lto*(B1)$);
|
||
\coordinate(a3) at ($(A2) - \lfrom*(A2) + \lfrom*(B2)$);
|
||
\coordinate(b3) at ($(A2) - \lto*(A2) + \lto*(B2)$);
|
||
\coordinate(a4) at ($(A3) - \lfrom*(A3) + \lfrom*(B2)$);
|
||
\coordinate(b4) at ($(A3) - \lto*(A3) + \lto*(B2)$);
|
||
\coordinate(a5) at ($(A3) - \lfrom*(A3) + \lfrom*(B3)$);
|
||
\coordinate(b5) at ($(A3) - \lto*(A3) + \lto*(B3)$);
|
||
\coordinate(a6) at ($(A1) - \lfrom*(A1) + \lfrom*(B3)$);
|
||
\coordinate(b6) at ($(A1) - \lto*(A1) + \lto*(B3)$);
|
||
|
||
% Center of the Stewart Platform
|
||
% \node[color=colorblue] at ($0.25*(a1) + 0.25*(a6) + 0.25*(b3) + 0.25*(b4)$){$\bullet$};
|
||
|
||
% We draw the fixed and mobiles platforms
|
||
\path[fill=colorblue, opacity=0.2] (a1) -- (a2) -- (a3) -- (a4) -- (a5) -- (a6) -- cycle;
|
||
\path[fill=colorblue, opacity=0.2] (b1) -- (b2) -- (b3) -- (b4) -- (b5) -- (b6) -- cycle;
|
||
\draw[color=colorblue, dashed] (a1) -- (a2) -- (a3) -- (a4) -- (a5) -- (a6) -- cycle;
|
||
\draw[color=colorblue, dashed] (b1) -- (b2) -- (b3) -- (b4) -- (b5) -- (b6) -- cycle;
|
||
|
||
% The legs of the hexapod are drawn
|
||
\draw[color=colorblue] (a1)node{$\bullet$} -- (b1)node{$\bullet$};
|
||
\draw[color=colorblue] (a2)node{$\bullet$} -- (b2)node{$\bullet$};
|
||
\draw[color=colorblue] (a3)node{$\bullet$} -- (b3)node{$\bullet$};
|
||
\draw[color=colorblue] (a4)node{$\bullet$} -- (b4)node{$\bullet$};
|
||
\draw[color=colorblue] (a5)node{$\bullet$} -- (b5)node{$\bullet$};
|
||
\draw[color=colorblue] (a6)node{$\bullet$} -- (b6)node{$\bullet$};
|
||
\end{scope}
|
||
|
||
% Height of the Hexapod
|
||
\coordinate[] (sizepos) at ($(a2)+(0.2, 0)$);
|
||
\coordinate[] (origin) at (0,0,0);
|
||
% \draw[<->, dashed] (a2-|sizepos) -- node[midway, right]{$H$} (b2-|sizepos);
|
||
% Height offset
|
||
% \draw[<->, dashed] (a2-|sizepos) -- node[midway, right]{$H_0$} (origin-|sizepos);
|
||
|
||
% \draw[<->, dashed] (0.5,2,0) --node[near end, right]{${}^{F}O_{C}$} ++(0,2,0);
|
||
% \draw[<->, dashed] (-2,2,0) --node[midway, right]{${}^{F}H_{A}$} ++(0,1,0);
|
||
% \draw[<->, dashed] (-2,6,0) --node[midway, right]{${}^{M}H_{B}$} ++(0,-1.5,0);
|
||
|
||
% Useful part of the cube
|
||
% \draw[<->, dashed] ($(A2)+(0.5,0)$) -- node[midway, right]{$H_{C}$} ($(B1)+(0.5,0)$);
|
||
\end{tikzpicture}
|
||
#+end_src
|
||
|
||
#+name: fig:detail_kinematics_cubic_schematic
|
||
#+caption: Stewart platform Cubic architecture. The struts are aligned with the sides of a cube.
|
||
#+RESULTS:
|
||
[[file:figs/detail_kinematics_cubic_schematic.png]]
|
||
|
||
** TODO [#A] Copy relevant parts of reports
|
||
|
||
** DONE [#A] Structure the review of Stewart platforms
|
||
CLOSED: [2025-03-30 Sun 11:38]
|
||
|
||
Focus on short stroke (<1 mm) stewart platforms with flexible joints.
|
||
|
||
- Actuators: voice coil, piezo
|
||
- Flexible joints
|
||
- Geometry:
|
||
- Cubic, non cubic, ...
|
||
- Control ? Maybe in the control section ?
|
||
|
||
** DONE [#B] Finish table about Stewart platforms
|
||
CLOSED: [2025-03-30 Sun 11:54]
|
||
|
||
[[tab:detail_kinematics_stewart_review][tab:detail_kinematics_stewart_review]]
|
||
|
||
- [ ] Only keep integrated sensor and not external metrology
|
||
- [ ] Check for missing information
|
||
|
||
** DONE [#A] Maybe need to have the Simscape model for the stewart platform?
|
||
CLOSED: [2025-03-30 Sun 19:38]
|
||
|
||
For what use?
|
||
Study of coupling between strut sensor
|
||
|
||
** DONE [#A] Verify Mobility of Stewart platform
|
||
CLOSED: [2025-04-01 Tue 09:36]
|
||
|
||
*Mobility is not a sphere but a cube!*
|
||
|
||
From [[cite:&mcinroy00_desig_contr_flexur_joint_hexap]]:
|
||
#+begin_quote
|
||
This implies that, if all struts can move equal
|
||
amounts, then the translational part of the hexapod’s Cartesian
|
||
workspace forms a *sphere*. Thus, this is a useful geometry when
|
||
the ability to move equal amounts in all translational directions
|
||
is required.
|
||
#+end_quote
|
||
*This is wrong*
|
||
|
||
Maybe easy check by taking few example points.
|
||
#+begin_src matlab :exports none :results none
|
||
%% Example of one Stewart platform and associated translational mobility
|
||
L_max = 50e-6; % Maximum actuator stroke (+/-) [m]
|
||
|
||
stewart = initializeStewartPlatform();
|
||
stewart = initializeFramesPositions(stewart, 'H', 100e-3, 'MO_B', -50e-3);
|
||
stewart = generateGeneralConfiguration(stewart, 'FH', 0, 'FR', 100e-3, 'MH', 0, 'MR', 100e-3, ...
|
||
'FTh', [-5, 5, 120-5, 120+5, 240-5, 240+5]*(pi/180), ...
|
||
'MTh', [-60+5, 60-5, 60+5, 180-5, 180+5, -60-5]*(pi/180));
|
||
stewart = computeJointsPose(stewart);
|
||
stewart = initializeStrutDynamics(stewart, 'k', 1);
|
||
stewart = computeJacobian(stewart);
|
||
stewart = initializeCylindricalPlatforms(stewart, 'Fpr', 110e-3, 'Mpr', 110e-3);
|
||
|
||
displayArchitecture(stewart, 'labels', false, 'frames', false, 'F_color', [0,0,0], 'M_color', [0,0,0], 'L_color', [0,0,0]);
|
||
#+end_src
|
||
|
||
#+begin_src matlab
|
||
thetas = linspace(0, pi, 100);
|
||
phis = linspace(0, 2*pi, 100);
|
||
rs = zeros(length(thetas), length(phis));
|
||
|
||
for i = 1:length(thetas)
|
||
for j = 1:length(phis)
|
||
% Unit vector pointing to "spherical direction"
|
||
Tx = sin(thetas(i))*cos(phis(j));
|
||
Ty = sin(thetas(i))*sin(phis(j));
|
||
Tz = cos(thetas(i));
|
||
|
||
% Compute Strut motion required for unit displacement in theta/phi direction
|
||
dL = stewart.kinematics.J*[Tx; Ty; Tz; 0; 0; 0;];
|
||
|
||
% Due to maximum strut stroke, maximum displacement in the considered direction is limited
|
||
rs(i, j) = L_max/max(abs(dL));
|
||
end
|
||
end
|
||
|
||
% Sphere with radius equal to actuator stroke
|
||
[Xs,Ys,Zs] = sphere;
|
||
Xs = 1e6*L_max*Xs;
|
||
Ys = 1e6*L_max*Ys;
|
||
Zs = 1e6*L_max*Zs;
|
||
|
||
[phi_grid, theta_grid] = meshgrid(phis, thetas);
|
||
X = 1e6 * rs .* sin(theta_grid) .* cos(phi_grid);
|
||
Y = 1e6 * rs .* sin(theta_grid) .* sin(phi_grid);
|
||
Z = 1e6 * rs .* cos(theta_grid);
|
||
|
||
figure('Renderer', 'painters');
|
||
hold on;
|
||
surf(X, Y, Z, 'FaceColor', 'none', 'LineWidth', 0.1, 'EdgeColor', [0, 0, 0]);
|
||
surf(Xs, Ys, Zs, 'FaceColor', colors(2,:), 'EdgeColor', 'none');
|
||
quiver3(0, 0, 0, 100, 0, 0, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.9);
|
||
quiver3(0, 0, 0, 0, 100, 0, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.9);
|
||
quiver3(0, 0, 0, 0, 0, 100, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.9);
|
||
hold off;
|
||
axis equal;
|
||
grid off;
|
||
axis off;
|
||
view(55, 25);
|
||
#+end_src
|
||
|
||
#+begin_src matlab
|
||
for i = 1:length(thetas)
|
||
for j = 1:length(phis)
|
||
max(abs(stewart.kinematics.J*[X(i,j); Y(i,j); Z(i,j); 0; 0; 0]))
|
||
end
|
||
end
|
||
#+end_src
|
||
|
||
#+begin_src matlab
|
||
inv(stewart.kinematics.J)*[42.8; 40.8; 29.3; 0; 0; 0]
|
||
stewart.kinematics.J*[-6.4; -0.89; 24.6; 136.3; -348.7; -89.2]
|
||
#+end_src
|
||
|
||
** TODO [#A] Compute all the figures
|
||
SCHEDULED: <2025-04-01 Tue>
|
||
|
||
** DONE [#B] Verify cubic architecture in literature
|
||
CLOSED: [2025-04-01 Tue 11:31]
|
||
|
||
[[cite:&yang19_dynam_model_decoup_contr_flexib]]: *It is not cubic*
|
||
#+begin_src matlab
|
||
a1 = [0.1829; 0.06039; -0.03515];
|
||
a2 = [-0.03916; 0.1886; -0.03515];
|
||
a3 = [-0.1438; 0.1282 ;-0.03515];
|
||
b1 = [0.02771; 0.1906; 0.03515];
|
||
b2 = [0.1512; 0.1193; 0.03515];
|
||
b3 = [-0.1789; -0.07131; 0.03515];
|
||
|
||
v1 = b1-a1;
|
||
v2 = b2-a2;
|
||
v3 = b3-a3;
|
||
angle_rad = acos(dot(v1,v3)/(norm(v1)*norm(v3)));
|
||
angle_deg = rad2deg(angle_rad)
|
||
#+end_src
|
||
|
||
|
||
[[cite:&furutani04_nanom_cuttin_machin_using_stewar]]
|
||
It says 35 degrees from the horizontal plane for the struts.
|
||
Check if this is the case for a cubic architecture.
|
||
#+begin_src matlab
|
||
H = 200e-3; % height of the Stewart platform [m]
|
||
MO_B = 50e-3; % Position {B} with respect to {M} [m]
|
||
|
||
stewart = initializeStewartPlatform();
|
||
stewart = initializeFramesPositions(stewart, 'H', H, 'MO_B', MO_B);
|
||
stewart = generateCubicConfiguration(stewart, 'Hc', H, 'FOc', H/2, 'FHa', 25e-3, 'MHb', 25e-3);
|
||
stewart = computeJointsPose(stewart);
|
||
stewart = initializeStrutDynamics(stewart, 'k', 1e6, 'c', 1e1);
|
||
stewart = initializeJointDynamics(stewart, 'type_F', '2dof', 'type_M', '3dof');
|
||
stewart = computeJacobian(stewart);
|
||
stewart = initializeStewartPose(stewart);
|
||
stewart = initializeCylindricalPlatforms(stewart, ...
|
||
'Mpm', 1e-6, ... % Massless platform
|
||
'Fpm', 1e-6, ... % Massless platform
|
||
'Mph', 20e-3, ... % Thin platform
|
||
'Fph', 20e-3, ... % Thin platform
|
||
'Mpr', 1.2*max(vecnorm(stewart.platform_M.Mb)), ...
|
||
'Fpr', 1.2*max(vecnorm(stewart.platform_F.Fa)));
|
||
stewart = initializeCylindricalStruts(stewart, ...
|
||
'Fsm', 1e-6, ... % Massless strut
|
||
'Msm', 1e-6, ... % Massless strut
|
||
'Fsh', stewart.geometry.l(1)/2, ...
|
||
'Msh', stewart.geometry.l(1)/2 ...
|
||
);
|
||
|
||
% Verify 90 degrees between the struts
|
||
v1 = stewart.geometry.As(:,1);
|
||
v2 = stewart.geometry.As(:,2);
|
||
angle_rad = acos(dot(v1,v2)/(norm(v1)*norm(v2)));
|
||
angle_deg = rad2deg(angle_rad)
|
||
|
||
% Check angle with horizontal plane
|
||
v1 = stewart.geometry.As(:,1)
|
||
v2 = [1;0;0]
|
||
angle_rad = acos(dot(v1,v2)/(norm(v1)*norm(v2)));
|
||
angle_deg = rad2deg(angle_rad)
|
||
#+end_src
|
||
|
||
** DONE [#A] Get analytical formula of stiffness matrix for cubic architecture?
|
||
CLOSED: [2025-03-31 Mon 21:40]
|
||
*** Introduction
|
||
- [ ] Copy this analysis to relevant section
|
||
|
||
- Make some simplifying assumption:
|
||
- Cube at the center of the Stewart platform
|
||
- Cube size =
|
||
- Height of the mobile joints =
|
||
|
||
#+begin_src latex :file detail_kinematics_cubic_schematic.pdf
|
||
\begin{tikzpicture}
|
||
\begin{scope}[rotate={45}, shift={(0, 0, -4)}]
|
||
% We first define the coordinate of the points of the Cube
|
||
\coordinate[] (bot) at (0,0,4);
|
||
\coordinate[] (top) at (4,4,0);
|
||
\coordinate[] (A1) at (0,0,0);
|
||
\coordinate[] (A2) at (4,0,4);
|
||
\coordinate[] (A3) at (0,4,4);
|
||
\coordinate[] (B1) at (4,0,0);
|
||
\coordinate[] (B2) at (4,4,4);
|
||
\coordinate[] (B3) at (0,4,0);
|
||
|
||
% Center of the Cube
|
||
\node[] (cubecenter) at ($0.5*(bot) + 0.5*(top)$){$\bullet$};
|
||
\node[above right] at (cubecenter){$C$};
|
||
|
||
% We draw parts of the cube that corresponds to the Stewart platform
|
||
\draw[] (A1)node[]{$\bullet$} -- (B1)node[]{$\bullet$} -- (A2)node[]{$\bullet$} -- (B2)node[]{$\bullet$} -- (A3)node[]{$\bullet$} -- (B3)node[]{$\bullet$} -- (A1);
|
||
|
||
% ai and bi are computed
|
||
\def\lfrom{0.1}
|
||
\def\lto{0.8}
|
||
|
||
\coordinate(a1) at ($(A1) - \lfrom*(A1) + \lfrom*(B1)$);
|
||
\coordinate(b1) at ($(A1) - \lto*(A1) + \lto*(B1)$);
|
||
\coordinate(a2) at ($(A2) - \lfrom*(A2) + \lfrom*(B1)$);
|
||
\coordinate(b2) at ($(A2) - \lto*(A2) + \lto*(B1)$);
|
||
\coordinate(a3) at ($(A2) - \lfrom*(A2) + \lfrom*(B2)$);
|
||
\coordinate(b3) at ($(A2) - \lto*(A2) + \lto*(B2)$);
|
||
\coordinate(a4) at ($(A3) - \lfrom*(A3) + \lfrom*(B2)$);
|
||
\coordinate(b4) at ($(A3) - \lto*(A3) + \lto*(B2)$);
|
||
\coordinate(a5) at ($(A3) - \lfrom*(A3) + \lfrom*(B3)$);
|
||
\coordinate(b5) at ($(A3) - \lto*(A3) + \lto*(B3)$);
|
||
\coordinate(a6) at ($(A1) - \lfrom*(A1) + \lfrom*(B3)$);
|
||
\coordinate(b6) at ($(A1) - \lto*(A1) + \lto*(B3)$);
|
||
|
||
% Center of the Stewart Platform
|
||
% \node[color=colorblue] at ($0.25*(a1) + 0.25*(a6) + 0.25*(b3) + 0.25*(b4)$){$\bullet$};
|
||
|
||
% We draw the fixed and mobiles platforms
|
||
\path[fill=colorblue, opacity=0.2] (a1) -- (a2) -- (a3) -- (a4) -- (a5) -- (a6) -- cycle;
|
||
\path[fill=colorblue, opacity=0.2] (b1) -- (b2) -- (b3) -- (b4) -- (b5) -- (b6) -- cycle;
|
||
\draw[color=colorblue, dashed] (a1) -- (a2) -- (a3) -- (a4) -- (a5) -- (a6) -- cycle;
|
||
\draw[color=colorblue, dashed] (b1) -- (b2) -- (b3) -- (b4) -- (b5) -- (b6) -- cycle;
|
||
|
||
% The legs of the hexapod are drawn
|
||
\draw[color=colorblue] (a1)node{$\bullet$} -- node[midway, right]{$3$} (b1)node{$\bullet$};
|
||
\draw[color=colorblue] (a2)node{$\bullet$} -- node[midway, right]{$4$} (b2)node{$\bullet$};
|
||
\draw[color=colorblue] (a3)node{$\bullet$} -- node[midway, right]{$5$} (b3)node{$\bullet$};
|
||
\draw[color=colorblue] (a4)node{$\bullet$} -- node[midway, right]{$6$} (b4)node{$\bullet$};
|
||
\draw[color=colorblue] (a5)node{$\bullet$} -- node[midway, right]{$1$} (b5)node{$\bullet$};
|
||
\draw[color=colorblue] (a6)node{$\bullet$} -- node[midway, right]{$2$} (b6)node{$\bullet$};
|
||
|
||
% Labels
|
||
\node[left=0.1 of a5] {$a_i$};
|
||
\node[left=0.1 of b5] {$b_i$};
|
||
\end{scope}
|
||
|
||
% Height of the Hexapod
|
||
\coordinate[] (sizepos) at ($(a2)+(0.2, 0)$);
|
||
\coordinate[] (origin) at (0,0,0);
|
||
% \draw[<->, dashed] (a2-|sizepos) -- node[midway, right]{$H$} (b2-|sizepos);
|
||
% Height offset
|
||
% \draw[<->, dashed] (a2-|sizepos) -- node[midway, right]{$H_0$} (origin-|sizepos);
|
||
|
||
\draw[->] (0,6,0) node[above right]{$\{M\}$} -- ++(0,0,1);
|
||
\draw[->] (0,6,0) -- ++(1,0,0);
|
||
\draw[->] (0,6,0) -- ++(0,1,0);
|
||
|
||
\draw[->] (0,2,0) node[below right]{$\{F\}$}-- ++(0,0,1)node[left]{$x$};
|
||
\draw[->] (0,2,0) -- ++(1,0,0)node[above]{$y$};
|
||
\draw[->] (0,2,0) -- ++(0,1,0)node[right]{$z$};
|
||
|
||
\draw[<->, dashed] (0.5,2,0) --node[near end, right]{${}^{F}O_{C}$} ++(0,2,0);
|
||
\draw[<->, dashed] (-2,2,0) --node[midway, right]{${}^{F}H_{A}$} ++(0,1,0);
|
||
\draw[<->, dashed] (-2,6,0) --node[midway, right]{${}^{M}H_{B}$} ++(0,-1.5,0);
|
||
|
||
% Useful part of the cube
|
||
\draw[<->, dashed] ($(A2)+(0.5,0)$) -- node[midway, right]{$H_{C}$} ($(B1)+(0.5,0)$);
|
||
\end{tikzpicture}
|
||
#+end_src
|
||
|
||
#+RESULTS:
|
||
[[file:figs/detail_kinematics_cubic_schematic.png]]
|
||
|
||
Compute:
|
||
- [X] si : easy (always the same)
|
||
- [X] bi : should also be easy
|
||
- Have to find intersection between struts and top platform (height of the joints)
|
||
- Need the equation of the cube's sides?
|
||
|
||
|
||
\begin{equation}
|
||
\hat{\bm{s}}_1 = \begin{bmatrix} \sqrt{2}/\sqrt{3} \\ 0 \\ 1/\sqrt{3} \end{bmatrix} \quad
|
||
\hat{\bm{s}}_2 = \begin{bmatrix} -1/\sqrt{6} \\ -1/\sqrt{2} \\ 1/\sqrt{3} \end{bmatrix} \quad
|
||
\hat{\bm{s}}_3 = \begin{bmatrix} -1/\sqrt{6} \\ 1/\sqrt{2} \\ 1/\sqrt{3} \end{bmatrix} \quad
|
||
\hat{\bm{s}}_4 = \begin{bmatrix} \sqrt{2}/\sqrt{3} \\ 0 \\ 1/\sqrt{3} \end{bmatrix} \quad
|
||
\hat{\bm{s}}_5 = \begin{bmatrix} -1/\sqrt{6} \\ -1/\sqrt{2} \\ 1/\sqrt{3} \end{bmatrix} \quad
|
||
\hat{\bm{s}}_6 = \begin{bmatrix} -1/\sqrt{6} \\ 1/\sqrt{2} \\ 1/\sqrt{3} \end{bmatrix}
|
||
\end{equation}
|
||
|
||
|
||
\begin{equation}
|
||
\sum_{i = 1}^{6} \hat{\bm{s}}_i \cdot \hat{\bm{s}}_i^T = 2 \bm{I}_3
|
||
\end{equation}
|
||
|
||
|
||
Need to include size of the cube for bi:
|
||
This is wrong, check from matlab script
|
||
|
||
\begin{equation}
|
||
\bm{b}_1 = \begin{bmatrix} \sqrt{2}/\sqrt{3} \\ 0 \\ 1/\sqrt{3} \end{bmatrix} \quad
|
||
\bm{b}_2 = \begin{bmatrix} -1/\sqrt{6} \\ -1/\sqrt{2} \\ 1/\sqrt{3} \end{bmatrix} \quad
|
||
\bm{b}_3 = \begin{bmatrix} -1/\sqrt{6} \\ 1/\sqrt{2} \\ 1/\sqrt{3} \end{bmatrix} \quad
|
||
\bm{b}_4 = \begin{bmatrix} \sqrt{2}/\sqrt{3} \\ 0 \\ 1/\sqrt{3} \end{bmatrix} \quad
|
||
\bm{b}_5 = \begin{bmatrix} -1/\sqrt{6} \\ -1/\sqrt{2} \\ 1/\sqrt{3} \end{bmatrix} \quad
|
||
\bm{b}_6 = \begin{bmatrix} -1/\sqrt{6} \\ 1/\sqrt{2} \\ 1/\sqrt{3} \end{bmatrix}
|
||
\end{equation}
|
||
|
||
|
||
\begin{equation}
|
||
\bm{K} = k \bm{J}^T \bm{J} =
|
||
k \left[
|
||
\begin{array}{c|c}
|
||
\Sigma_{i = 0}^{6} \hat{\bm{s}}_i \cdot \hat{\bm{s}}_i^T & \Sigma_{i = 0}^{6} \bm{\hat{s}}_i \cdot ({}^A\bm{b}_i \times {}^A\hat{\bm{s}}_i)^T \\
|
||
\hline
|
||
\Sigma_{i = 0}^{6} ({}^A\bm{b}_i \times {}^A\hat{\bm{s}}_i) \cdot \hat{\bm{s}}_i^T & \Sigma_{i = 0}^{6} ({}^A\bm{b}_i \times {}^A\hat{\bm{s}}_i) \cdot ({}^A\bm{b}_i \times {}^A\hat{\bm{s}}_i)^T\\
|
||
\end{array}
|
||
\right]
|
||
\end{equation}
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Cubic Architecture - Effect of the position of frame {A} and {B}
|
||
H = 20e-3; % Height of the Stewart platform [m]
|
||
Hc = 100e-3; % Size of the useful part of the cube [m]
|
||
FOc = 50e-3; % Center of the cube at the Stewart platform center
|
||
|
||
%% Frames {A} and {B} at the cube's center
|
||
MO_B = 0e-3; % Position {B} with respect to {M} [m]
|
||
MHb = 10e-3;
|
||
|
||
k = 1.4;
|
||
|
||
stewart_center = initializeStewartPlatform();
|
||
stewart_center = initializeFramesPositions(stewart_center, 'H', H, 'MO_B', MO_B);
|
||
stewart_center = generateCubicConfiguration(stewart_center, 'Hc', Hc, 'FOc', FOc, 'FHa', 5e-3, 'MHb', MHb);
|
||
stewart_center = computeJointsPose(stewart_center);
|
||
stewart_center = initializeStrutDynamics(stewart_center, 'k', k);
|
||
stewart_center = computeJacobian(stewart_center);
|
||
stewart_center = initializeCylindricalPlatforms(stewart_center, 'Fpr', 150e-3, 'Mpr', 150e-3);
|
||
|
||
displayArchitecture(stewart_center, 'labels', true, 'frames', true);
|
||
plotCube(stewart_center, 'Hc', Hc, 'FOc', FOc, 'color', [0,0,0,1], 'link_to_struts', true);
|
||
|
||
%% Si
|
||
si = 1/sqrt(3)*[
|
||
[ sqrt(2); 0; ; 1], ...
|
||
[-sqrt(2)/2; -sqrt(3/2); 1], ...
|
||
[-sqrt(2)/2; sqrt(3/2); 1], ...
|
||
[ sqrt(2); 0; ; 1], ...
|
||
[-sqrt(2)/2; -sqrt(3/2); 1], ...
|
||
[-sqrt(2)/2; sqrt(3/2); 1] ...
|
||
];
|
||
|
||
% Verification
|
||
if norm(si - stewart_center.geometry.Bs) > 1e-9
|
||
warning('wrong formulas')
|
||
end
|
||
|
||
%% Bi with Hc the "cube height"
|
||
% Position of the cube's top points for the six struts (centered cube)
|
||
ci = Hc * [
|
||
[1/sqrt(2); -sqrt(3)/sqrt(2); 0.5], ...
|
||
[1/sqrt(2); -sqrt(3)/sqrt(2); 0.5], ...
|
||
[1/sqrt(2); sqrt(3)/sqrt(2); 0.5], ...
|
||
[1/sqrt(2); sqrt(3)/sqrt(2); 0.5], ...
|
||
[-sqrt(2); 0; 0.5], ...
|
||
[-sqrt(2); 0; 0.5] ...
|
||
];
|
||
|
||
% Position of ci with respect to {B}
|
||
ci = ci + (- H - MO_B + FOc) * [0;0;1];
|
||
|
||
% Position of bi with respect to {B}
|
||
bi = ci - si * (MHb + FOc + Hc/2 - H) ./ si(3,:);
|
||
|
||
% Compare from Bi computed from Script
|
||
if norm(bi - stewart_center.geometry.Bb) > 1e-9
|
||
warning('wrong formulas')
|
||
end
|
||
|
||
%% Stiffness matrix
|
||
K = zeros(6,6);
|
||
K(1:3, 4:6) = si * cross(bi,si).';
|
||
K(4:6, 1:3) = cross(bi,si) * si.';
|
||
K(1:3,1:3) = si * si';
|
||
K(4:6,4:6) = cross(bi,si) * cross(bi,si).';
|
||
K = k*K;
|
||
if norm(K - stewart_center.kinematics.K) > 1e-9
|
||
warning('wrong formulas')
|
||
end
|
||
#+end_src
|
||
|
||
*** Analytical equations
|
||
|
||
A and B at cube's center.
|
||
Position of bi can be anywhere along the cube's edges
|
||
|
||
#+begin_src matlab
|
||
% Define symbolic variables
|
||
syms k Hc alpha
|
||
|
||
% Define si matrix (support vectors)
|
||
si = 1/sqrt(3)*[
|
||
[ sqrt(2), 0, 1]; ...
|
||
[-sqrt(2)/2, -sqrt(3/2), 1]; ...
|
||
[-sqrt(2)/2, sqrt(3/2), 1]; ...
|
||
[ sqrt(2), 0, 1]; ...
|
||
[-sqrt(2)/2, -sqrt(3/2), 1]; ...
|
||
[-sqrt(2)/2, sqrt(3/2), 1] ...
|
||
];
|
||
|
||
% Define ci matrix (connection vectors)
|
||
ci = Hc * [
|
||
[1/sqrt(2), -sqrt(3)/sqrt(2), 0.5]; ...
|
||
[1/sqrt(2), -sqrt(3)/sqrt(2), 0.5]; ...
|
||
[1/sqrt(2), sqrt(3)/sqrt(2), 0.5]; ...
|
||
[1/sqrt(2), sqrt(3)/sqrt(2), 0.5]; ...
|
||
[-sqrt(2), 0, 0.5]; ...
|
||
[-sqrt(2), 0, 0.5] ...
|
||
];
|
||
|
||
% Calculate bi vectors
|
||
bi = ci + alpha * si;
|
||
|
||
% Initialize stiffness matrix
|
||
K = sym(zeros(6,6));
|
||
|
||
% Calculate elements of the stiffness matrix
|
||
for i = 1:6
|
||
% Extract vectors for each leg
|
||
s_i = si(i,:)';
|
||
b_i = bi(i,:)';
|
||
|
||
% Calculate cross product vector
|
||
cross_bs = cross(b_i, s_i);
|
||
|
||
% Build matrix blocks
|
||
K(1:3, 4:6) = K(1:3, 4:6) + s_i * cross_bs';
|
||
K(4:6, 1:3) = K(4:6, 1:3) + cross_bs * s_i';
|
||
K(1:3, 1:3) = K(1:3, 1:3) + s_i * s_i';
|
||
K(4:6, 4:6) = K(4:6, 4:6) + cross_bs * cross_bs';
|
||
end
|
||
|
||
% Scale by stiffness coefficient
|
||
K = k * K;
|
||
|
||
% Simplify the expressions
|
||
K = simplify(K);
|
||
|
||
% Display the analytical stiffness matrix
|
||
disp('Analytical Stiffness Matrix:');
|
||
pretty(K);
|
||
|
||
% If you want to analyze specific components
|
||
disp('Top-left block (K₁₁):');
|
||
pretty(K(1:3, 1:3));
|
||
|
||
disp('Top-right block (K₁₂):');
|
||
pretty(K(1:3, 4:6));
|
||
|
||
disp('Bottom-left block (K₂₁):');
|
||
pretty(K(4:6, 1:3));
|
||
|
||
disp('Bottom-right block (K₂₂):');
|
||
pretty(K(4:6, 4:6));
|
||
|
||
% Eigenvalue analysis (optional)
|
||
disp('Eigenvalues:');
|
||
eig_vals = simplify(eig(K));
|
||
pretty(eig_vals);
|
||
#+end_src
|
||
|
||
*** Effect of un-centered frame with cube's center
|
||
#+begin_src matlab
|
||
% Define symbolic variables
|
||
syms k Hc alpha H
|
||
|
||
assume(k > 0); % k is positive real
|
||
assume(Hc, 'real'); % Hc is real
|
||
assume(H, 'real'); % H is real
|
||
assume(alpha, 'real'); % alpha is real
|
||
|
||
|
||
% Define si matrix (support vectors)
|
||
si = 1/sqrt(3)*[
|
||
[ sqrt(2), 0, 1]; ...
|
||
[-sqrt(2)/2, -sqrt(3/2), 1]; ...
|
||
[-sqrt(2)/2, sqrt(3/2), 1]; ...
|
||
[ sqrt(2), 0, 1]; ...
|
||
[-sqrt(2)/2, -sqrt(3/2), 1]; ...
|
||
[-sqrt(2)/2, sqrt(3/2), 1] ...
|
||
];
|
||
|
||
% Define ci matrix (connection vectors)
|
||
ci = Hc * [
|
||
[1/sqrt(2), -sqrt(3)/sqrt(2), 0.5]; ...
|
||
[1/sqrt(2), -sqrt(3)/sqrt(2), 0.5]; ...
|
||
[1/sqrt(2), sqrt(3)/sqrt(2), 0.5]; ...
|
||
[1/sqrt(2), sqrt(3)/sqrt(2), 0.5]; ...
|
||
[-sqrt(2), 0, 0.5]; ...
|
||
[-sqrt(2), 0, 0.5] ...
|
||
];
|
||
|
||
% Apply vertical shift to ci
|
||
ci = ci + H * [0, 0, 1];
|
||
|
||
% Calculate bi vectors
|
||
bi = ci + alpha * si;
|
||
|
||
% Initialize stiffness matrix
|
||
K = sym(zeros(6,6));
|
||
|
||
% Calculate elements of the stiffness matrix
|
||
for i = 1:6
|
||
% Extract vectors for each leg
|
||
s_i = si(i,:)';
|
||
b_i = bi(i,:)';
|
||
|
||
% Calculate cross product vector
|
||
cross_bs = cross(b_i, s_i);
|
||
|
||
% Build matrix blocks
|
||
K(1:3, 4:6) = K(1:3, 4:6) + s_i * cross_bs';
|
||
K(4:6, 1:3) = K(4:6, 1:3) + cross_bs * s_i';
|
||
K(1:3, 1:3) = K(1:3, 1:3) + s_i * s_i';
|
||
K(4:6, 4:6) = K(4:6, 4:6) + cross_bs * cross_bs';
|
||
end
|
||
|
||
% Scale by stiffness coefficient
|
||
K = k * K;
|
||
|
||
% Simplify the expressions
|
||
K = simplify(K);
|
||
|
||
% Display the analytical stiffness matrix
|
||
disp('Analytical Stiffness Matrix:');
|
||
pretty(K);
|
||
#+end_src
|
||
|
||
*** Centered cube - joints at cube's vertices => diagonal stiffness matrix
|
||
|
||
#+begin_src matlab
|
||
%% Suppose centered cube : Hc = H, FOc = H/2, MO_B = -H/2
|
||
k = 1;
|
||
Hc = 200e-3
|
||
|
||
si = 1/sqrt(3)*[
|
||
[ sqrt(2); 0; ; 1], ...
|
||
[-sqrt(2)/2; -sqrt(3/2); 1], ...
|
||
[-sqrt(2)/2; sqrt(3/2); 1], ...
|
||
[ sqrt(2); 0; ; 1], ...
|
||
[-sqrt(2)/2; -sqrt(3/2); 1], ...
|
||
[-sqrt(2)/2; sqrt(3/2); 1] ...
|
||
];
|
||
|
||
bi = Hc * [
|
||
[1/sqrt(2); -sqrt(3)/sqrt(2); 0.5], ...
|
||
[1/sqrt(2); -sqrt(3)/sqrt(2); 0.5], ...
|
||
[1/sqrt(2); sqrt(3)/sqrt(2); 0.5], ...
|
||
[1/sqrt(2); sqrt(3)/sqrt(2); 0.5], ...
|
||
[-sqrt(2); 0; 0.5], ...
|
||
[-sqrt(2); 0; 0.5] ...
|
||
];
|
||
|
||
K = zeros(6,6);
|
||
K(1:3, 4:6) = si * cross(bi,si).';
|
||
K(4:6, 1:3) = cross(bi,si) * si.';
|
||
K(1:3,1:3) = si * si';
|
||
K(4:6,4:6) = cross(bi,si) * cross(bi,si).';
|
||
K = k*K
|
||
|
||
K_formula = diag([2*k, 2*k, 2*k, 1.5*k*Hc^2, 1.5*k*Hc^2, 6*k*Hc^2])
|
||
#+end_src
|
||
|
||
*** Verify general structure of the Stewart platform
|
||
|
||
#+begin_src matlab
|
||
stewart = initializeStewartPlatform();
|
||
stewart = initializeFramesPositions(stewart, 'H', 100e-3, 'MO_B', -50e-3);
|
||
stewart = generateGeneralConfiguration(stewart, 'FH', 0, 'FR', 100e-3, 'MH', 0, 'MR', 100e-3, ...
|
||
'FTh', [-5, 5, 120-5, 120+5, 240-5, 240+5]*(pi/180), ...
|
||
'MTh', [-60+5, 60-5, 60+5, 180-5, 180+5, -60-5]*(pi/180));
|
||
stewart = computeJointsPose(stewart);
|
||
stewart = initializeStrutDynamics(stewart, 'k', 1);
|
||
stewart = computeJacobian(stewart);
|
||
stewart = initializeCylindricalPlatforms(stewart, 'Fpr', 110e-3, 'Mpr', 110e-3);
|
||
|
||
displayArchitecture(stewart, 'labels', false, 'frames', false, 'F_color', [0,0,0], 'M_color', [0,0,0], 'L_color', [0,0,0]);
|
||
#+end_src
|
||
|
||
** DONE [#A] Make table for review of Stewart platforms
|
||
CLOSED: [2025-03-19 Wed 18:25]
|
||
|
||
[[file:~/Cloud/work-projects/ID31-NASS/matlab/stewart-simscape/org/bibliography.org::*Built Stewart PLatforms][Built Stewart PLatforms]]
|
||
|
||
Link to figures.
|
||
|
||
In figure legend: link to references, mention the university and the application.
|
||
|
||
** DONE [#C] Create a function to plot the mobility of the Stewart platform
|
||
CLOSED: [2025-03-30 Sun 18:31]
|
||
|
||
Arguments:
|
||
- choose to fix the orientation with ${}^{B}R_{A}$
|
||
- maximum stroke of each actuator (may be included in the Stewart object)
|
||
|
||
* Introduction :ignore:
|
||
|
||
- In the conceptual design phase, the geometry of the Stewart platform was chosen arbitrarily and not optimized
|
||
- In the detail design phase, we want to see if the geometry can be optimized to improve the overall performances
|
||
- Optimization criteria: mobility, stiffness, dynamical decoupling, more performance / bandwidth
|
||
|
||
Outline:
|
||
- Review of Stewart platform (Section ref:sec:detail_kinematics_stewart_review)
|
||
Geometry, Actuators, Sensors, Joints
|
||
- Effect of geometry on the Stewart platform characteristics (Section ref:sec:detail_kinematics_geometry)
|
||
- Cubic configuration: benefits? (Section ref:sec:detail_kinematics_cubic)
|
||
- Obtained geometry for the nano hexapod (Section ref:sec:detail_kinematics_nano_hexapod)
|
||
|
||
* Review of Stewart platforms
|
||
<<sec:detail_kinematics_stewart_review>>
|
||
** Introduction :ignore:
|
||
|
||
- As was explained in the conceptual phase, Stewart platform have the following key elements:
|
||
# Section ref:sec:nhexa_stewart_platform
|
||
- Two plates connected by six struts
|
||
- Each strut is composed of:
|
||
- a flexible joint at each end
|
||
- an actuator
|
||
- one or several sensors
|
||
- The exact geometry (i.e. position of joints and orientation of the struts) can be chosen freely depending on the application.
|
||
- This results in many different designs found in the literature.
|
||
- The focus is here made on Stewart platforms for nano-positioning and vibration control.
|
||
Long stroke stewart platforms are not considered here as their design impose other challenges.
|
||
Some Stewart platforms found in the literature are listed in Table ref:tab:detail_kinematics_stewart_review
|
||
- All presented Stewart platforms are using flexible joints, as it is a prerequisites for nano-positioning capabilities.
|
||
- Most of stewart platforms are using voice coil actuators or piezoelectric actuators.
|
||
The actuators used for the Stewart platform will be chosen in the next section.
|
||
# TODO - Add reference to the section
|
||
- Depending on the application, various sensors are integrated in the struts or on the plates.
|
||
The choice of sensor for the nano-hexapod will be described in the next section.
|
||
# TODO - Add reference to the section
|
||
- There are two categories of Stewart platform geometry:
|
||
- Cubic architecture (Figure ref:fig:detail_kinematics_stewart_examples_cubic).
|
||
Struts are positioned along 6 sides of a cubic (and are therefore orthogonal to each other).
|
||
Such specific architecture has some special properties that will be studied in Section ref:sec:detail_kinematics_cubic.
|
||
- Non-cubic architecture (Figure ref:fig:detail_kinematics_stewart_examples_non_cubic)
|
||
|
||
#+name: fig:detail_kinematics_stewart_examples_cubic
|
||
#+caption: Some examples of developped Stewart platform with Cubic geometry. (\subref{fig:detail_kinematics_jpl}), (\subref{fig:detail_kinematics_uw_gsp}), (\subref{fig:detail_kinematics_ulb_pz}), (\subref{fig:detail_kinematics_uqp})
|
||
#+attr_latex: :options [htbp]
|
||
#+begin_figure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_jpl}California Institute of Technology - USA}
|
||
#+attr_latex: :options {0.48\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.95\linewidth
|
||
[[file:figs/detail_kinematics_jpl.jpg]]
|
||
#+end_subfigure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_uw_gsp}University of Wyoming - USA}
|
||
#+attr_latex: :options {0.48\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.95\linewidth
|
||
[[file:figs/detail_kinematics_uw_gsp.jpg]]
|
||
#+end_subfigure
|
||
|
||
\bigskip
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_ulb_pz}ULB - Belgium}
|
||
#+attr_latex: :options {0.53\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.95\linewidth
|
||
[[file:figs/detail_kinematics_ulb_pz.jpg]]
|
||
#+end_subfigure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_uqp}Naval Postgraduate School - USA}
|
||
#+attr_latex: :options {0.43\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.95\linewidth
|
||
[[file:figs/detail_kinematics_uqp.jpg]]
|
||
#+end_subfigure
|
||
#+end_figure
|
||
|
||
#+name: fig:detail_kinematics_stewart_examples_non_cubic
|
||
#+caption: Some examples of developped Stewart platform with non-cubic geometry. (\subref{fig:detail_kinematics_pph}), (\subref{fig:detail_kinematics_zhang11}), (\subref{fig:detail_kinematics_yang19}), (\subref{fig:detail_kinematics_naves})
|
||
#+attr_latex: :options [htbp]
|
||
#+begin_figure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_pph}Naval Postgraduate School - USA}
|
||
#+attr_latex: :options {0.48\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :height 5cm
|
||
[[file:figs/detail_kinematics_pph.jpg]]
|
||
#+end_subfigure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_zhang11}Beihang University - China}
|
||
#+attr_latex: :options {0.48\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :height 5cm
|
||
[[file:figs/detail_kinematics_zhang11.jpg]]
|
||
#+end_subfigure
|
||
|
||
\bigskip
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_yang19}Nanjing University - China}
|
||
#+attr_latex: :options {0.43\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :height 5cm
|
||
[[file:figs/detail_kinematics_yang19.jpg]]
|
||
#+end_subfigure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_naves}University of Twente - Netherlands}
|
||
#+attr_latex: :options {0.53\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :height 5cm
|
||
[[file:figs/detail_kinematics_naves.jpg]]
|
||
#+end_subfigure
|
||
#+end_figure
|
||
|
||
#+name: tab:detail_kinematics_stewart_review
|
||
#+caption: Examples of Stewart platform developed. When not specifically indicated, sensors are included in the struts. All presented Stewart platforms are using flexible joints. The table is ordered by appearance in the literature
|
||
#+attr_latex: :environment tabularx :width \linewidth :align llllX
|
||
#+attr_latex: :center t :booktabs t :font \scriptsize
|
||
| | *Geometry* | *Actuators* | *Sensors* | *Reference* |
|
||
|------------------------------------------+--------------+------------------------------+------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||
| | Cubic | Magnetostrictive | Force, Accelerometers | [[cite:&geng93_six_degree_of_freed_activ;&geng94_six_degree_of_freed_activ;&geng95_intel_contr_system_multip_degree]] |
|
||
| Figure ref:fig:detail_kinematics_jpl | Cubic | Voice Coil (0.5 mm) | Force | [[cite:&spanos95_soft_activ_vibrat_isolat;&rahman98_multiax]] |
|
||
| | Cubic | Voice Coil (10 mm) | Force, LVDT, Geophones | [[cite:&thayer98_stewar;&thayer02_six_axis_vibrat_isolat_system;&hauge04_sensor_contr_space_based_six]] |
|
||
| Figure ref:fig:detail_kinematics_uw_gsp | Cubic | Voice Coil | Force | [[cite:&mcinroy99_dynam;&mcinroy99_precis_fault_toler_point_using_stewar_platf;&mcinroy00_desig_contr_flexur_joint_hexap;&li01_simul_vibrat_isolat_point_contr;&jafari03_orthog_gough_stewar_platf_microm]] |
|
||
| | Cubic | Piezoelectric ($25\,\mu m$) | Force | [[cite:&defendini00_techn]] |
|
||
| Figure ref:fig:detail_kinematics_ulb_pz | Cubic | APA ($50\,\mu m$) | Force | [[cite:&abu02_stiff_soft_stewar_platf_activ]] |
|
||
| Figure ref:fig:detail_kinematics_pph | Non-Cubic | Voice Coil | Accelerometers | [[cite:&chen03_payload_point_activ_vibrat_isolat]] |
|
||
| | Cubic | Voice Coil | Force | [[cite:&hanieh03_activ_stewar;&preumont07_six_axis_singl_stage_activ]] |
|
||
| Figure ref:fig:detail_kinematics_uqp | Cubic | Piezoelectric ($50\,\mu m$) | Geophone | [[cite:&agrawal04_algor_activ_vibrat_isolat_spacec]] |
|
||
| | Non-Cubic | Piezoelectric ($16\,\mu m$) | Eddy Current | [[cite:&furutani04_nanom_cuttin_machin_using_stewar]] |
|
||
| | Cubic | Piezoelectric ($120\,\mu m$) | (External) Capacitive | [[cite:&ting06_desig_stewar_nanos_platf;&ting13_compos_contr_desig_stewar_nanos_platf]] |
|
||
| | Non-Cubic | Piezoelectric ($160\,\mu m$) | (External) Capacitive | [[cite:&ting07_measur_calib_stewar_microm_system]] |
|
||
| Figure ref:fig:detail_kinematics_zhang11 | Non-cubic | Magnetostrictive | Accelerometer | [[cite:&zhang11_six_dof]] |
|
||
| | Non-Cubic | Piezoelectric | Strain Gauge | [[cite:&du14_piezo_actuat_high_precis_flexib]] |
|
||
| | Cubic | Voice Coil | Accelerometer | [[cite:&chi15_desig_exper_study_vcm_based;&tang18_decen_vibrat_contr_voice_coil;&jiao18_dynam_model_exper_analy_stewar]] |
|
||
| | Cubic | Piezoelectric | Force | [[cite:&wang16_inves_activ_vibrat_isolat_stewar]] |
|
||
| | Almost cubic | Voice Coil | Force, Accelerometer | [[cite:&beijen18_self_tunin_mimo_distur_feedf;&tjepkema12_activ_ph]] |
|
||
| Figure ref:fig:detail_kinematics_yang19 | Almost cubic | Piezoelectric | Force, Strain gauge | [[cite:&yang19_dynam_model_decoup_contr_flexib]] |
|
||
| Figure ref:fig:detail_kinematics_naves | Non-Cubic | 3-phase rotary motor | Rotary Encoder | [[cite:&naves20_desig;&naves20_t_flex]] |
|
||
|
||
Conclusion:
|
||
- Various Stewart platform designs:
|
||
- geometry, sizes, orientation of struts
|
||
- Lot's have a "cubic" architecture that will be discussed in Section ref:sec:detail_kinematics_cubic
|
||
- actuator types
|
||
- various sensors
|
||
- flexible joints (discussed in next chapter)
|
||
- The effect of geometry on the properties of the Stewart platform is studied in section ref:sec:detail_kinematics_geometry
|
||
- It is determined what is the optimal geometry for the NASS
|
||
|
||
* Effect of geometry on Stewart platform properties
|
||
:PROPERTIES:
|
||
:HEADER-ARGS:matlab+: :tangle matlab/detail_kinematics_1_geometry.m
|
||
:END:
|
||
<<sec:detail_kinematics_geometry>>
|
||
** Introduction :ignore:
|
||
|
||
# Section ref:sec:nhexa_stewart_platform (page pageref:sec:nhexa_stewart_platform),
|
||
- As was shown during the conceptual phase, the geometry of the Stewart platform influences:
|
||
- the stiffness and compliance properties
|
||
- the mobility
|
||
- the force authority
|
||
- the dynamics of the manipulator
|
||
- It is therefore important to understand how the geometry impact these properties, and to be able to optimize the geometry for a specific application.
|
||
|
||
One important tool to study this is the Jacobian matrix which depends on the $\bm{b}_i$ (join position w.r.t top platform) and $\hat{\bm{s}}_i$ (orientation of struts).
|
||
The choice of frames ($\{A\}$ and $\{B\}$), independently of the physical Stewart platform geometry, impacts the obtained kinematics and stiffness matrix, as it is defined for forces and motion evaluated at the chosen frame.
|
||
|
||
** 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
|
||
|
||
#+begin_src matlab :tangle no :noweb yes
|
||
<<m-init-path>>
|
||
#+end_src
|
||
|
||
#+begin_src matlab :eval no :noweb yes
|
||
<<m-init-path-tangle>>
|
||
#+end_src
|
||
|
||
#+begin_src matlab :noweb yes
|
||
<<m-init-simscape>>
|
||
#+end_src
|
||
|
||
#+begin_src matlab :noweb yes
|
||
<<m-init-other>>
|
||
#+end_src
|
||
|
||
** Platform Mobility / Workspace
|
||
**** Introduction :ignore:
|
||
|
||
The mobility of the Stewart platform (or any manipulator) is here defined as the range of motion that it can perform.
|
||
It corresponds to the set of possible pose (i.e. combined translation and rotation) of frame {B} with respect to frame {A}.
|
||
It should therefore be represented in a six dimensional space.
|
||
|
||
As was shown during the conceptual phase, for small displacements, the Jacobian matrix can be used to link the strut motion to the motion of frame B with respect to A through equation eqref:eq:detail_kinematics_jacobian.
|
||
# Section ref:ssec:nhexa_stewart_platform_jacobian (page pageref:ssec:nhexa_stewart_platform_jacobian).
|
||
|
||
\begin{equation}\label{eq:detail_kinematics_jacobian}
|
||
\begin{bmatrix} \delta l_1 \\ \delta l_2 \\ \delta l_3 \\ \delta l_4 \\ \delta l_5 \\ \delta l_6 \end{bmatrix} = \begin{bmatrix}
|
||
{{}^A\hat{\bm{s}}_1}^T & ({}^A\bm{b}_1 \times {}^A\hat{\bm{s}}_1)^T \\
|
||
{{}^A\hat{\bm{s}}_2}^T & ({}^A\bm{b}_2 \times {}^A\hat{\bm{s}}_2)^T \\
|
||
{{}^A\hat{\bm{s}}_3}^T & ({}^A\bm{b}_3 \times {}^A\hat{\bm{s}}_3)^T \\
|
||
{{}^A\hat{\bm{s}}_4}^T & ({}^A\bm{b}_4 \times {}^A\hat{\bm{s}}_4)^T \\
|
||
{{}^A\hat{\bm{s}}_5}^T & ({}^A\bm{b}_5 \times {}^A\hat{\bm{s}}_5)^T \\
|
||
{{}^A\hat{\bm{s}}_6}^T & ({}^A\bm{b}_6 \times {}^A\hat{\bm{s}}_6)^T
|
||
\end{bmatrix} \begin{bmatrix} \delta x \\ \delta y \\ \delta z \\ \delta \theta_x \\ \delta \theta_y \\ \delta \theta_z \end{bmatrix}
|
||
\end{equation}
|
||
|
||
Therefore, the mobility of the Stewart platform (set of $[\delta x\ \delta y\ \delta z\ \delta \theta_x\ \delta \theta_y\ \delta \theta_z]$) depends on:
|
||
- the stroke of each strut
|
||
- the geometry of the Stewart platform (embodied in the Jacobian matrix)
|
||
|
||
More specifically:
|
||
- the XYZ mobility only depends on the si (orientation of struts)
|
||
- the mobility in rotation depends on bi (position of top joints)
|
||
|
||
As will be shown in Section ref:sec:detail_kinematics_cubic, there are some geometry that gives same stroke in X, Y and Z directions.
|
||
|
||
As the mobility is of dimension six, it is difficult to represent.
|
||
Depending on the applications, only the translation mobility or the rotation mobility may be represented.
|
||
|
||
#+begin_quote
|
||
Although there is no human readable way to represent the complete workspace, some projections of the full workspace can be drawn.
|
||
#+end_quote
|
||
|
||
Difficulty of studying workspace of parallel manipulators.
|
||
|
||
**** Mobility in translation
|
||
|
||
Here, for simplicity, only translations are first considered:
|
||
- Let's consider a general Stewart platform geometry shown in Figure ref:fig:detail_kinematics_mobility_trans_arch.
|
||
- In the general case: the translational mobility can be represented by a 3D shape with 12 faces (each actuator limits the stroke along its orientation in positive and negative directions).
|
||
The faces are therefore perpendicular to the strut direction.
|
||
The obtained mobility is shown in Figure ref:fig:detail_kinematics_mobility_trans_result.
|
||
- Considering an actuator stroke of $\pm d$, the mobile platform can be translated in any direction with a stroke of $d$
|
||
A circle with radius $d$ can be contained in the general shape.
|
||
It will touch the shape along six lines defined by the strut axes.
|
||
The sphere with radius $d$ is shown in Figure ref:fig:detail_kinematics_mobility_trans_result.
|
||
- Therefore, for any (small stroke) Stewart platform with actuator stroke $\pm d$, it is possible to move the top platform in any direction by at least a distance $d$.
|
||
Note that no platform angular motion is here considered. When combining angular motion, the linear stroke decreases.
|
||
- When considering some symmetry in the system (as typically the case), the shape becomes a Trigonal trapezohedron whose height and width depends on the orientation of the struts.
|
||
We only get 6 faces as usually the Stewart platform consists of 3 sets of 2 parallels struts.
|
||
- In reality, portion of spheres, but well approximated by flat surfaces for short stroke hexapods.
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Example of one Stewart platform and associated translational mobility
|
||
L_max = 50e-6; % Maximum actuator stroke (+/-) [m]
|
||
|
||
stewart = initializeStewartPlatform();
|
||
stewart = initializeFramesPositions(stewart, 'H', 100e-3, 'MO_B', -50e-3);
|
||
stewart = generateGeneralConfiguration(stewart, 'FH', 0, 'FR', 100e-3, 'MH', 0, 'MR', 100e-3, ...
|
||
'FTh', [-5, 5, 120-5, 120+5, 240-5, 240+5]*(pi/180), ...
|
||
'MTh', [-60+5, 60-5, 60+5, 180-5, 180+5, -60-5]*(pi/180));
|
||
stewart = computeJointsPose(stewart);
|
||
stewart = initializeStrutDynamics(stewart, 'k', 1);
|
||
stewart = computeJacobian(stewart);
|
||
stewart = initializeCylindricalPlatforms(stewart, 'Fpr', 110e-3, 'Mpr', 110e-3);
|
||
|
||
displayArchitecture(stewart, 'labels', false, 'frames', false, 'F_color', [0,0,0], 'M_color', [0,0,0], 'L_color', [0,0,0]);
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_mobility_trans_arch.pdf', 'width', 'half', 'height', 'normal');
|
||
#+end_src
|
||
|
||
#+begin_src matlab
|
||
thetas = linspace(0, pi, 100);
|
||
phis = linspace(0, 2*pi, 100);
|
||
rs = zeros(length(thetas), length(phis));
|
||
|
||
for i = 1:length(thetas)
|
||
for j = 1:length(phis)
|
||
Tx = sin(thetas(i))*cos(phis(j));
|
||
Ty = sin(thetas(i))*sin(phis(j));
|
||
Tz = cos(thetas(i));
|
||
|
||
dL = stewart.kinematics.J*[Tx; Ty; Tz; 0; 0; 0;]; % dL required for 1m displacement in theta/phi direction
|
||
|
||
rs(i, j) = L_max/max(abs(dL));
|
||
end
|
||
end
|
||
|
||
% Sphere with radius equal to actuator stroke
|
||
[Xs,Ys,Zs] = sphere;
|
||
Xs = 1e6*L_max*Xs;
|
||
Ys = 1e6*L_max*Ys;
|
||
Zs = 1e6*L_max*Zs;
|
||
|
||
[phi_grid, theta_grid] = meshgrid(phis, thetas);
|
||
X = 1e6 * rs .* sin(theta_grid) .* cos(phi_grid);
|
||
Y = 1e6 * rs .* sin(theta_grid) .* sin(phi_grid);
|
||
Z = 1e6 * rs .* cos(theta_grid);
|
||
|
||
figure('Renderer', 'painters');
|
||
hold on;
|
||
surf(X, Y, Z, 'FaceColor', 'none', 'LineWidth', 0.1, 'EdgeColor', [0, 0, 0]);
|
||
surf(Xs, Ys, Zs, 'FaceColor', colors(2,:), 'EdgeColor', 'none');
|
||
quiver3(0, 0, 0, 100, 0, 0, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.9);
|
||
quiver3(0, 0, 0, 0, 100, 0, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.9);
|
||
quiver3(0, 0, 0, 0, 0, 100, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.9);
|
||
hold off;
|
||
axis equal;
|
||
grid off;
|
||
axis off;
|
||
view(55, 25);
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_mobility_trans_result.pdf', 'width', 'normal', 'height', 'tall', 'simplify', true);
|
||
#+end_src
|
||
|
||
#+name: fig:detail_kinematics_mobility_trans
|
||
#+caption: Example of one Stewart platform (\subref{fig:detail_kinematics_mobility_trans_arch}) and associated translational mobility (\subref{fig:detail_kinematics_mobility_trans_result})
|
||
#+attr_latex: :options [htbp]
|
||
#+begin_figure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_mobility_trans_arch}Stewart platform geometry}
|
||
#+attr_latex: :options {0.48\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :scale 1
|
||
[[file:figs/detail_kinematics_mobility_trans_arch.png]]
|
||
#+end_subfigure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_mobility_trans_result}Translational mobility}
|
||
#+attr_latex: :options {0.48\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :scale 1
|
||
[[file:figs/detail_kinematics_mobility_trans_result.png]]
|
||
#+end_subfigure
|
||
#+end_figure
|
||
|
||
To better understand how the geometry of the Stewart platform impacts the translational mobility, two configurations are compared:
|
||
- Struts oriented horizontally (Figure ref:fig:detail_kinematics_stewart_mobility_vert_struts) => more stroke in horizontal direction
|
||
- Struts oriented vertically (Figure ref:fig:detail_kinematics_stewart_mobility_hori_struts) => more stroke in vertical direction
|
||
- Corresponding mobility shown in Figure ref:fig:detail_kinematics_mobility_translation_strut_orientation
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Stewart platform with Vertically oriented struts
|
||
L_max = 50e-6; % Maximum actuator stroke (+/-) [m]
|
||
|
||
stewart_vert = initializeStewartPlatform();
|
||
stewart_vert = initializeFramesPositions(stewart_vert, 'H', 40e-3, 'MO_B', -20e-3);
|
||
stewart_vert = generateGeneralConfiguration(stewart_vert, 'FH', 0, 'FR', 100e-3, 'MH', 0, 'MR', 100e-3, ...
|
||
'FTh', [-25, 25, 120-25, 120+25, 240-25, 240+25]*(pi/180), ...
|
||
'MTh', [-60+25, 60-25, 60+25, 180-25, 180+25, -60-25]*(pi/180));
|
||
stewart_vert = computeJointsPose(stewart_vert);
|
||
stewart_vert = initializeStrutDynamics(stewart_vert, 'k', 1);
|
||
stewart_vert = computeJacobian(stewart_vert);
|
||
stewart_vert = initializeCylindricalPlatforms(stewart_vert, 'Fpr', 110e-3, 'Mpr', 110e-3);
|
||
|
||
displayArchitecture(stewart_vert, 'labels', false, 'frames', false, 'F_color', colors(1,:), 'M_color', colors(1,:), 'L_color', colors(1,:));
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_stewart_mobility_vert_struts.pdf', 'width', 'half', 'height', 'normal');
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Stewart platform with Horizontally oriented struts
|
||
stewart_hori = initializeStewartPlatform();
|
||
stewart_hori = initializeFramesPositions(stewart_hori, 'H', 40e-3, 'MO_B', -20e-3);
|
||
stewart_hori = generateGeneralConfiguration(stewart_hori, 'FH', 0, 'FR', 100e-3, 'MH', 0, 'MR', 100e-3, ...
|
||
'FTh', [-5, 5, 120-5, 120+5, 240-5, 240+5]*(pi/180), ...
|
||
'MTh', [-60+5, 60-5, 60+5, 180-5, 180+5, -60-5]*(pi/180));
|
||
stewart_hori = computeJointsPose(stewart_hori);
|
||
stewart_hori = initializeStrutDynamics(stewart_hori, 'k', 1);
|
||
stewart_hori = computeJacobian(stewart_hori);
|
||
stewart_hori = initializeCylindricalPlatforms(stewart_hori, 'Fpr', 110e-3, 'Mpr', 110e-3);
|
||
|
||
displayArchitecture(stewart_hori, 'labels', false, 'frames', false, 'F_color', colors(2,:), 'M_color', colors(2,:), 'L_color', colors(2,:));
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_stewart_mobility_hori_struts.pdf', 'width', 'half', 'height', 'normal');
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Translation mobility for two Stewart platform geometry
|
||
thetas = linspace(0, pi, 100);
|
||
phis = linspace(0, 2*pi, 100);
|
||
rs_vert = zeros(length(thetas), length(phis));
|
||
rs_hori = zeros(length(thetas), length(phis));
|
||
|
||
for i = 1:length(thetas)
|
||
for j = 1:length(phis)
|
||
Tx = sin(thetas(i))*cos(phis(j));
|
||
Ty = sin(thetas(i))*sin(phis(j));
|
||
Tz = cos(thetas(i));
|
||
|
||
dL = stewart_vert.kinematics.J*[Tx; Ty; Tz; 0; 0; 0;]; % dL required for 1m displacement in theta/phi direction
|
||
rs_vert(i, j) = L_max/max(abs(dL));
|
||
|
||
dL = stewart_hori.kinematics.J*[Tx; Ty; Tz; 0; 0; 0;]; % dL required for 1m displacement in theta/phi direction
|
||
rs_hori(i, j) = L_max/max(abs(dL));
|
||
end
|
||
end
|
||
|
||
[phi_grid, theta_grid] = meshgrid(phis, thetas);
|
||
|
||
X_vert = 1e6 * rs_vert .* sin(theta_grid) .* cos(phi_grid);
|
||
Y_vert = 1e6 * rs_vert .* sin(theta_grid) .* sin(phi_grid);
|
||
Z_vert = 1e6 * rs_vert .* cos(theta_grid);
|
||
|
||
X_hori = 1e6 * rs_hori .* sin(theta_grid) .* cos(phi_grid);
|
||
Y_hori = 1e6 * rs_hori .* sin(theta_grid) .* sin(phi_grid);
|
||
Z_hori = 1e6 * rs_hori .* cos(theta_grid);
|
||
|
||
[Xs,Ys,Zs] = sphere;
|
||
Xs = 1e6*L_max*Xs;
|
||
Ys = 1e6*L_max*Ys;
|
||
Zs = 1e6*L_max*Zs;
|
||
|
||
figure;
|
||
hold on;
|
||
surf(X_vert, Y_vert, Z_vert, 'FaceColor', 'white', 'LineWidth', 0.1, 'EdgeColor', colors(1,:));
|
||
surf(X_hori, Y_hori+400, Z_hori, 'FaceColor', 'white', 'LineWidth', 0.1, 'EdgeColor', colors(2,:));
|
||
quiver3(0, 0, 0, 200, 0, 0, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.7);
|
||
quiver3(0, 0, 0, 0, 200, 0, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.7);
|
||
quiver3(0, 0, 0, 0, 0, 200, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.7);
|
||
text(200, 0, 0, '$D_x$', 'FontSize', 10, 'HorizontalAlignment', 'center', 'VerticalAlignment', 'top' );
|
||
text(0, 200, 0, '$D_y$', 'FontSize', 10, 'HorizontalAlignment', 'right', 'VerticalAlignment', 'bottom');
|
||
text(0, 0, 200, '$D_z$', 'FontSize', 10, 'HorizontalAlignment', 'left', 'VerticalAlignment', 'top' );
|
||
quiver3(0, 400, 0, 200, 0, 0, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.7);
|
||
quiver3(0, 400, 0, 0, 200, 0, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.7);
|
||
quiver3(0, 400, 0, 0, 0, 200, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.7);
|
||
text(200, 400, 0, '$D_x$', 'FontSize', 10, 'HorizontalAlignment', 'center', 'VerticalAlignment', 'top' );
|
||
text(0, 600, 0, '$D_y$', 'FontSize', 10, 'HorizontalAlignment', 'right', 'VerticalAlignment', 'bottom');
|
||
text(0, 400, 200, '$D_z$', 'FontSize', 10, 'HorizontalAlignment', 'left', 'VerticalAlignment', 'top' );
|
||
hold off;
|
||
axis equal;
|
||
grid off;
|
||
axis off;
|
||
view(105, 15);
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_mobility_translation_strut_orientation.pdf', 'width', 'full', 'height', 'tall', 'simplify', true);
|
||
#+end_src
|
||
|
||
#+name: fig:detail_kinematics_stewart_mobility_examples
|
||
#+caption: Effect of strut orientation on the obtained mobility in translation. Two Stewart platform geometry are considered: struts oriented vertically (\subref{fig:detail_kinematics_stewart_mobility_vert_struts}) and struts oriented vertically (\subref{fig:detail_kinematics_stewart_mobility_hori_struts}). Obtained mobility for both geometry are shown in (\subref{fig:detail_kinematics_mobility_translation_strut_orientation}).
|
||
#+attr_latex: :options [htbp]
|
||
#+begin_figure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_stewart_mobility_vert_struts}Struts oriented vertically}
|
||
#+attr_latex: :options {0.48\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :scale 1
|
||
[[file:figs/detail_kinematics_stewart_mobility_vert_struts.png]]
|
||
#+end_subfigure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_stewart_mobility_hori_struts}Struts oriented horizontally}
|
||
#+attr_latex: :options {0.48\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :scale 1
|
||
[[file:figs/detail_kinematics_stewart_mobility_hori_struts.png]]
|
||
#+end_subfigure
|
||
|
||
\bigskip
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_mobility_translation_strut_orientation}Translational mobility of the two configurations}
|
||
#+attr_latex: :options {0.95\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :scale 1
|
||
[[file:figs/detail_kinematics_mobility_translation_strut_orientation.png]]
|
||
#+end_subfigure
|
||
#+end_figure
|
||
|
||
**** Mobility in rotation
|
||
|
||
As shown by equation eqref:eq:detail_kinematics_jacobian, the rotational mobility depends both on the orientation of the struts and on the location of the top joints.
|
||
|
||
Similarly to the translational case, to increase the rotational mobility in one direction, it is advantageous to have the struts more perpendicular to the rotational direction.
|
||
|
||
For instance, having the struts more vertical (Figure ref:fig:detail_kinematics_stewart_mobility_vert_struts) gives less rotational stroke along the vertical direction than having the struts oriented more horizontally (Figure ref:fig:detail_kinematics_stewart_mobility_hori_struts).
|
||
|
||
Two cases are considered with same strut orientation but with different top joints positions:
|
||
- struts close to each other (Figure ref:fig:detail_kinematics_stewart_mobility_close_struts)
|
||
- struts further apart (Figure ref:fig:detail_kinematics_stewart_mobility_space_struts)
|
||
|
||
The mobility for pure rotations are compared in Figure ref:fig:detail_kinematics_mobility_angle_strut_distance.
|
||
Note that the same strut stroke are considered in both cases to evaluate the mobility.
|
||
Having struts further apart decreases the "level arm" and therefore the rotational mobility is reduced.
|
||
|
||
For rotations and translations, having more mobility also means increasing the effect of actuator noise on the considering degree of freedom.
|
||
Somehow, the level arm is increased, so any strut vibration gets amplified.
|
||
Therefore, the designed Stewart platform should just have the necessary mobility.
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Stewart platform with struts close to each other
|
||
stewart_close = initializeStewartPlatform();
|
||
stewart_close = initializeFramesPositions(stewart_close, 'H', 100e-3, 'MO_B', 0);
|
||
stewart_close = generateGeneralConfiguration(stewart_close, 'FH', 0, 'FR', 50e-3, 'MH', 0, 'MR', 50e-3, ...
|
||
'FTh', [-6, 6, 120-6, 120+6, 240-6, 240+6]*(pi/180), ...
|
||
'MTh', [-60+6, 60-6, 60+6, 180-6, 180+6, -60-6]*(pi/180));
|
||
stewart_close = computeJointsPose(stewart_close);
|
||
stewart_close = initializeStrutDynamics(stewart_close, 'k', 1);
|
||
stewart_close = computeJacobian(stewart_close);
|
||
stewart_close = initializeCylindricalPlatforms(stewart_close, 'Fpr', 110e-3, 'Mpr', 110e-3);
|
||
|
||
displayArchitecture(stewart_close, 'labels', false, 'frames', false, 'F_color', colors(1,:), 'M_color', colors(1,:), 'L_color', colors(1,:));
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_stewart_mobility_close_struts.pdf', 'width', 'full', 'height', 'short');
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Stewart platform with struts further away from each other
|
||
stewart_space = initializeStewartPlatform();
|
||
stewart_space = initializeFramesPositions(stewart_space, 'H', 100e-3, 'MO_B', 0);
|
||
stewart_space = generateGeneralConfiguration(stewart_space, 'FH', 0, 'FR', 100e-3, 'MH', 0, 'MR', 100e-3, ...
|
||
'FTh', [-6, 6, 120-6, 120+6, 240-6, 240+6]*(pi/180), ...
|
||
'MTh', [-60+6, 60-6, 60+6, 180-6, 180+6, -60-6]*(pi/180));
|
||
stewart_space.platform_F.Fa = stewart_space.platform_M.Mb - (stewart_close.platform_M.Mb - stewart_close.platform_F.Fa);
|
||
stewart_space = computeJointsPose(stewart_space);
|
||
stewart_space = initializeStrutDynamics(stewart_space, 'k', 1);
|
||
stewart_space = computeJacobian(stewart_space);
|
||
stewart_space = initializeCylindricalPlatforms(stewart_space, 'Fpr', 110e-3, 'Mpr', 110e-3);
|
||
|
||
displayArchitecture(stewart_space, 'labels', false, 'frames', false, 'F_color', colors(2,:), 'M_color', colors(2,:), 'L_color', colors(2,:));
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_stewart_mobility_space_struts.pdf', 'width', 'full', 'height', 'short');
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Translation mobility for two Stewart platform geometry
|
||
thetas = linspace(0, pi, 50);
|
||
phis = linspace(0, 2*pi, 50);
|
||
rs_close = zeros(length(thetas), length(phis));
|
||
rs_space = zeros(length(thetas), length(phis));
|
||
|
||
for i = 1:length(thetas)
|
||
for j = 1:length(phis)
|
||
Rx = sin(thetas(i))*cos(phis(j));
|
||
Ry = sin(thetas(i))*sin(phis(j));
|
||
Rz = cos(thetas(i));
|
||
|
||
dL = stewart_close.kinematics.J*[0; 0; 0; Rx; Ry; Rz;];
|
||
rs_close(i, j) = L_max/max(abs(dL));
|
||
|
||
dL = stewart_space.kinematics.J*[0; 0; 0; Rx; Ry; Rz;];
|
||
rs_space(i, j) = L_max/max(abs(dL));
|
||
end
|
||
end
|
||
|
||
[phi_grid, theta_grid] = meshgrid(phis, thetas);
|
||
|
||
X_close = 1e6 * rs_close .* sin(theta_grid) .* cos(phi_grid);
|
||
Y_close = 1e6 * rs_close .* sin(theta_grid) .* sin(phi_grid);
|
||
Z_close = 1e6 * rs_close .* cos(theta_grid);
|
||
|
||
X_space = 1e6 * rs_space .* sin(theta_grid) .* cos(phi_grid);
|
||
Y_space = 1e6 * rs_space .* sin(theta_grid) .* sin(phi_grid);
|
||
Z_space = 1e6 * rs_space .* cos(theta_grid);
|
||
|
||
figure;
|
||
hold on;
|
||
surf(X_close, Y_close, Z_close, 'FaceColor', 'white', 'LineWidth', 0.1, 'EdgeColor', colors(1,:));
|
||
surf(X_space, Y_space+6000, Z_space, 'FaceColor', 'white', 'LineWidth', 0.1, 'EdgeColor', colors(2,:));
|
||
quiver3(0, 0, 0, 4000, 0, 0, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.7);
|
||
quiver3(0, 0, 0, 0, 4000, 0, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.7);
|
||
quiver3(0, 0, 0, 0, 0, 4000, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.7);
|
||
text(4000, 0, 0, '$R_x$', 'FontSize', 10, 'HorizontalAlignment', 'center', 'VerticalAlignment', 'top' );
|
||
text(0, 4000, 0, '$R_y$', 'FontSize', 10, 'HorizontalAlignment', 'right', 'VerticalAlignment', 'bottom');
|
||
text(0, 0, 4000, '$R_z$', 'FontSize', 10, 'HorizontalAlignment', 'left', 'VerticalAlignment', 'top' );
|
||
quiver3(0, 6000, 0, 4000, 0, 0, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.7);
|
||
quiver3(0, 6000, 0, 0, 4000, 0, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.7);
|
||
quiver3(0, 6000, 0, 0, 0, 4000, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.7);
|
||
text(4000, 6000, 0, '$R_x$', 'FontSize', 10, 'HorizontalAlignment', 'center', 'VerticalAlignment', 'top');
|
||
text(0, 10000, 0, '$R_y$', 'FontSize', 10, 'HorizontalAlignment', 'right', 'VerticalAlignment', 'bottom');
|
||
text(0, 6000, 4000, '$R_z$', 'FontSize', 10, 'HorizontalAlignment', 'left', 'VerticalAlignment', 'top');
|
||
hold off;
|
||
axis equal;
|
||
grid off;
|
||
axis off;
|
||
view(105, 15);
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_mobility_angle_strut_distance.pdf', 'width', 'full', 'height', 'full', 'simplify', true);
|
||
#+end_src
|
||
|
||
#+name: fig:detail_kinematics_stewart_mobility_examples
|
||
#+caption: Effect of strut position on the obtained mobility in rotation. Two Stewart platform geometry are considered: struts close to each other (\subref{fig:detail_kinematics_stewart_mobility_close_struts}) and struts further appart (\subref{fig:detail_kinematics_stewart_mobility_space_struts}). Obtained mobility for both geometry are shown in (\subref{fig:detail_kinematics_mobility_angle_strut_distance}).
|
||
#+attr_latex: :options [htbp]
|
||
#+begin_figure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_stewart_mobility_close_struts}Struts oriented closeically}
|
||
#+attr_latex: :options {0.48\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :scale 1
|
||
[[file:figs/detail_kinematics_stewart_mobility_close_struts.png]]
|
||
#+end_subfigure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_stewart_mobility_space_struts}Struts oriented spacezontally}
|
||
#+attr_latex: :options {0.48\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :scale 1
|
||
[[file:figs/detail_kinematics_stewart_mobility_space_struts.png]]
|
||
#+end_subfigure
|
||
|
||
\bigskip
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_mobility_angle_strut_distance}Translational mobility of the two configurations}
|
||
#+attr_latex: :options {0.95\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :scale 1
|
||
[[file:figs/detail_kinematics_mobility_angle_strut_distance.png]]
|
||
#+end_subfigure
|
||
#+end_figure
|
||
|
||
**** Combined translations and rotations
|
||
|
||
It is possible to consider combined translations and rotations.
|
||
Displaying such mobility is more complex.
|
||
It will be used for the nano-hexapod to verify that the obtained design has the necessary mobility.
|
||
|
||
For a fixed geometry and a wanted mobility (combined translations and rotations), it is possible to estimate the required minimum actuator stroke.
|
||
It will be done in Section ref:sec:detail_kinematics_nano_hexapod to estimate the required actuator stroke for the nano-hexapod geometry.
|
||
|
||
** Stiffness
|
||
**** Introduction :ignore:
|
||
|
||
Stiffness matrix:
|
||
- defines how the nano-hexapod deforms (frame $\{B\}$ with respect to frame $\{A\}$) due to static forces/torques applied on $\{B\}$.
|
||
- Depends on the Jacobian matrix (i.e. the geometry) and the strut axial stiffness eqref:eq:detail_kinematics_stiffness_matrix
|
||
- Contribution of joints stiffness is here not considered [[cite:&mcinroy00_desig_contr_flexur_joint_hexap;&mcinroy02_model_desig_flexur_joint_stewar]]
|
||
|
||
\begin{equation}\label{eq:detail_kinematics_stiffness_matrix}
|
||
\bm{K} = \bm{J}^T \bm{\mathcal{K}} \bm{J}
|
||
\end{equation}
|
||
|
||
It is assumed that the stiffness of all strut is the same: $\bm{\mathcal{K}} = k \cdot \mathbf{I}_6$.
|
||
Obtained stiffness matrix linearly depends on the strut stiffness $k$ eqref:eq:detail_kinematics_stiffness_matrix_simplified.
|
||
|
||
\begin{equation}\label{eq:detail_kinematics_stiffness_matrix_simplified}
|
||
\bm{K} = k \bm{J}^T \bm{J} =
|
||
k \left[
|
||
\begin{array}{c|c}
|
||
\Sigma_{i = 0}^{6} \hat{\bm{s}}_i \cdot \hat{\bm{s}}_i^T & \Sigma_{i = 0}^{6} \bm{\hat{s}}_i \cdot ({}^A\bm{b}_i \times {}^A\hat{\bm{s}}_i)^T \\
|
||
\hline
|
||
\Sigma_{i = 0}^{6} ({}^A\bm{b}_i \times {}^A\hat{\bm{s}}_i) \cdot \hat{\bm{s}}_i^T & \Sigma_{i = 0}^{6} ({}^A\bm{b}_i \times {}^A\hat{\bm{s}}_i) \cdot ({}^A\bm{b}_i \times {}^A\hat{\bm{s}}_i)^T\\
|
||
\end{array}
|
||
\right]
|
||
\end{equation}
|
||
|
||
**** Translation Stiffness
|
||
|
||
XYZ stiffnesses:
|
||
- Only depends on the orientation of the struts and not their location: $\hat{\bm{s}}_i \cdot \hat{\bm{s}}_i^T$
|
||
- Extreme case: all struts are vertical $s_i = [0,\ 0,\ 1]$ => vertical stiffness of $6 k$, but null stiffness in X and Y directions
|
||
- If two struts along X, two struts along Y, and two struts along Z => $\hat{\bm{s}}_i \cdot \hat{\bm{s}}_i^T = 2 \bm{I}_3$
|
||
Stiffness is well distributed along directions.
|
||
This corresponds to the cubic architecture.
|
||
|
||
If struts more vertical (Figure ref:fig:detail_kinematics_stewart_mobility_vert_struts):
|
||
- increase vertical stiffness
|
||
- decrease horizontal stiffness
|
||
- increase Rx,Ry stiffness
|
||
- decrease Rz stiffness
|
||
|
||
Opposite conclusions if struts are not horizontal (Figure ref:fig:detail_kinematics_stewart_mobility_hori_struts).
|
||
|
||
**** Rotational Stiffness
|
||
|
||
Rotational stiffnesses:
|
||
- Same orientation but increased distances (bi) by a factor 2 => rotational stiffness increased by factor 4
|
||
Figure ref:fig:detail_kinematics_stewart_mobility_close_struts
|
||
Figure ref:fig:detail_kinematics_stewart_mobility_space_struts
|
||
|
||
Struts further apart:
|
||
- no change to XYZ
|
||
- increase in rotational stiffness (by the square of the distance)
|
||
|
||
**** Diagonal Stiffness Matrix
|
||
|
||
Having the stiffness matrix $\bm{K}$ diagonal can be beneficial for control purposes as it would make the plant in the cartesian frame decoupled at low frequency.
|
||
|
||
This depends on the geometry and on the chosen {A} frame.
|
||
|
||
For specific configurations, it is possible to have a diagonal K matrix.
|
||
|
||
This will be discussed in Section ref:ssec:detail_kinematics_cubic_static.
|
||
|
||
** Dynamical properties
|
||
**** In the Cartesian Frame
|
||
|
||
Dynamical equations (both in the cartesian frame and in the frame of the struts) for the Stewart platform were derived during the conceptual phase with simplifying assumptions (massless struts and perfect joints).
|
||
# Section ref:ssec:nhexa_stewart_platform_dynamics (page pageref:ssec:nhexa_stewart_platform_dynamics).
|
||
|
||
The dynamics depends both on the geometry (Jacobian matrix) but also on the payload being placed on top of the platform.
|
||
|
||
Under very specific conditions, the equations of motion can be decoupled in the Cartesian space.
|
||
These are studied in Section ref:ssec:detail_kinematics_cubic_dynamic.
|
||
|
||
\begin{equation}\label{eq:nhexa_transfer_function_cart}
|
||
\frac{{\mathcal{X}}}{\bm{\mathcal{F}}}(s) = ( \bm{M} s^2 + \bm{J}^{T} \bm{\mathcal{C}} \bm{J} s + \bm{J}^{T} \bm{\mathcal{K}} \bm{J} )^{-1}
|
||
\end{equation}
|
||
|
||
**** In the frame of the Struts
|
||
|
||
In the frame of the struts, the equations of motion are well decoupled at low frequency.
|
||
This is why most of Stewart platforms are controlled in the frame of the struts: bellow the resonance frequency, the system is decoupled and SISO control may be applied for each strut.
|
||
|
||
\begin{equation}\label{eq:nhexa_transfer_function_struts}
|
||
\frac{\bm{\mathcal{L}}}{\bm{f}}(s) = ( \bm{J}^{-T} \bm{M} \bm{J}^{-1} s^2 + \bm{\mathcal{C}} + \bm{\mathcal{K}} )^{-1}
|
||
\end{equation}
|
||
|
||
Coupling between sensors (force sensors, relative position sensor, inertial sensors) in different struts may also be important for decentralized control.
|
||
Can the geometry be optimized to have lower coupling between the struts?
|
||
This will be studied with the cubic architecture.
|
||
|
||
**** TODO Dynamic Isotropy
|
||
|
||
[[cite:&afzali-far16_vibrat_dynam_isotr_hexap_analy_studies]]:
|
||
"*Dynamic isotropy*, leading to equal eigenfrequencies, is a powerful optimization measure."
|
||
|
||
** Conclusion
|
||
:PROPERTIES:
|
||
:UNNUMBERED: t
|
||
:END:
|
||
|
||
The effects of two changes in the manipulator's geometry, namely the position and orientation of the legs, are summarized in Table ref:tab:detail_kinematics_geometry.
|
||
These results could have been easily deduced based on some mechanical principles, but thanks to the kinematic analysis, they can be quantified.
|
||
|
||
These trade-offs give some guidelines when choosing the Stewart platform geometry.
|
||
|
||
#+name: tab:detail_kinematics_geometry
|
||
#+attr_latex: :environment tabularx :width \linewidth :align lXX
|
||
#+attr_latex: :center t :booktabs t :float t
|
||
#+caption: Effect of a change in geometry on the manipulator's stiffness, force authority and stroke
|
||
| | *legs pointing more vertically* | *legs further apart* |
|
||
|-------------------------------+---------------------------------+----------------------|
|
||
| Vertical stiffness | $\nearrow$ | $=$ |
|
||
| Horizontal stiffness | $\searrow$ | $=$ |
|
||
| Vertical rotation stiffness | $\searrow$ | $\nearrow$ |
|
||
| Horizontal rotation stiffness | $\nearrow$ | $\nearrow$ |
|
||
|-------------------------------+---------------------------------+----------------------|
|
||
| Vertical force authority | $\nearrow$ | $=$ |
|
||
| Horizontal force authority | $\searrow$ | $=$ |
|
||
| Vertical torque authority | $\searrow$ | $\nearrow$ |
|
||
| Horizontal torque authority | $\nearrow$ | $\nearrow$ |
|
||
|-------------------------------+---------------------------------+----------------------|
|
||
| Vertical stroke | $\searrow$ | $=$ |
|
||
| Horizontal stroke | $\nearrow$ | $=$ |
|
||
| Vertical rotation stroke | $\nearrow$ | $\searrow$ |
|
||
| Horizontal rotation stroke | $\searrow$ | $\searrow$ |
|
||
|
||
* The Cubic Architecture
|
||
:PROPERTIES:
|
||
:HEADER-ARGS:matlab+: :tangle matlab/detail_kinematics_2_cubic.m
|
||
:END:
|
||
<<sec:detail_kinematics_cubic>>
|
||
** Introduction :ignore:
|
||
|
||
# Cubic configuration file:~/Cloud/work-projects/ID31-NASS/matlab/stewart-simscape/org/cubic-configuration.org
|
||
|
||
The Cubic configuration for the Stewart platform was first proposed in [[cite:&geng94_six_degree_of_freed_activ]].
|
||
|
||
This configuration is quite specific in the sense that the active struts are arranged in a mutually orthogonal configuration connecting the corners of a cube Figure ref:fig:detail_kinematics_cubic_architecture_examples.
|
||
|
||
Cubic configuration:
|
||
- The struts are corresponding to 6 of the 8 edges of a cube.
|
||
- This way, all struts are perpendicular to each other (except sets of two that are parallel).
|
||
|
||
Struts with similar size than the cube's edge (Figure ref:fig:detail_kinematics_cubic_architecture_example).
|
||
Similar to Figures ref:fig:detail_kinematics_jpl, ref:fig:detail_kinematics_uw_gsp and ref:fig:detail_kinematics_uqp.
|
||
|
||
Struts smaller than the cube's edge (Figure ref:fig:detail_kinematics_cubic_architecture_example_small).
|
||
Similar to the Stewart platform of Figure ref:fig:detail_kinematics_ulb_pz.
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Example of a typical "cubic" architecture
|
||
MO_B = -50e-3; % Position {B} with respect to {M} [m]
|
||
|
||
H = 100e-3; % Height of the Stewart platform [m]
|
||
|
||
Hc = 100e-3; % Size of the useful part of the cube [m]
|
||
|
||
FOc = H + MO_B; % Center of the cube with respect to {F}
|
||
% here positionned at the frame {B}
|
||
|
||
stewart = initializeStewartPlatform();
|
||
stewart = initializeFramesPositions(stewart, 'H', H, 'MO_B', MO_B);
|
||
stewart = generateCubicConfiguration(stewart, 'Hc', Hc, 'FOc', FOc, 'FHa', 5e-3, 'MHb', 5e-3);
|
||
stewart = computeJointsPose(stewart);
|
||
stewart = initializeStrutDynamics(stewart, 'k', 1);
|
||
stewart = initializeJointDynamics(stewart)
|
||
stewart = initializeCylindricalPlatforms(stewart, 'Fpr', 150e-3, 'Mpr', 150e-3);
|
||
stewart = initializeCylindricalStruts(stewart);
|
||
stewart = computeJacobian(stewart);
|
||
stewart = initializeStewartPose(stewart)
|
||
|
||
displayArchitecture(stewart, 'labels', false, 'frames', false);
|
||
plotCube(stewart, 'Hc', Hc, 'FOc', FOc, 'color', [0,0,0,0.5], 'link_to_struts', true);
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_cubic_architecture_example.pdf', 'width', 'half', 'height', 600);
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Example of a typical "cubic" architecture
|
||
MO_B = -20e-3; % Position {B} with respect to {M} [m]
|
||
|
||
H = 40e-3; % Height of the Stewart platform [m]
|
||
|
||
Hc = 100e-3; % Size of the useful part of the cube [m]
|
||
|
||
FOc = H + MO_B; % Center of the cube with respect to {F}
|
||
% here positionned at the frame {B}
|
||
|
||
stewart = initializeStewartPlatform();
|
||
stewart = initializeFramesPositions(stewart, 'H', H, 'MO_B', MO_B);
|
||
stewart = generateCubicConfiguration(stewart, 'Hc', Hc, 'FOc', FOc, 'FHa', 5e-3, 'MHb', 5e-3);
|
||
stewart = computeJointsPose(stewart);
|
||
stewart = initializeStrutDynamics(stewart, 'k', 1);
|
||
stewart = computeJacobian(stewart);
|
||
stewart = initializeCylindricalPlatforms(stewart, 'Fpr', 150e-3, 'Mpr', 150e-3);
|
||
|
||
displayArchitecture(stewart, 'labels', false, 'frames', false);
|
||
plotCube(stewart, 'Hc', Hc, 'FOc', FOc, 'color', [0,0,0,0.5], 'link_to_struts', true);
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_cubic_architecture_example_small.pdf', 'width', 'half', 'height', 600);
|
||
#+end_src
|
||
|
||
#+name: fig:detail_kinematics_cubic_architecture_examples
|
||
#+caption: Caption with reference to sub figure (\subref{fig:detail_kinematics_cubic_architecture_example}) (\subref{fig:detail_kinematics_cubic_architecture_example_small})
|
||
#+attr_latex: :options [htbp]
|
||
#+begin_figure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_cubic_architecture_example}sub caption a}
|
||
#+attr_latex: :options {0.49\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :scale 1
|
||
[[file:figs/detail_kinematics_cubic_architecture_example.png]]
|
||
#+end_subfigure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_cubic_architecture_example_small}sub caption b}
|
||
#+attr_latex: :options {0.49\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :scale 1
|
||
[[file:figs/detail_kinematics_cubic_architecture_example_small.png]]
|
||
#+end_subfigure
|
||
#+end_figure
|
||
|
||
|
||
The cubic configuration is attributed a number of properties that made this configuration widely used ([[cite:&preumont07_six_axis_singl_stage_activ;&jafari03_orthog_gough_stewar_platf_microm]]).
|
||
From [[cite:&geng94_six_degree_of_freed_activ]]:
|
||
1) Uniformity in control capability in all directions
|
||
2) Uniformity in stiffness in all directions
|
||
3) Minimum cross coupling force effect among actuators
|
||
4) Facilitate collocated sensor-actuator control system design
|
||
5) Simple kinematics relationships
|
||
6) Simple dynamic analysis
|
||
7) Simple mechanical design
|
||
|
||
According to [[cite:&preumont07_six_axis_singl_stage_activ]], it "minimizes the cross-coupling amongst actuators and sensors of different legs" (being orthogonal to each other).
|
||
|
||
Specific points of interest are:
|
||
- uniform mobility, uniform stiffness, and coupling properties
|
||
|
||
In this section:
|
||
- Such properties are studied
|
||
- Additional properties interesting for control?
|
||
- It is determined if the cubic architecture is interested for the nano-hexapod
|
||
|
||
** 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
|
||
|
||
#+begin_src matlab :tangle no :noweb yes
|
||
<<m-init-path>>
|
||
#+end_src
|
||
|
||
#+begin_src matlab :eval no :noweb yes
|
||
<<m-init-path-tangle>>
|
||
#+end_src
|
||
|
||
#+begin_src matlab :noweb yes
|
||
<<m-init-simscape>>
|
||
#+end_src
|
||
|
||
#+begin_src matlab :noweb yes
|
||
<<m-init-other>>
|
||
#+end_src
|
||
|
||
** Static Properties
|
||
<<ssec:detail_kinematics_cubic_static>>
|
||
**** Stiffness matrix for the Cubic architecture
|
||
Consider the cubic architecture shown in Figure ref:fig:detail_kinematics_cubic_schematic_full.
|
||
|
||
The unit vectors corresponding to the edges of the cube are described by eqref:eq:detail_kinematics_cubic_s.
|
||
|
||
\begin{equation}\label{eq:detail_kinematics_cubic_s}
|
||
\hat{\bm{s}}_1 = \begin{bmatrix} \sqrt{2}/\sqrt{3} \\ 0 \\ 1/\sqrt{3} \end{bmatrix} \quad
|
||
\hat{\bm{s}}_2 = \begin{bmatrix} -1/\sqrt{6} \\ -1/\sqrt{2} \\ 1/\sqrt{3} \end{bmatrix} \quad
|
||
\hat{\bm{s}}_3 = \begin{bmatrix} -1/\sqrt{6} \\ 1/\sqrt{2} \\ 1/\sqrt{3} \end{bmatrix} \quad
|
||
\hat{\bm{s}}_4 = \begin{bmatrix} \sqrt{2}/\sqrt{3} \\ 0 \\ 1/\sqrt{3} \end{bmatrix} \quad
|
||
\hat{\bm{s}}_5 = \begin{bmatrix} -1/\sqrt{6} \\ -1/\sqrt{2} \\ 1/\sqrt{3} \end{bmatrix} \quad
|
||
\hat{\bm{s}}_6 = \begin{bmatrix} -1/\sqrt{6} \\ 1/\sqrt{2} \\ 1/\sqrt{3} \end{bmatrix}
|
||
\end{equation}
|
||
|
||
Coordinates of the cube's vertices relevant for the top joints, expressed with respect to the cube's center eqref:eq:detail_kinematics_cubic_vertices.
|
||
|
||
\begin{equation}\label{eq:detail_kinematics_cubic_vertices}
|
||
\tilde{\bm{b}}_1 = \tilde{\bm{b}}_2 = H_c \begin{bmatrix} \frac{1}{\sqrt{2}} \\ \frac{-\sqrt{3}}{\sqrt{2}} \\ \frac{1}{2} \end{bmatrix}, \quad
|
||
\tilde{\bm{b}}_3 = \tilde{\bm{b}}_4 = H_c \begin{bmatrix} \frac{1}{\sqrt{2}} \\ \frac{ \sqrt{3}}{\sqrt{2}} \\ \frac{1}{2} \end{bmatrix}, \quad
|
||
\tilde{\bm{b}}_5 = \tilde{\bm{b}}_6 = H_c \begin{bmatrix} \frac{-2}{\sqrt{2}} \\ 0 \\ \frac{1}{2} \end{bmatrix}
|
||
\end{equation}
|
||
|
||
#+begin_src latex :file detail_kinematics_cubic_schematic_full.pdf :results file none
|
||
\begin{tikzpicture}
|
||
\begin{scope}[rotate={45}, shift={(0, 0, -4)}]
|
||
% We first define the coordinate of the points of the Cube
|
||
\coordinate[] (bot) at (0,0,4);
|
||
\coordinate[] (top) at (4,4,0);
|
||
\coordinate[] (A1) at (0,0,0);
|
||
\coordinate[] (A2) at (4,0,4);
|
||
\coordinate[] (A3) at (0,4,4);
|
||
\coordinate[] (B1) at (4,0,0);
|
||
\coordinate[] (B2) at (4,4,4);
|
||
\coordinate[] (B3) at (0,4,0);
|
||
|
||
% Center of the Cube
|
||
\node[] (cubecenter) at ($0.5*(bot) + 0.5*(top)$){$\bullet$};
|
||
|
||
% We draw parts of the cube that corresponds to the Stewart platform
|
||
\draw[] (A1)node[]{$\bullet$} -- (B1)node[]{$\bullet$} -- (A2)node[]{$\bullet$} -- (B2)node[]{$\bullet$} -- (A3)node[]{$\bullet$} -- (B3)node[]{$\bullet$} -- (A1);
|
||
|
||
% ai and bi are computed
|
||
\def\lfrom{0.0}
|
||
\def\lto{1.0}
|
||
|
||
\coordinate(a1) at ($(A1) - \lfrom*(A1) + \lfrom*(B1)$);
|
||
\coordinate(b1) at ($(A1) - \lto*(A1) + \lto*(B1)$);
|
||
\coordinate(a2) at ($(A2) - \lfrom*(A2) + \lfrom*(B1)$);
|
||
\coordinate(b2) at ($(A2) - \lto*(A2) + \lto*(B1)$);
|
||
\coordinate(a3) at ($(A2) - \lfrom*(A2) + \lfrom*(B2)$);
|
||
\coordinate(b3) at ($(A2) - \lto*(A2) + \lto*(B2)$);
|
||
\coordinate(a4) at ($(A3) - \lfrom*(A3) + \lfrom*(B2)$);
|
||
\coordinate(b4) at ($(A3) - \lto*(A3) + \lto*(B2)$);
|
||
\coordinate(a5) at ($(A3) - \lfrom*(A3) + \lfrom*(B3)$);
|
||
\coordinate(b5) at ($(A3) - \lto*(A3) + \lto*(B3)$);
|
||
\coordinate(a6) at ($(A1) - \lfrom*(A1) + \lfrom*(B3)$);
|
||
\coordinate(b6) at ($(A1) - \lto*(A1) + \lto*(B3)$);
|
||
|
||
% We draw the fixed and mobiles platforms
|
||
\path[fill=colorblue, opacity=0.2] (a1) -- (a2) -- (a3) -- (a4) -- (a5) -- (a6) -- cycle;
|
||
\path[fill=colorblue, opacity=0.2] (b1) -- (b2) -- (b3) -- (b4) -- (b5) -- (b6) -- cycle;
|
||
\draw[color=colorblue, dashed] (a1) -- (a2) -- (a3) -- (a4) -- (a5) -- (a6) -- cycle;
|
||
\draw[color=colorblue, dashed] (b1) -- (b2) -- (b3) -- (b4) -- (b5) -- (b6) -- cycle;
|
||
|
||
% The legs of the hexapod are drawn
|
||
\draw[color=colorblue] (a1)node{$\bullet$} -- (b1)node{$\bullet$};
|
||
\draw[color=colorblue] (a2)node{$\bullet$} -- (b2)node{$\bullet$};
|
||
\draw[color=colorblue] (a3)node{$\bullet$} -- (b3)node{$\bullet$};
|
||
\draw[color=colorblue] (a4)node{$\bullet$} -- (b4)node{$\bullet$};
|
||
\draw[color=colorblue] (a5)node{$\bullet$} -- (b5)node{$\bullet$};
|
||
\draw[color=colorblue] (a6)node{$\bullet$} -- (b6)node{$\bullet$};
|
||
|
||
% Unit vector
|
||
\draw[color=colorred, ->] ($0.9*(a1)+0.1*(b1)$)node{$\bullet$} -- ($0.65*(a1)+0.35*(b1)$)node[right]{$\hat{\bm{s}}_3$};
|
||
\draw[color=colorred, ->] ($0.9*(a2)+0.1*(b2)$)node{$\bullet$} -- ($0.65*(a2)+0.35*(b2)$)node[left]{$\hat{\bm{s}}_4$};
|
||
\draw[color=colorred, ->] ($0.9*(a3)+0.1*(b3)$)node{$\bullet$} -- ($0.65*(a3)+0.35*(b3)$)node[below]{$\hat{\bm{s}}_5$};
|
||
\draw[color=colorred, ->] ($0.9*(a4)+0.1*(b4)$)node{$\bullet$} -- ($0.65*(a4)+0.35*(b4)$)node[below]{$\hat{\bm{s}}_6$};
|
||
\draw[color=colorred, ->] ($0.9*(a5)+0.1*(b5)$)node{$\bullet$} -- ($0.65*(a5)+0.35*(b5)$)node[left]{$\hat{\bm{s}}_1$};
|
||
\draw[color=colorred, ->] ($0.9*(a6)+0.1*(b6)$)node{$\bullet$} -- ($0.65*(a6)+0.35*(b6)$)node[right]{$\hat{\bm{s}}_2$};
|
||
|
||
% Labels
|
||
\node[above=0.1 of B1] {$\tilde{\bm{b}}_3 = \tilde{\bm{b}}_4$};
|
||
\node[above=0.1 of B2] {$\tilde{\bm{b}}_5 = \tilde{\bm{b}}_6$};
|
||
\node[above=0.1 of B3] {$\tilde{\bm{b}}_1 = \tilde{\bm{b}}_2$};
|
||
\end{scope}
|
||
|
||
% Height of the Hexapod
|
||
\coordinate[] (sizepos) at ($(a2)+(0.2, 0)$);
|
||
\coordinate[] (origin) at (0,0,0);
|
||
|
||
\draw[->] (cubecenter.center) node[above right]{$\{B\}$} -- ++(0,0,1);
|
||
\draw[->] (cubecenter.center) -- ++(1,0,0);
|
||
\draw[->] (cubecenter.center) -- ++(0,1,0);
|
||
|
||
% Useful part of the cube
|
||
\draw[<->, dashed] ($(A2)+(0.5,0)$) -- node[midway, right]{$H_{C}$} ($(B1)+(0.5,0)$);
|
||
\end{tikzpicture}
|
||
#+end_src
|
||
|
||
#+begin_src latex :file detail_kinematics_cubic_schematic.pdf :results file none
|
||
\begin{tikzpicture}
|
||
\begin{scope}[rotate={45}, shift={(0, 0, -4)}]
|
||
% We first define the coordinate of the points of the Cube
|
||
\coordinate[] (bot) at (0,0,4);
|
||
\coordinate[] (top) at (4,4,0);
|
||
\coordinate[] (A1) at (0,0,0);
|
||
\coordinate[] (A2) at (4,0,4);
|
||
\coordinate[] (A3) at (0,4,4);
|
||
\coordinate[] (B1) at (4,0,0);
|
||
\coordinate[] (B2) at (4,4,4);
|
||
\coordinate[] (B3) at (0,4,0);
|
||
|
||
% Center of the Cube
|
||
\node[] (cubecenter) at ($0.5*(bot) + 0.5*(top)$){$\bullet$};
|
||
|
||
% We draw parts of the cube that corresponds to the Stewart platform
|
||
\draw[] (A1)node[]{$\bullet$} -- (B1)node[]{$\bullet$} -- (A2)node[]{$\bullet$} -- (B2)node[]{$\bullet$} -- (A3)node[]{$\bullet$} -- (B3)node[]{$\bullet$} -- (A1);
|
||
|
||
% ai and bi are computed
|
||
\def\lfrom{0.2}
|
||
\def\lto{0.8}
|
||
|
||
\coordinate(a1) at ($(A1) - \lfrom*(A1) + \lfrom*(B1)$);
|
||
\coordinate(b1) at ($(A1) - \lto*(A1) + \lto*(B1)$);
|
||
\coordinate(a2) at ($(A2) - \lfrom*(A2) + \lfrom*(B1)$);
|
||
\coordinate(b2) at ($(A2) - \lto*(A2) + \lto*(B1)$);
|
||
\coordinate(a3) at ($(A2) - \lfrom*(A2) + \lfrom*(B2)$);
|
||
\coordinate(b3) at ($(A2) - \lto*(A2) + \lto*(B2)$);
|
||
\coordinate(a4) at ($(A3) - \lfrom*(A3) + \lfrom*(B2)$);
|
||
\coordinate(b4) at ($(A3) - \lto*(A3) + \lto*(B2)$);
|
||
\coordinate(a5) at ($(A3) - \lfrom*(A3) + \lfrom*(B3)$);
|
||
\coordinate(b5) at ($(A3) - \lto*(A3) + \lto*(B3)$);
|
||
\coordinate(a6) at ($(A1) - \lfrom*(A1) + \lfrom*(B3)$);
|
||
\coordinate(b6) at ($(A1) - \lto*(A1) + \lto*(B3)$);
|
||
|
||
% We draw the fixed and mobiles platforms
|
||
\path[fill=colorblue, opacity=0.2] (a1) -- (a2) -- (a3) -- (a4) -- (a5) -- (a6) -- cycle;
|
||
\path[fill=colorblue, opacity=0.2] (b1) -- (b2) -- (b3) -- (b4) -- (b5) -- (b6) -- cycle;
|
||
\draw[color=colorblue, dashed] (a1) -- (a2) -- (a3) -- (a4) -- (a5) -- (a6) -- cycle;
|
||
\draw[color=colorblue, dashed] (b1) -- (b2) -- (b3) -- (b4) -- (b5) -- (b6) -- cycle;
|
||
|
||
% The legs of the hexapod are drawn
|
||
\draw[color=colorblue] (a1)node{$\bullet$} -- (b1)node{$\bullet$}node[below right]{$\bm{b}_3$};
|
||
\draw[color=colorblue] (a2)node{$\bullet$} -- (b2)node{$\bullet$}node[right]{$\bm{b}_4$};
|
||
\draw[color=colorblue] (a3)node{$\bullet$} -- (b3)node{$\bullet$}node[above right]{$\bm{b}_5$};
|
||
\draw[color=colorblue] (a4)node{$\bullet$} -- (b4)node{$\bullet$}node[above left]{$\bm{b}_6$};
|
||
\draw[color=colorblue] (a5)node{$\bullet$} -- (b5)node{$\bullet$}node[left]{$\bm{b}_1$};
|
||
\draw[color=colorblue] (a6)node{$\bullet$} -- (b6)node{$\bullet$}node[below left]{$\bm{b}_2$};
|
||
|
||
% Labels
|
||
\node[above=0.1 of B1] {$\tilde{\bm{b}}_3 = \tilde{\bm{b}}_4$};
|
||
\node[above=0.1 of B2] {$\tilde{\bm{b}}_5 = \tilde{\bm{b}}_6$};
|
||
\node[above=0.1 of B3] {$\tilde{\bm{b}}_1 = \tilde{\bm{b}}_2$};
|
||
\end{scope}
|
||
|
||
% Height of the Hexapod
|
||
\coordinate[] (sizepos) at ($(a2)+(0.2, 0)$);
|
||
\coordinate[] (origin) at (0,0,0);
|
||
|
||
\draw[->] (cubecenter.center) node[above right]{$\{B\}$} -- ++(0,0,1);
|
||
\draw[->] (cubecenter.center) -- ++(1,0,0);
|
||
\draw[->] (cubecenter.center) -- ++(0,1,0);
|
||
\end{tikzpicture}
|
||
#+end_src
|
||
|
||
#+begin_src latex :file detail_kinematics_cubic_schematic_off_centered.pdf :results file none
|
||
\begin{tikzpicture}
|
||
\begin{scope}[rotate={45}, shift={(0, 0, -4)}]
|
||
% We first define the coordinate of the points of the Cube
|
||
\coordinate[] (bot) at (0,0,4);
|
||
\coordinate[] (top) at (4,4,0);
|
||
\coordinate[] (A1) at (0,0,0);
|
||
\coordinate[] (A2) at (4,0,4);
|
||
\coordinate[] (A3) at (0,4,4);
|
||
\coordinate[] (B1) at (4,0,0);
|
||
\coordinate[] (B2) at (4,4,4);
|
||
\coordinate[] (B3) at (0,4,0);
|
||
|
||
% Center of the Cube
|
||
\node[] (cubecenter) at ($0.5*(bot) + 0.5*(top)$){$\bullet$};
|
||
|
||
% We draw parts of the cube that corresponds to the Stewart platform
|
||
\draw[] (A1)node[]{$\bullet$} -- (B1)node[]{$\bullet$} -- (A2)node[]{$\bullet$} -- (B2)node[]{$\bullet$} -- (A3)node[]{$\bullet$} -- (B3)node[]{$\bullet$} -- (A1);
|
||
|
||
% ai and bi are computed
|
||
\def\lfrom{0.1}
|
||
\def\lto{0.9}
|
||
|
||
\coordinate(a1) at ($(A1) - \lfrom*(A1) + \lfrom*(B1)$);
|
||
\coordinate(b1) at ($(A1) - \lto*(A1) + \lto*(B1)$);
|
||
\coordinate(a2) at ($(A2) - \lfrom*(A2) + \lfrom*(B1)$);
|
||
\coordinate(b2) at ($(A2) - \lto*(A2) + \lto*(B1)$);
|
||
\coordinate(a3) at ($(A2) - \lfrom*(A2) + \lfrom*(B2)$);
|
||
\coordinate(b3) at ($(A2) - \lto*(A2) + \lto*(B2)$);
|
||
\coordinate(a4) at ($(A3) - \lfrom*(A3) + \lfrom*(B2)$);
|
||
\coordinate(b4) at ($(A3) - \lto*(A3) + \lto*(B2)$);
|
||
\coordinate(a5) at ($(A3) - \lfrom*(A3) + \lfrom*(B3)$);
|
||
\coordinate(b5) at ($(A3) - \lto*(A3) + \lto*(B3)$);
|
||
\coordinate(a6) at ($(A1) - \lfrom*(A1) + \lfrom*(B3)$);
|
||
\coordinate(b6) at ($(A1) - \lto*(A1) + \lto*(B3)$);
|
||
|
||
% We draw the fixed and mobiles platforms
|
||
\path[fill=colorblue, opacity=0.2] (a1) -- (a2) -- (a3) -- (a4) -- (a5) -- (a6) -- cycle;
|
||
\path[fill=colorblue, opacity=0.2] (b1) -- (b2) -- (b3) -- (b4) -- (b5) -- (b6) -- cycle;
|
||
\draw[color=colorblue, dashed] (a1) -- (a2) -- (a3) -- (a4) -- (a5) -- (a6) -- cycle;
|
||
\draw[color=colorblue, dashed] (b1) -- (b2) -- (b3) -- (b4) -- (b5) -- (b6) -- cycle;
|
||
|
||
% The legs of the hexapod are drawn
|
||
\draw[color=colorblue] (a1)node{$\bullet$} -- (b1)node{$\bullet$};
|
||
\draw[color=colorblue] (a2)node{$\bullet$} -- (b2)node{$\bullet$};
|
||
\draw[color=colorblue] (a3)node{$\bullet$} -- (b3)node{$\bullet$};
|
||
\draw[color=colorblue] (a4)node{$\bullet$} -- (b4)node{$\bullet$};
|
||
\draw[color=colorblue] (a5)node{$\bullet$} -- (b5)node{$\bullet$};
|
||
\draw[color=colorblue] (a6)node{$\bullet$} -- (b6)node{$\bullet$};
|
||
\end{scope}
|
||
|
||
% Height of the Hexapod
|
||
\coordinate[] (sizepos) at ($(a2)+(0.2, 0)$);
|
||
\coordinate[] (origin) at (0,0,0);
|
||
|
||
\draw[->] ($(cubecenter.center)+(0,2.0,0)$) node[above right]{$\{B\}$} -- ++(0,0,1);
|
||
\draw[->] ($(cubecenter.center)+(0,2.0,0)$) -- ++(1,0,0);
|
||
\draw[->] ($(cubecenter.center)+(0,2.0,0)$) -- ++(0,1,0);
|
||
|
||
\draw[<->, dashed] (cubecenter.center) -- node[midway, right]{$H$} ($(cubecenter.center)+(0,2.0,0)$);
|
||
\end{tikzpicture}
|
||
#+end_src
|
||
|
||
#+name: fig:detail_kinematics_cubic_schematic_cases
|
||
#+caption: Struts are represented un blue. The cube's center by a dot.
|
||
#+attr_latex: :options [htbp]
|
||
#+begin_figure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_cubic_schematic_full}Full cube}
|
||
#+attr_latex: :options {0.33\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.9\linewidth
|
||
[[file:figs/detail_kinematics_cubic_schematic_full.png]]
|
||
#+end_subfigure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_cubic_schematic}Cube's portion}
|
||
#+attr_latex: :options {0.33\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.9\linewidth
|
||
[[file:figs/detail_kinematics_cubic_schematic.png]]
|
||
#+end_subfigure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_cubic_schematic_off_centered}Off Centered}
|
||
#+attr_latex: :options {0.33\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.9\linewidth
|
||
[[file:figs/detail_kinematics_cubic_schematic_off_centered.png]]
|
||
#+end_subfigure
|
||
#+end_figure
|
||
|
||
#+begin_src matlab
|
||
%% Analytical formula for Stiffness matrix of the Cubic Stewart platform
|
||
% Define symbolic variables
|
||
syms k Hc alpha H
|
||
|
||
assume(k > 0); % k is positive real
|
||
assume(Hc, 'real'); % Hc is real
|
||
assume(H, 'real'); % H is real
|
||
assume(alpha, 'real'); % alpha is real
|
||
|
||
% Define si matrix (edges of the cubes)
|
||
si = 1/sqrt(3)*[
|
||
[ sqrt(2), 0, 1]; ...
|
||
[-sqrt(2)/2, -sqrt(3/2), 1]; ...
|
||
[-sqrt(2)/2, sqrt(3/2), 1]; ...
|
||
[ sqrt(2), 0, 1]; ...
|
||
[-sqrt(2)/2, -sqrt(3/2), 1]; ...
|
||
[-sqrt(2)/2, sqrt(3/2), 1] ...
|
||
];
|
||
|
||
% Define ci matrix (vertices of the cubes)
|
||
ci = Hc * [
|
||
[1/sqrt(2), -sqrt(3)/sqrt(2), 0.5]; ...
|
||
[1/sqrt(2), -sqrt(3)/sqrt(2), 0.5]; ...
|
||
[1/sqrt(2), sqrt(3)/sqrt(2), 0.5]; ...
|
||
[1/sqrt(2), sqrt(3)/sqrt(2), 0.5]; ...
|
||
[-sqrt(2), 0, 0.5]; ...
|
||
[-sqrt(2), 0, 0.5] ...
|
||
];
|
||
|
||
% Apply vertical shift to ci
|
||
ci = ci + H * [0, 0, 1];
|
||
|
||
% Calculate bi vectors (Stewart platform top joints)
|
||
bi = ci + alpha * si;
|
||
|
||
% Initialize stiffness matrix
|
||
K = sym(zeros(6,6));
|
||
|
||
% Calculate elements of the stiffness matrix
|
||
for i = 1:6
|
||
% Extract vectors for each leg
|
||
s_i = si(i,:)';
|
||
b_i = bi(i,:)';
|
||
|
||
% Calculate cross product vector
|
||
cross_bs = cross(b_i, s_i);
|
||
|
||
% Build matrix blocks
|
||
K(1:3, 4:6) = K(1:3, 4:6) + s_i * cross_bs';
|
||
K(4:6, 1:3) = K(4:6, 1:3) + cross_bs * s_i';
|
||
K(1:3, 1:3) = K(1:3, 1:3) + s_i * s_i';
|
||
K(4:6, 4:6) = K(4:6, 4:6) + cross_bs * cross_bs';
|
||
end
|
||
|
||
% Scale by stiffness coefficient
|
||
K = k * K;
|
||
|
||
% Simplify the expressions
|
||
K = simplify(K);
|
||
|
||
% Display the analytical stiffness matrix
|
||
disp('Analytical Stiffness Matrix:');
|
||
pretty(K);
|
||
#+end_src
|
||
|
||
In that case (top joints at the cube's vertices), a diagonal stiffness matrix is obtained eqref:eq:detail_kinematics_cubic_stiffness.
|
||
Translation stiffness is twice the stiffness of the struts, and rotational stiffness is proportional to the square of the cube's size Hc.
|
||
|
||
\begin{equation}\label{eq:detail_kinematics_cubic_stiffness}
|
||
\bm{K}_{\{B\} = \{C\}} = k \begin{bmatrix}
|
||
2 & 0 & 0 & 0 & 0 & 0 \\
|
||
0 & 2 & 0 & 0 & 0 & 0 \\
|
||
0 & 0 & 2 & 0 & 0 & 0 \\
|
||
0 & 0 & 0 & \frac{3}{2} H_c^2 & 0 & 0 \\
|
||
0 & 0 & 0 & 0 & \frac{3}{2} H_c^2 & 0 \\
|
||
0 & 0 & 0 & 0 & 0 & 6 H_c^2 \\
|
||
\end{bmatrix}
|
||
\end{equation}
|
||
|
||
But typically, the top joints are not placed at the cube's vertices but on the cube's edges (Figure ref:fig:detail_kinematics_cubic_schematic).
|
||
In that case, the location of the top joints can be expressed by eqref:eq:detail_kinematics_cubic_edges.
|
||
|
||
\begin{equation}\label{eq:detail_kinematics_cubic_edges}
|
||
\bm{b}_i = \tilde{\bm{b}}_i + \alpha \hat{\bm{s}}_i
|
||
\end{equation}
|
||
|
||
But the computed stiffness matrix is the same eqref:eq:detail_kinematics_cubic_stiffness.
|
||
|
||
The Stiffness matrix is diagonal for forces and torques applied on the top platform, but expressed at the center of the cube, and for translations and rotations of the top platform expressed with respect to the cube's center.
|
||
|
||
- [ ] Should I introduce the term "center of stiffness" here?
|
||
|
||
**** Effect of having frame $\{B\}$ off-centered
|
||
|
||
However, as soon as the location of the A and B frames are shifted from the cube's center, off diagonal elements in the stiffness matrix appear.
|
||
|
||
Let's consider here a vertical shift as shown in Figure ref:fig:detail_kinematics_cubic_schematic_off_centered.
|
||
In that case, the stiffness matrix is eqref:eq:detail_kinematics_cubic_stiffness_off_centered.
|
||
Off diagonal elements are increasing with the height difference between the cube's center and the considered B frame.
|
||
|
||
\begin{equation}\label{eq:detail_kinematics_cubic_stiffness_off_centered}
|
||
\bm{K}_{\{B\} \neq \{C\}} = k \begin{bmatrix}
|
||
2 & 0 & 0 & 0 & -2 H & 0 \\
|
||
0 & 2 & 0 & 2 H & 0 & 0 \\
|
||
0 & 0 & 2 & 0 & 0 & 0 \\
|
||
0 & 2 H & 0 & \frac{3}{2} H_c^2 + 2 H^2 & 0 & 0 \\
|
||
-2 H & 0 & 0 & 0 & \frac{3}{2} H_c^2 + 2 H^2 & 0 \\
|
||
0 & 0 & 0 & 0 & 0 & 6 H_c^2 \\
|
||
\end{bmatrix}
|
||
\end{equation}
|
||
|
||
|
||
Such structure of the stiffness matrix is very typical with Stewart platform that have some symmetry, but not necessary only for cubic architectures.
|
||
|
||
Therefore, the stiffness of the cubic architecture is special only when considering a frame located at the center of the cube.
|
||
This is not very convenient, as in the vast majority of cases, the interesting frame is located about the top platform.
|
||
|
||
Note that the cube's center needs not to be at the "center" of the Stewart platform.
|
||
This can lead to interesting architectures shown in Section ref:ssec:detail_kinematics_cubic_design.
|
||
|
||
**** Uniform Mobility
|
||
|
||
Uniform mobility in X,Y,Z directions (Figure ref:fig:detail_kinematics_cubic_mobility_translations)
|
||
- This is somehow more uniform than other architecture
|
||
- A cube is obtained
|
||
- The length of the cube's edge is equal to the strut axial stroke
|
||
- Mobility in translation does not depend on the cube's size
|
||
|
||
Some have argue that the translational mobility of the Cubic Stewart platform is a sphere [[cite:&mcinroy00_desig_contr_flexur_joint_hexap]], and this is useful to be able to move equal amount in all directions.
|
||
As shown here, this is wrong.
|
||
It is possible the consider that the mobility is uniform along the directions of the struts, but usually these are not interesting directions.
|
||
|
||
|
||
Also show mobility in Rx,Ry,Rz (Figure ref:fig:detail_kinematics_cubic_mobility_rotations):
|
||
- more mobility in Rx and Ry than in Rz
|
||
- Mobility decreases with the size of the cube
|
||
|
||
#+begin_src matlab
|
||
%% Cubic configuration
|
||
H = 100e-3; % Height of the Stewart platform [m]
|
||
Hc = 100e-3; % Size of the useful part of the cube [m]
|
||
FOc = 50e-3; % Center of the cube at the Stewart platform center
|
||
MO_B = -50e-3; % Position {B} with respect to {M} [m]
|
||
MHb = 0;
|
||
|
||
stewart_cubic = initializeStewartPlatform();
|
||
stewart_cubic = initializeFramesPositions(stewart_cubic, 'H', H, 'MO_B', MO_B);
|
||
stewart_cubic = generateCubicConfiguration(stewart_cubic, 'Hc', Hc, 'FOc', FOc, 'FHa', 5e-3, 'MHb', MHb);
|
||
stewart_cubic = computeJointsPose(stewart_cubic);
|
||
stewart_cubic = initializeStrutDynamics(stewart_cubic, 'k', 1);
|
||
stewart_cubic = computeJacobian(stewart_cubic);
|
||
stewart_cubic = initializeCylindricalPlatforms(stewart_cubic, 'Fpr', 150e-3, 'Mpr', 150e-3);
|
||
|
||
% Let's now define the actuator stroke.
|
||
L_max = 50e-6; % [m]
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Mobility of a Stewart platform with Cubic architecture - Translations
|
||
thetas = linspace(0, pi, 100);
|
||
phis = linspace(0, 2*pi, 200);
|
||
rs = zeros(length(thetas), length(phis));
|
||
|
||
for i = 1:length(thetas)
|
||
for j = 1:length(phis)
|
||
Tx = sin(thetas(i))*cos(phis(j));
|
||
Ty = sin(thetas(i))*sin(phis(j));
|
||
Tz = cos(thetas(i));
|
||
|
||
dL = stewart_cubic.kinematics.J*[Tx; Ty; Tz; 0; 0; 0;]; % dL required for 1m displacement in theta/phi direction
|
||
|
||
rs(i, j) = L_max/max(abs(dL));
|
||
% rs(i, j) = max(abs([dL(dL<0)*L_min; dL(dL>=0)*L_max]));
|
||
end
|
||
end
|
||
|
||
[phi_grid, theta_grid] = meshgrid(phis, thetas);
|
||
X = 1e6 * rs .* sin(theta_grid) .* cos(phi_grid);
|
||
Y = 1e6 * rs .* sin(theta_grid) .* sin(phi_grid);
|
||
Z = 1e6 * rs .* cos(theta_grid);
|
||
|
||
figure;
|
||
hold on;
|
||
surf(X, Y, Z, 'FaceColor', 'white', 'EdgeColor', colors(1,:));
|
||
quiver3(0, 0, 0, 150, 0, 0, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.7);
|
||
quiver3(0, 0, 0, 0, 150, 0, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.7);
|
||
quiver3(0, 0, 0, 0, 0, 150, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.7);
|
||
text(150, 0, 0, '$D_x$', 'FontSize', 10, 'HorizontalAlignment', 'center', 'VerticalAlignment', 'top' );
|
||
text(0, 150, 0, '$D_y$', 'FontSize', 10, 'HorizontalAlignment', 'right', 'VerticalAlignment', 'bottom');
|
||
text(0, 0, 150, '$D_z$', 'FontSize', 10, 'HorizontalAlignment', 'left', 'VerticalAlignment', 'top' );
|
||
hold off;
|
||
axis equal;
|
||
grid off;
|
||
axis off;
|
||
view(105, 15);
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_cubic_mobility_translations.pdf', 'width', 'normal', 'height', 'full', 'simplify', true);
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Mobility of a Stewart platform with Cubic architecture - Rotations
|
||
thetas = linspace(0, pi, 100);
|
||
phis = linspace(0, 2*pi, 200);
|
||
rs_cubic = zeros(length(thetas), length(phis));
|
||
|
||
for i = 1:length(thetas)
|
||
for j = 1:length(phis)
|
||
Rx = sin(thetas(i))*cos(phis(j));
|
||
Ry = sin(thetas(i))*sin(phis(j));
|
||
Rz = cos(thetas(i));
|
||
|
||
dL = stewart_cubic.kinematics.J*[0; 0; 0; Rx; Ry; Rz;];
|
||
rs_cubic(i, j) = L_max/max(abs(dL));
|
||
end
|
||
end
|
||
|
||
[phi_grid, theta_grid] = meshgrid(phis, thetas);
|
||
|
||
X_cubic = 1e6 * rs_cubic .* sin(theta_grid) .* cos(phi_grid);
|
||
Y_cubic = 1e6 * rs_cubic .* sin(theta_grid) .* sin(phi_grid);
|
||
Z_cubic = 1e6 * rs_cubic .* cos(theta_grid);
|
||
|
||
figure;
|
||
hold on;
|
||
surf(X_cubic, Y_cubic, Z_cubic, 'FaceColor', 'white', 'LineWidth', 0.2, 'EdgeColor', colors(1,:));
|
||
quiver3(0, 0, 0, 1500, 0, 0, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.7);
|
||
quiver3(0, 0, 0, 0, 1500, 0, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.7);
|
||
quiver3(0, 0, 0, 0, 0, 1500, 'k', 'LineWidth', 2, 'MaxHeadSize', 0.7);
|
||
text(1500, 0, 0, '$R_x$', 'FontSize', 10, 'HorizontalAlignment', 'center', 'VerticalAlignment', 'top' );
|
||
text(0, 1500, 0, '$R_y$', 'FontSize', 10, 'HorizontalAlignment', 'right', 'VerticalAlignment', 'bottom');
|
||
text(0, 0, 1500, '$R_z$', 'FontSize', 10, 'HorizontalAlignment', 'left', 'VerticalAlignment', 'top' );
|
||
hold off;
|
||
axis equal;
|
||
grid off;
|
||
axis off;
|
||
view(105, 15);
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_cubic_mobility_rotations.pdf', 'width', 'normal', 'height', 'full', 'simplify', true);
|
||
#+end_src
|
||
|
||
#+name: fig:detail_kinematics_cubic_mobility
|
||
#+caption: Mobility of a Stewart platform with Cubic architecture. Both for translations (\subref{fig:detail_kinematics_cubic_mobility_translations}) and rotations (\subref{fig:detail_kinematics_cubic_mobility_rotations})
|
||
#+attr_latex: :options [htbp]
|
||
#+begin_figure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_cubic_mobility_translations}Mobility in translation}
|
||
#+attr_latex: :options {0.48\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :scale 1
|
||
[[file:figs/detail_kinematics_cubic_mobility_translations.png]]
|
||
#+end_subfigure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_cubic_mobility_rotations}Mobility in rotation}
|
||
#+attr_latex: :options {0.48\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :scale 1
|
||
[[file:figs/detail_kinematics_cubic_mobility_rotations.png]]
|
||
#+end_subfigure
|
||
#+end_figure
|
||
|
||
** Dynamical Decoupling
|
||
<<ssec:detail_kinematics_cubic_dynamic>>
|
||
**** Introduction :ignore:
|
||
|
||
- [ ] [[cite:&mcinroy00_desig_contr_flexur_joint_hexap]]
|
||
Why is this here?
|
||
|
||
In this section, the dynamics of the platform in the cartesian frame is studied.
|
||
This corresponds to the transfer function from forces and torques $\bm{\mathcal{F}}$ to translations and rotations $\bm{\mathcal{X}}$ of the top platform.
|
||
If relative motion sensor are located in each strut ($\bm{\mathcal{L}}$ is measured), the pose $\bm{\mathcal{X}}$ is computed using the Jacobian matrix as shown in Figure ref:fig:detail_kinematics_centralized_control.
|
||
|
||
#+begin_src latex :file detail_kinematics_centralized_control.pdf
|
||
\begin{tikzpicture}
|
||
\node[block] (Jt) at (0, 0) {$\bm{J}^{-T}$};
|
||
\node[block, right= of Jt] (G) {$\bm{G}$};
|
||
\node[block, right= of G] (J) {$\bm{J}^{-1}$};
|
||
\node[block, left= of Jt] (Kx) {$\bm{K}_{\mathcal{X}}$};
|
||
|
||
\draw[->] (Kx.east) -- node[midway, above]{$\bm{\mathcal{F}}$} (Jt.west);
|
||
\draw[->] (Jt.east) -- (G.west) node[above left]{$\bm{\tau}$};
|
||
\draw[->] (G.east) -- (J.west) node[above left]{$\bm{\mathcal{L}}$};
|
||
\draw[->] (J.east) -- ++(1.0, 0);
|
||
\draw[->] ($(J.east) + (0.5, 0)$)node[]{$\bullet$} node[above]{$\bm{\mathcal{X}}$} -- ++(0, -1) -| ($(Kx.west) + (-0.5, 0)$) -- (Kx.west);
|
||
|
||
\begin{scope}[on background layer]
|
||
\node[fit={(Jt.south west) (J.north east)}, fill=black!20!white, draw, dashed, inner sep=4pt] (Px) {};
|
||
\node[anchor={south}] at (Px.north){\small{Cartesian Plant}};
|
||
\end{scope}
|
||
\end{tikzpicture}
|
||
#+end_src
|
||
|
||
#+name: fig:detail_kinematics_centralized_control
|
||
#+caption: From Strut coordinate to Cartesian coordinate using the Jacobian matrix
|
||
#+RESULTS:
|
||
[[file:figs/detail_kinematics_centralized_control.png]]
|
||
|
||
We want to see if the Stewart platform has some special properties for control in the cartesian frame.
|
||
|
||
**** Low frequency and High frequency coupling
|
||
|
||
As was derived during the conceptual design phase, the dynamics from $\bm{\mathcal{F}}$ to $\bm{\mathcal{X}}$ is described by eqref:eq:detail_kinematics_transfer_function_cart
|
||
|
||
\begin{equation}\label{eq:detail_kinematics_transfer_function_cart}
|
||
\frac{{\mathcal{X}}}{\bm{\mathcal{F}}}(s) = ( \bm{M} s^2 + \bm{J}^{T} \bm{\mathcal{C}} \bm{J} s + \bm{J}^{T} \bm{\mathcal{K}} \bm{J} )^{-1}
|
||
\end{equation}
|
||
|
||
|
||
At low frequency: the static behavior of the platform depends on the stiffness matrix eqref:eq:detail_kinematics_transfer_function_cart_low_freq.
|
||
|
||
\begin{equation}\label{eq:detail_kinematics_transfer_function_cart_low_freq}
|
||
\frac{{\mathcal{X}}}{\bm{\mathcal{F}}}(j \omega) \xrightarrow[\omega \to 0]{} \bm{K}^{-1}
|
||
\end{equation}
|
||
|
||
In section ref:ssec:detail_kinematics_cubic_static, it was shown that for the cubic configuration, the stiffness matrix is diagonal if frame $\{B\}$ is taken at the cube's center.
|
||
In that case, the "cartesian" plant is decoupled at low frequency.
|
||
|
||
At high frequency, the behavior depends on the mass matrix (evaluated at frame B) eqref:eq:detail_kinematics_transfer_function_high_freq.
|
||
|
||
\begin{equation}\label{eq:detail_kinematics_transfer_function_high_freq}
|
||
\frac{{\mathcal{X}}}{\bm{\mathcal{F}}}(j \omega) \xrightarrow[\omega \to \infty]{} - \omega^2 \bm{M}^{-1}
|
||
\end{equation}
|
||
|
||
To have the mass matrix diagonal, the center of mass of the mobile parts needs to coincide with the B frame and the principal axes of inertia of the body also needs to coincide with the axis of the B frame.
|
||
|
||
To verify that,
|
||
- CoM above the top platform (Figure ref:fig:detail_kinematics_cubic_payload)
|
||
- The transfer functions from F to X are computed for two specific locations of the B frames:
|
||
- center of mass: coupled at low frequency due to non diagonal stiffness matrix (Figure ref:fig:detail_kinematics_cubic_cart_coupling_com)
|
||
- center of stiffness: coupled at high frequency due to non diagonal mass matrix (Figure ref:fig:detail_kinematics_cubic_cart_coupling_cok)
|
||
- In both cases, we would get similar dynamics for a non-cubic stewart platform.
|
||
|
||
#+name: fig:detail_kinematics_cubic_payload
|
||
#+caption: Cubic stewart platform with top cylindrical payload
|
||
#+attr_latex: :width 0.6\linewidth
|
||
[[file:figs/detail_kinematics_cubic_payload.png]]
|
||
|
||
#+begin_src matlab
|
||
%% Input/Output definition of the Simscape model
|
||
clear io; io_i = 1;
|
||
io(io_i) = linio([mdl, '/Controller'], 1, 'openinput'); io_i = io_i + 1; % Actuator Force Inputs [N]
|
||
io(io_i) = linio([mdl, '/plant'], 1, 'openoutput'); io_i = io_i + 1; % External metrology [m,rad]
|
||
|
||
% Prepare simulation
|
||
controller = initializeController('type', 'open-loop');
|
||
sample = initializeSample('type', 'cylindrical', 'm', 10, 'H', 100e-3, 'R', 100e-3);
|
||
|
||
%% Cubic Stewart platform with payload above the top platform - B frame at the CoM
|
||
H = 200e-3; % height of the Stewart platform [m]
|
||
MO_B = 50e-3; % Position {B} with respect to {M} [m]
|
||
|
||
stewart = initializeStewartPlatform();
|
||
stewart = initializeFramesPositions(stewart, 'H', H, 'MO_B', MO_B);
|
||
stewart = generateCubicConfiguration(stewart, 'Hc', H, 'FOc', H/2, 'FHa', 25e-3, 'MHb', 25e-3);
|
||
stewart = computeJointsPose(stewart);
|
||
stewart = initializeStrutDynamics(stewart, 'k', 1e6, 'c', 1e1);
|
||
stewart = initializeJointDynamics(stewart, 'type_F', '2dof', 'type_M', '3dof');
|
||
stewart = computeJacobian(stewart);
|
||
stewart = initializeStewartPose(stewart);
|
||
stewart = initializeCylindricalPlatforms(stewart, ...
|
||
'Mpm', 1e-6, ... % Massless platform
|
||
'Fpm', 1e-6, ... % Massless platform
|
||
'Mph', 20e-3, ... % Thin platform
|
||
'Fph', 20e-3, ... % Thin platform
|
||
'Mpr', 1.2*max(vecnorm(stewart.platform_M.Mb)), ...
|
||
'Fpr', 1.2*max(vecnorm(stewart.platform_F.Fa)));
|
||
stewart = initializeCylindricalStruts(stewart, ...
|
||
'Fsm', 1e-6, ... % Massless strut
|
||
'Msm', 1e-6, ... % Massless strut
|
||
'Fsh', stewart.geometry.l(1)/2, ...
|
||
'Msh', stewart.geometry.l(1)/2 ...
|
||
);
|
||
|
||
% Run the linearization
|
||
G_CoM = linearize(mdl, io)*inv(stewart.kinematics.J).';
|
||
G_CoM.InputName = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'};
|
||
G_CoM.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
|
||
|
||
%% Same geometry but B Frame at cube's center (CoK)
|
||
MO_B = -100e-3; % Position {B} with respect to {M} [m]
|
||
stewart = initializeStewartPlatform();
|
||
stewart = initializeFramesPositions(stewart, 'H', H, 'MO_B', MO_B);
|
||
stewart = generateCubicConfiguration(stewart, 'Hc', H, 'FOc', H/2, 'FHa', 25e-3, 'MHb', 25e-3);
|
||
stewart = computeJointsPose(stewart);
|
||
stewart = initializeStrutDynamics(stewart, 'k', 1e6, 'c', 1e1);
|
||
stewart = initializeJointDynamics(stewart, 'type_F', '2dof', 'type_M', '3dof');
|
||
stewart = computeJacobian(stewart);
|
||
stewart = initializeStewartPose(stewart);
|
||
stewart = initializeCylindricalPlatforms(stewart, ...
|
||
'Mpm', 1e-6, ... % Massless platform
|
||
'Fpm', 1e-6, ... % Massless platform
|
||
'Mph', 20e-3, ... % Thin platform
|
||
'Fph', 20e-3, ... % Thin platform
|
||
'Mpr', 1.2*max(vecnorm(stewart.platform_M.Mb)), ...
|
||
'Fpr', 1.2*max(vecnorm(stewart.platform_F.Fa)));
|
||
stewart = initializeCylindricalStruts(stewart, ...
|
||
'Fsm', 1e-6, ... % Massless strut
|
||
'Msm', 1e-6, ... % Massless strut
|
||
'Fsh', stewart.geometry.l(1)/2, ...
|
||
'Msh', stewart.geometry.l(1)/2 ...
|
||
);
|
||
|
||
% Run the linearization
|
||
G_CoK = linearize(mdl, io)*inv(stewart.kinematics.J.');
|
||
G_CoK.InputName = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'};
|
||
G_CoK.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Coupling in the cartesian frame for a Cubic Stewart platform - Frame {B} is at the center of mass of the payload
|
||
freqs = logspace(0, 4, 1000);
|
||
figure;
|
||
tiledlayout(1, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
||
ax1 = nexttile();
|
||
hold on;
|
||
% for i = 1:5
|
||
% for j = i+1:6
|
||
% plot(freqs, abs(squeeze(freqresp(G_CoM(i, j), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2], ...
|
||
% 'HandleVisibility', 'off');
|
||
% end
|
||
% end
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM(1, 1), freqs, 'Hz'))), 'color', colors(1,:), ...
|
||
'DisplayName', '$D_x/F_x$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM(2, 2), freqs, 'Hz'))), 'color', colors(2,:), ...
|
||
'DisplayName', '$D_y/F_y$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM(3, 3), freqs, 'Hz'))), 'color', colors(3,:), ...
|
||
'DisplayName', '$D_z/F_z$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM(4, 4), freqs, 'Hz'))), 'color', colors(4,:), ...
|
||
'DisplayName', '$R_x/M_x$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM(5, 5), freqs, 'Hz'))), 'color', colors(5,:), ...
|
||
'DisplayName', '$R_y/M_y$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM(6, 6), freqs, 'Hz'))), 'color', colors(6,:), ...
|
||
'DisplayName', '$R_z/M_z$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM(4, 2), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2], ...
|
||
'DisplayName', '$R_x/F_y$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM(5, 1), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2], ...
|
||
'DisplayName', '$R_y/F_x$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM(1, 5), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2], ...
|
||
'DisplayName', '$D_x/M_y$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM(2, 4), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2], ...
|
||
'DisplayName', '$D_y/M_x$');
|
||
hold off;
|
||
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
||
xlabel('Frequency [Hz]'); ylabel('Amplitude');
|
||
leg = legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 2);
|
||
leg.ItemTokenSize(1) = 15;
|
||
xlim([1, 1e4]);
|
||
ylim([1e-10, 2e-3])
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_cubic_cart_coupling_com.pdf', 'width', 'half', 'height', 600);
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Coupling in the cartesian frame for a Cubic Stewart platform - Frame {B} is at the center of the cube
|
||
freqs = logspace(0, 4, 1000);
|
||
figure;
|
||
tiledlayout(1, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
||
ax1 = nexttile();
|
||
hold on;
|
||
% for i = 1:5
|
||
% for j = i+1:6
|
||
% plot(freqs, abs(squeeze(freqresp(G_CoK(i, j), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2], ...
|
||
% 'HandleVisibility', 'off');
|
||
% end
|
||
% end
|
||
plot(freqs, abs(squeeze(freqresp(G_CoK(1, 1), freqs, 'Hz'))), 'color', colors(1,:), ...
|
||
'DisplayName', '$D_x/F_x$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoK(2, 2), freqs, 'Hz'))), 'color', colors(2,:), ...
|
||
'DisplayName', '$D_y/F_y$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoK(3, 3), freqs, 'Hz'))), 'color', colors(3,:), ...
|
||
'DisplayName', '$D_z/F_z$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoK(4, 4), freqs, 'Hz'))), 'color', colors(4,:), ...
|
||
'DisplayName', '$R_x/M_x$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoK(5, 5), freqs, 'Hz'))), 'color', colors(5,:), ...
|
||
'DisplayName', '$R_y/M_y$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoK(6, 6), freqs, 'Hz'))), 'color', colors(6,:), ...
|
||
'DisplayName', '$R_z/M_z$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoK(4, 2), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2], ...
|
||
'DisplayName', '$R_x/F_y$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoK(5, 1), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2], ...
|
||
'DisplayName', '$R_y/F_x$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoK(1, 5), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2], ...
|
||
'DisplayName', '$D_x/M_y$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoK(2, 4), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2], ...
|
||
'DisplayName', '$D_y/M_x$');
|
||
hold off;
|
||
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
||
xlabel('Frequency [Hz]'); ylabel('Amplitude');
|
||
leg = legend('location', 'southeast', 'FontSize', 8, 'NumColumns', 2);
|
||
leg.ItemTokenSize(1) = 15;
|
||
xlim([1, 1e4]);
|
||
ylim([1e-10, 2e-3])
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_cubic_cart_coupling_cok.pdf', 'width', 'half', 'height', 600);
|
||
#+end_src
|
||
|
||
#+name: fig:detail_kinematics_cubic_cart_coupling
|
||
#+caption: Transfer functions for a Cubic Stewart platform expressed in the Cartesian frame. Two locations of the $\{B\}$ frame are considered: at the cube's center (\subref{fig:detail_kinematics_cubic_cart_coupling_cok}) and at the center of mass of the moving body (\subref{fig:detail_kinematics_cubic_cart_coupling_com}).
|
||
#+attr_latex: :options [htbp]
|
||
#+begin_figure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_cubic_cart_coupling_com}$\{B\}$ at the center of mass}
|
||
#+attr_latex: :options {0.48\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.95\linewidth
|
||
[[file:figs/detail_kinematics_cubic_cart_coupling_com.png]]
|
||
#+end_subfigure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_cubic_cart_coupling_cok}$\{B\}$ at the cube's center}
|
||
#+attr_latex: :options {0.48\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.95\linewidth
|
||
[[file:figs/detail_kinematics_cubic_cart_coupling_cok.png]]
|
||
#+end_subfigure
|
||
#+end_figure
|
||
|
||
**** Payload's CoM at the cube's center
|
||
|
||
It is therefore natural to try to have the cube's center and the center of mass of the moving part coincide at the same location.
|
||
|
||
- CoM at the center of the cube: Figure ref:fig:detail_kinematics_cubic_centered_payload
|
||
|
||
This is what is physically done in [[cite:&mcinroy99_dynam;&mcinroy99_precis_fault_toler_point_using_stewar_platf;&mcinroy00_desig_contr_flexur_joint_hexap;&li01_simul_vibrat_isolat_point_contr;&jafari03_orthog_gough_stewar_platf_microm]]
|
||
Shown in Figure ref:fig:detail_kinematics_uw_gsp
|
||
|
||
The obtained dynamics is indeed well decoupled, thanks to the diagonal stiffness matrix and mass matrix as the same time.
|
||
|
||
The main issue with this is that usually we want the payload to be located above the top platform, as it is the case for the nano-hexapod.
|
||
Indeed, if a similar design than the one shown in Figure ref:fig:detail_kinematics_cubic_centered_payload was used, the x-ray beam will hit the different struts during the rotation of the spindle.
|
||
|
||
#+begin_src matlab
|
||
%% Cubic Stewart platform with payload above the top platform
|
||
H = 200e-3;
|
||
MO_B = -100e-3; % Position {B} with respect to {M} [m]
|
||
|
||
stewart = initializeStewartPlatform();
|
||
stewart = initializeFramesPositions(stewart, 'H', H, 'MO_B', MO_B);
|
||
stewart = generateCubicConfiguration(stewart, 'Hc', H, 'FOc', H/2, 'FHa', 25e-3, 'MHb', 25e-3);
|
||
stewart = computeJointsPose(stewart);
|
||
stewart = initializeStrutDynamics(stewart, 'k', 1e6, 'c', 1e1);
|
||
stewart = initializeJointDynamics(stewart, 'type_F', '2dof', 'type_M', '3dof');
|
||
stewart = computeJacobian(stewart);
|
||
stewart = initializeStewartPose(stewart);
|
||
stewart = initializeCylindricalPlatforms(stewart, ...
|
||
'Mpm', 1e-6, ... % Massless platform
|
||
'Fpm', 1e-6, ... % Massless platform
|
||
'Mph', 20e-3, ... % Thin platform
|
||
'Fph', 20e-3, ... % Thin platform
|
||
'Mpr', 1.2*max(vecnorm(stewart.platform_M.Mb)), ...
|
||
'Fpr', 1.2*max(vecnorm(stewart.platform_F.Fa)));
|
||
stewart = initializeCylindricalStruts(stewart, ...
|
||
'Fsm', 1e-6, ... % Massless strut
|
||
'Msm', 1e-6, ... % Massless strut
|
||
'Fsh', stewart.geometry.l(1)/2, ...
|
||
'Msh', stewart.geometry.l(1)/2 ...
|
||
);
|
||
|
||
% Sample at the Center of the cube
|
||
sample = initializeSample('type', 'cylindrical', 'm', 10, 'H', 100e-3, 'H_offset', -H/2-50e-3);
|
||
|
||
% Run the linearization
|
||
G_CoM_CoK = linearize(mdl, io)*inv(stewart.kinematics.J.');
|
||
G_CoM_CoK.InputName = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'};
|
||
G_CoM_CoK.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none
|
||
freqs = logspace(0, 4, 1000);
|
||
figure;
|
||
tiledlayout(1, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
||
ax1 = nexttile();
|
||
hold on;
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK(1, 1), freqs, 'Hz'))), 'color', colors(1,:), ...
|
||
'DisplayName', '$D_x/F_x$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK(2, 2), freqs, 'Hz'))), 'color', colors(2,:), ...
|
||
'DisplayName', '$D_y/F_y$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK(3, 3), freqs, 'Hz'))), 'color', colors(3,:), ...
|
||
'DisplayName', '$D_z/F_z$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK(4, 4), freqs, 'Hz'))), 'color', colors(4,:), ...
|
||
'DisplayName', '$R_x/M_x$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK(5, 5), freqs, 'Hz'))), 'color', colors(5,:), ...
|
||
'DisplayName', '$R_y/M_y$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK(6, 6), freqs, 'Hz'))), 'color', colors(6,:), ...
|
||
'DisplayName', '$R_z/M_z$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK(4, 2), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2], ...
|
||
'DisplayName', '$R_x/F_y$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK(5, 1), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2], ...
|
||
'DisplayName', '$R_y/F_x$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK(1, 5), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2], ...
|
||
'DisplayName', '$D_x/M_y$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK(2, 4), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2], ...
|
||
'DisplayName', '$D_y/M_x$');
|
||
hold off;
|
||
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
||
xlabel('Frequency [Hz]'); ylabel('Amplitude [m/V]');
|
||
leg = legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 2);
|
||
leg.ItemTokenSize(1) = 15;
|
||
xlim([1, 1e4]);
|
||
ylim([1e-10, 2e-3])
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_cubic_cart_coupling_com_cok.pdf', 'width', 'half', 'height', 600);
|
||
#+end_src
|
||
|
||
#+name: fig:detail_kinematics_cubic_com_cok
|
||
#+caption: Cubic Stewart platform with payload at the cube's center (\subref{fig:detail_kinematics_cubic_centered_payload}). Obtained cartesian plant is fully decoupled (\subref{fig:detail_kinematics_cubic_cart_coupling_com_cok})
|
||
#+attr_latex: :options [htbp]
|
||
#+begin_figure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_cubic_centered_payload}Payload at the cube's center}
|
||
#+attr_latex: :options {0.49\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.95\linewidth
|
||
[[file:figs/detail_kinematics_cubic_centered_payload.png]]
|
||
#+end_subfigure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_cubic_cart_coupling_com_cok}Fully decoupled cartesian plant}
|
||
#+attr_latex: :options {0.49\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.95\linewidth
|
||
[[file:figs/detail_kinematics_cubic_cart_coupling_com_cok.png]]
|
||
#+end_subfigure
|
||
#+end_figure
|
||
|
||
**** TODO Uniform stiffness :noexport:
|
||
|
||
One may argue that the compliance matrix is more important that the stiffness matrix, as it describes how the platform with deforms to forces and torques.
|
||
As soon at the forces and torques are not longer applied to the center of the cube (which is typically not the case, except for specific case, as will be discussed), the Cubic architecture no longer provides same compliance in horizontal and vertical directions.
|
||
|
||
Conclusion:
|
||
- Cubic architecture:
|
||
Very specific in the sense that it can give both:
|
||
- Same XYZ stiffness
|
||
- Diagonal K matrix
|
||
But only when evaluated at the cube's center
|
||
|
||
First, we have to understand what is the physical meaning of the Stiffness matrix $\bm{K}$.
|
||
|
||
The Stiffness matrix links forces $\bm{f}$ and torques $\bm{n}$ applied on the mobile platform at $\{B\}$ to the displacement $\Delta\bm{\mathcal{X}}$ of the mobile platform represented by $\{B\}$ with respect to $\{A\}$:
|
||
\[ \bm{\mathcal{F}} = \bm{K} \Delta\bm{\mathcal{X}} \]
|
||
|
||
with:
|
||
- $\bm{\mathcal{F}} = [\bm{f}\ \bm{n}]^{T}$
|
||
- $\Delta\bm{\mathcal{X}} = [\delta x, \delta y, \delta z, \delta \theta_{x}, \delta \theta_{y}, \delta \theta_{z}]^{T}$
|
||
|
||
If the stiffness matrix is inversible, its inverse is the compliance matrix: $\bm{C} = \bm{K}^{-1$ and:
|
||
\[ \Delta \bm{\mathcal{X}} = C \bm{\mathcal{F}} \]
|
||
|
||
Thus, if the stiffness matrix is diagonal, the compliance matrix is also diagonal and a force (resp. torque) $\bm{\mathcal{F}}_i$ applied on the mobile platform at $\{B\}$ will induce a pure translation (resp. rotation) of the mobile platform represented by $\{B\}$ with respect to $\{A\}$.
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Cubic Architecture - Effect of the position of frame {A} and {B}
|
||
H = 100e-3; % Height of the Stewart platform [m]
|
||
Hc = 100e-3; % Size of the useful part of the cube [m]
|
||
FOc = H/2; % Center of the cube at the Stewart platform center
|
||
|
||
%% Frames {A} and {B} at the cube's center
|
||
MO_B = -50e-3; % Position {B} with respect to {M} [m]
|
||
|
||
stewart_center = initializeStewartPlatform();
|
||
stewart_center = initializeFramesPositions(stewart_center, 'H', H, 'MO_B', MO_B);
|
||
stewart_center = generateCubicConfiguration(stewart_center, 'Hc', Hc, 'FOc', FOc, 'FHa', 5e-3, 'MHb', 5e-3);
|
||
stewart_center = computeJointsPose(stewart_center);
|
||
stewart_center = initializeStrutDynamics(stewart_center, 'k', 1);
|
||
stewart_center = computeJacobian(stewart_center);
|
||
stewart_center = initializeCylindricalPlatforms(stewart_center, 'Fpr', 150e-3, 'Mpr', 150e-3);
|
||
|
||
displayArchitecture(stewart_center, 'labels', false, 'frames', true);
|
||
plotCube(stewart_center, 'Hc', Hc, 'FOc', FOc, 'color', [0,0,0,0.5], 'link_to_struts', true);
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Frames {A} and {B} offset from the cube's center
|
||
MO_B = 50e-3; % Position {B} with respect to {M} [m]
|
||
|
||
stewart_offset = initializeStewartPlatform();
|
||
stewart_offset = initializeFramesPositions(stewart_offset, 'H', H, 'MO_B', MO_B);
|
||
stewart_offset = generateCubicConfiguration(stewart_offset, 'Hc', Hc, 'FOc', FOc, 'FHa', 5e-3, 'MHb', 5e-3);
|
||
stewart_offset = computeJointsPose(stewart_offset);
|
||
stewart_offset = initializeStrutDynamics(stewart_offset, 'k', 2);
|
||
stewart_offset = computeJacobian(stewart_offset);
|
||
stewart_offset = initializeCylindricalPlatforms(stewart_offset, 'Fpr', 150e-3, 'Mpr', 150e-3);
|
||
|
||
displayArchitecture(stewart_offset, 'labels', false, 'frames', true);
|
||
plotCube(stewart_offset, 'Hc', Hc, 'FOc', FOc, 'color', [0,0,0,0.5], 'link_to_struts', true);
|
||
#+end_src
|
||
|
||
Here are the conclusion about the Stiffness matrix for the Cubic configuration:
|
||
- The cubic configuration permits to have $k_x = k_y = k_z$ and $k_{\theta_x} = k_{\theta_y}$
|
||
- The stiffness matrix $K$ is diagonal for the cubic configuration if the Jacobian is estimated at the cube center
|
||
|
||
**** TODO Dynamic isotropy :noexport:
|
||
|
||
[[cite:&afzali-far16_vibrat_dynam_isotr_hexap_analy_studies]]:
|
||
- proposes an architecture where the CoM can be above the top platform
|
||
- [ ] Try to find a stewart platform an a payload for witch all resonances are equal.
|
||
Massless struts and plates.
|
||
Cylindrical payload tuned to obtained such property.
|
||
Show that all modes can be optimally damped?
|
||
Compare with Stewart platform with different resonance frequencies. Also need to have parallel stiffness with the struts
|
||
- Same resonance frequencies for suspension modes?
|
||
Maybe in one case: sphere at the CoM?
|
||
Could be nice to show that.
|
||
Say that this can be nice for optimal damping for instance (link to paper explaining that)
|
||
|
||
|
||
- Show examples where the dynamics can indeed be decoupled in the cartesian frame (i.e. decoupled K and M matrices)
|
||
|
||
|
||
- [ ] Try to find a stewart platform an a payload for witch all resonances are equal.
|
||
It is not possible for a cubic architecture and a cylinder.
|
||
But maybe we can propose to not use a cubic architecture and still have dynamic isotropy?
|
||
For instance, let's consider a specific payload => give some rules to obtain dynamic isotropy:
|
||
|
||
|
||
Inertia of a cylinder:
|
||
Iz = 1/2mr^2
|
||
Ix = Iy = 1/12 m (3r^2 + h^2)
|
||
|
||
We want M = alpha K
|
||
|
||
2k = alpha m
|
||
|
||
alpha = 2k/m
|
||
|
||
Krx = 3/2 k H^2 = Ix = 1/12 m
|
||
|
||
#+begin_src matlab
|
||
%% Cubic Stewart platform with payload above the top platform
|
||
H = 200e-3;
|
||
MO_B = -100e-3; % Position {B} with respect to {M} [m]
|
||
|
||
stewart = initializeStewartPlatform();
|
||
stewart = initializeFramesPositions(stewart, 'H', H, 'MO_B', MO_B);
|
||
stewart = generateCubicConfiguration(stewart, 'Hc', H, 'FOc', H/2, 'FHa', 25e-3, 'MHb', 25e-3);
|
||
stewart = computeJointsPose(stewart);
|
||
stewart = initializeStrutDynamics(stewart, 'k', 1e6, 'c', 1e1);
|
||
stewart = initializeJointDynamics(stewart, 'type_F', '2dof', 'type_M', '3dof');
|
||
stewart = computeJacobian(stewart);
|
||
stewart = initializeStewartPose(stewart);
|
||
stewart = initializeCylindricalPlatforms(stewart, ...
|
||
'Mpm', 1e-6, ... % Massless platform
|
||
'Fpm', 1e-6, ... % Massless platform
|
||
'Mph', 20e-3, ... % Thin platform
|
||
'Fph', 20e-3, ... % Thin platform
|
||
'Mpr', 1.2*max(vecnorm(stewart.platform_M.Mb)), ...
|
||
'Fpr', 1.2*max(vecnorm(stewart.platform_F.Fa)));
|
||
stewart = initializeCylindricalStruts(stewart, ...
|
||
'Fsm', 1e-6, ... % Massless strut
|
||
'Msm', 1e-6, ... % Massless strut
|
||
'Fsh', stewart.geometry.l(1)/2, ...
|
||
'Msh', stewart.geometry.l(1)/2 ...
|
||
);
|
||
|
||
% Sample at the Center of the cube
|
||
sample = initializeSample('type', 'cylindrical', 'm', 10, 'H', 1/9*H, 'H_offset', -H/2-1/9*H/2, 'R', sqrt(6)*H);
|
||
|
||
% Run the linearization
|
||
G_CoM_CoK = linearize(mdl, io)*inv(stewart.kinematics.J.');
|
||
G_CoM_CoK.InputName = {'Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz'};
|
||
G_CoM_CoK.OutputName = {'Dx', 'Dy', 'Dz', 'Rx', 'Ry', 'Rz'};
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none
|
||
freqs = logspace(0, 4, 1000);
|
||
figure;
|
||
tiledlayout(1, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
||
ax1 = nexttile();
|
||
hold on;
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK(1, 1), freqs, 'Hz'))), 'color', colors(1,:), ...
|
||
'DisplayName', '$D_x/F_x$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK(2, 2), freqs, 'Hz'))), 'color', colors(2,:), ...
|
||
'DisplayName', '$D_y/F_y$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK(3, 3), freqs, 'Hz'))), 'color', colors(3,:), ...
|
||
'DisplayName', '$D_z/F_z$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK(4, 4), freqs, 'Hz'))), 'color', colors(4,:), ...
|
||
'DisplayName', '$R_x/M_x$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK(5, 5), freqs, 'Hz'))), 'color', colors(5,:), ...
|
||
'DisplayName', '$R_y/M_y$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK(6, 6), freqs, 'Hz'))), 'color', colors(6,:), ...
|
||
'DisplayName', '$R_z/M_z$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK(4, 2), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2], ...
|
||
'DisplayName', '$R_x/F_y$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK(5, 1), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2], ...
|
||
'DisplayName', '$R_y/F_x$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK(1, 5), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2], ...
|
||
'DisplayName', '$D_x/M_y$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK(2, 4), freqs, 'Hz'))), 'color', [0, 0, 0, 0.2], ...
|
||
'DisplayName', '$D_y/M_x$');
|
||
hold off;
|
||
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
||
xlabel('Frequency [Hz]'); ylabel('Amplitude [m/V]');
|
||
leg = legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 2);
|
||
leg.ItemTokenSize(1) = 15;
|
||
xlim([1, 1e4]);
|
||
ylim([1e-10, 2e-3])
|
||
#+end_src
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
**** Conclusion
|
||
|
||
- Some work to still be decoupled when considering flexible joint stiffness
|
||
- [ ] Find the reference
|
||
|
||
- Better decoupling between the struts? Next section
|
||
|
||
Some conclusions can be drawn from the above analysis:
|
||
- Static Decoupling <=> Diagonal Stiffness matrix <=> {A} and {B} at the cube's center
|
||
- Dynamic Decoupling <=> Static Decoupling + CoM of mobile platform coincident with {A} and {B}.
|
||
- Not specific to the cubic architecture
|
||
- Same stiffness in XYZ => Possible to have dynamic isotropy
|
||
|
||
** Decentralized Control
|
||
<<ssec:detail_kinematics_decentralized_control>>
|
||
**** Introduction :ignore:
|
||
|
||
From [[cite:preumont07_six_axis_singl_stage_activ]], the cubic configuration "/minimizes the cross-coupling amongst actuators and sensors of different legs (being orthogonal to each other)/".
|
||
This would facilitate the use of decentralized control.
|
||
|
||
#+begin_src latex :file detail_kinematics_decentralized_control.pdf
|
||
\begin{tikzpicture}
|
||
\node[block] (G) at (0,0) {$\bm{G}$};
|
||
|
||
\node[block, left= of G] (Kl) {$\bm{K}_{\mathcal{L}}$};
|
||
|
||
\draw[->] (Kl.east) -- node[midway, above]{$\bm{\tau}$} (G.west);
|
||
\draw[->] (G.east) -- ++(1.0, 0);
|
||
\draw[->] ($(G.east) + (0.5, 0)$)node[]{$\bullet$} node[above]{$\bm{\mathcal{L}}$} -- ++(0, -1) -| ($(Kl.west) + (-0.5, 0)$) -- (Kl.west);
|
||
|
||
\begin{scope}[on background layer]
|
||
\node[fit={(G.south west) (G.north east)}, fill=black!20!white, draw, dashed, inner sep=4pt] (Pl) {};
|
||
\node[anchor={south}] at (Pl.north){\small{Strut Plant}};
|
||
\end{scope}
|
||
\end{tikzpicture}
|
||
#+end_src
|
||
|
||
#+name: fig:detail_kinematics_decentralized_control
|
||
#+caption: From Strut coordinate to Cartesian coordinate using the Jacobian matrix
|
||
#+RESULTS:
|
||
[[file:figs/detail_kinematics_decentralized_control.png]]
|
||
|
||
In this section, we wish to study such properties of the cubic architecture.
|
||
|
||
Here, the plant output are sensors integrated in the Stewart platform struts.
|
||
Two sensors are considered: a displacement sensor and a force sensor.
|
||
|
||
We will compare the transfer function from sensors to actuators in each strut for a cubic architecture and for a non-cubic architecture (where the struts are not orthogonal with each other).
|
||
|
||
The "strut plant" are compared for two Stewart platforms:
|
||
- with cubic architecture shown in Figure ref:fig:detail_kinematics_cubic_payload (page pageref:fig:detail_kinematics_cubic_payload)
|
||
- with a Stewart platform shown in Figure ref:fig:detail_kinematics_non_cubic_payload. It has the same payload and strut dynamics than for the cubic architecture.
|
||
The struts are oriented more vertically to be far away from the cubic architecture
|
||
|
||
#+name: fig:detail_kinematics_non_cubic_payload
|
||
#+caption: Stewart platform with non-cubic architecture
|
||
#+attr_latex: :width 0.6\linewidth
|
||
[[file:figs/detail_kinematics_non_cubic_payload.png]]
|
||
|
||
#+begin_src matlab
|
||
%% Input/Output definition of the Simscape model
|
||
clear io; io_i = 1;
|
||
io(io_i) = linio([mdl, '/Controller'], 1, 'openinput'); io_i = io_i + 1; % Actuator Force Inputs [N]
|
||
io(io_i) = linio([mdl, '/plant'], 2, 'openoutput', [], 'dL'); io_i = io_i + 1; % Displacement sensors [m]
|
||
io(io_i) = linio([mdl, '/plant'], 2, 'openoutput', [], 'fn'); io_i = io_i + 1; % Force Sensor [N]
|
||
|
||
% Prepare simulation : Payload above the top platform
|
||
controller = initializeController('type', 'open-loop');
|
||
sample = initializeSample('type', 'cylindrical', 'm', 10, 'H', 100e-3, 'R', 100e-3);
|
||
|
||
%% Cubic Stewart platform
|
||
H = 200e-3; % height of the Stewart platform [m]
|
||
MO_B = 50e-3; % Position {B} with respect to {M} [m]
|
||
|
||
stewart = initializeStewartPlatform();
|
||
stewart = initializeFramesPositions(stewart, 'H', H, 'MO_B', MO_B);
|
||
stewart = generateCubicConfiguration(stewart, 'Hc', H, 'FOc', H/2, 'FHa', 25e-3, 'MHb', 25e-3);
|
||
stewart = computeJointsPose(stewart);
|
||
stewart = initializeStrutDynamics(stewart, 'k', 1e6, 'c', 1e1);
|
||
stewart = initializeJointDynamics(stewart, 'type_F', '2dof', 'type_M', '3dof');
|
||
stewart = computeJacobian(stewart);
|
||
stewart = initializeStewartPose(stewart);
|
||
stewart = initializeCylindricalPlatforms(stewart, ...
|
||
'Mpm', 1e-6, ... % Massless platform
|
||
'Fpm', 1e-6, ... % Massless platform
|
||
'Mph', 20e-3, ... % Thin platform
|
||
'Fph', 20e-3, ... % Thin platform
|
||
'Mpr', 1.2*max(vecnorm(stewart.platform_M.Mb)), ...
|
||
'Fpr', 1.2*max(vecnorm(stewart.platform_F.Fa)));
|
||
stewart = initializeCylindricalStruts(stewart, ...
|
||
'Fsm', 1e-6, ... % Massless strut
|
||
'Msm', 1e-6, ... % Massless strut
|
||
'Fsh', stewart.geometry.l(1)/2, ...
|
||
'Msh', stewart.geometry.l(1)/2 ...
|
||
);
|
||
|
||
% Run the linearization
|
||
G_cubic = linearize(mdl, io);
|
||
G_cubic.InputName = {'f1', 'f2', 'f3', 'f4', 'f5', 'f6'};
|
||
G_cubic.OutputName = {'dL1', 'dL2', 'dL3', 'dL4', 'dL5', 'dL6', ...
|
||
'fn1', 'fn2', 'fn3', 'fn4', 'fn5', 'fn6'};
|
||
|
||
%% Non-Cubic Stewart platform
|
||
stewart = initializeStewartPlatform();
|
||
stewart = initializeFramesPositions(stewart, 'H', H, 'MO_B', MO_B);
|
||
stewart = generateCubicConfiguration(stewart, 'Hc', H, 'FOc', H/2, 'FHa', 25e-3, 'MHb', 25e-3);
|
||
stewart = generateGeneralConfiguration(stewart, 'FH', 25e-3, 'FR', 250e-3, 'MH', 25e-3, 'MR', 250e-3, ...
|
||
'FTh', [-22, 22, 120-22, 120+22, 240-22, 240+22]*(pi/180), ...
|
||
'MTh', [-60+22, 60-22, 60+22, 180-22, 180+22, -60-22]*(pi/180));
|
||
stewart = computeJointsPose(stewart);
|
||
stewart = initializeStrutDynamics(stewart, 'k', 1e6, 'c', 1e1);
|
||
stewart = initializeJointDynamics(stewart, 'type_F', '2dof', 'type_M', '3dof');
|
||
stewart = computeJacobian(stewart);
|
||
stewart = initializeStewartPose(stewart);
|
||
stewart = initializeCylindricalPlatforms(stewart, ...
|
||
'Mpm', 1e-6, ... % Massless platform
|
||
'Fpm', 1e-6, ... % Massless platform
|
||
'Mph', 20e-3, ... % Thin platform
|
||
'Fph', 20e-3, ... % Thin platform
|
||
'Mpr', 1.2*max(vecnorm(stewart.platform_M.Mb)), ...
|
||
'Fpr', 1.2*max(vecnorm(stewart.platform_F.Fa)));
|
||
stewart = initializeCylindricalStruts(stewart, ...
|
||
'Fsm', 1e-6, ... % Massless strut
|
||
'Msm', 1e-6, ... % Massless strut
|
||
'Fsh', stewart.geometry.l(1)/2, ...
|
||
'Msh', stewart.geometry.l(1)/2 ...
|
||
);
|
||
|
||
% Run the linearization
|
||
G_non_cubic = linearize(mdl, io);
|
||
G_non_cubic.InputName = {'f1', 'f2', 'f3', 'f4', 'f5', 'f6'};
|
||
G_non_cubic.OutputName = {'dL1', 'dL2', 'dL3', 'dL4', 'dL5', 'dL6', ...
|
||
'fn1', 'fn2', 'fn3', 'fn4', 'fn5', 'fn6'};
|
||
#+end_src
|
||
|
||
**** Relative Displacement Sensors
|
||
|
||
The transfer functions from actuator force included in each strut to the relative motion of the struts are shown in Figure ref:fig:detail_kinematics_decentralized_dL.
|
||
As expected from the equations of motion from $\bm{f}$ to $\bm{\mathcal{L}}$ eqref:eq:nhexa_transfer_function_struts, the $6 \times 6$ plants are decoupled at low frequency.
|
||
|
||
At high frequency, the plant is coupled as the mass matrix projected in the frame of the struts is not diagonal.
|
||
|
||
No clear advantage can be seen for the cubic architecture (figure ref:fig:detail_kinematics_cubic_decentralized_dL) as compared to the non-cubic architecture (Figure ref:fig:detail_kinematics_non_cubic_decentralized_dL).
|
||
|
||
Note that the resonance frequencies are not the same in both cases as having the struts oriented more vertically changed the stiffness properties of the Stewart platform and hence the frequency of different modes.
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Decentralized plant - Actuator force to Strut displacement - Cubic Architecture
|
||
freqs = logspace(0, 4, 1000);
|
||
figure;
|
||
tiledlayout(1, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
||
ax1 = nexttile();
|
||
hold on;
|
||
for i = 1:5
|
||
for j = i+1:6
|
||
plot(freqs, abs(squeeze(freqresp(G_non_cubic(sprintf('dL%i',i), sprintf('f%i',j)), freqs, 'Hz'))), 'color', [colors(1,:), 0.1], ...
|
||
'HandleVisibility', 'off');
|
||
end
|
||
end
|
||
plot(freqs, abs(squeeze(freqresp(G_non_cubic('dL1', 'f1'), freqs, 'Hz'))), 'color', [colors(1,:)], 'linewidth', 2.5, ...
|
||
'DisplayName', '$l_i/f_i$');
|
||
plot(freqs, abs(squeeze(freqresp(G_non_cubic('dL2', 'f1'), freqs, 'Hz'))), 'color', [colors(1,:), 0.1], ...
|
||
'DisplayName', '$l_i/f_j$');
|
||
hold off;
|
||
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
||
xlabel('Frequency [Hz]'); ylabel('Amplitude [m/N]');
|
||
leg = legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1);
|
||
leg.ItemTokenSize(1) = 15;
|
||
xlim([1, 1e4]);
|
||
ylim([1e-10, 1e-4])
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_non_cubic_decentralized_dL.pdf', 'width', 'half', 'height', 'normal');
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Decentralized plant - Actuator force to Strut displacement - Cubic Architecture
|
||
freqs = logspace(0, 4, 1000);
|
||
figure;
|
||
tiledlayout(1, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
||
ax1 = nexttile();
|
||
hold on;
|
||
for i = 1:5
|
||
for j = i+1:6
|
||
plot(freqs, abs(squeeze(freqresp(G_cubic(sprintf('dL%i',i), sprintf('f%i',j)), freqs, 'Hz'))), 'color', [colors(2,:), 0.1], ...
|
||
'HandleVisibility', 'off');
|
||
end
|
||
end
|
||
plot(freqs, abs(squeeze(freqresp(G_cubic('dL1', 'f1'), freqs, 'Hz'))), 'color', [colors(2,:)], 'linewidth', 2.5, ...
|
||
'DisplayName', '$l_i/f_i$');
|
||
plot(freqs, abs(squeeze(freqresp(G_cubic('dL2', 'f1'), freqs, 'Hz'))), 'color', [colors(2,:), 0.1], ...
|
||
'DisplayName', '$l_i/f_j$');
|
||
hold off;
|
||
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
||
xlabel('Frequency [Hz]'); ylabel('Amplitude [m/N]');
|
||
leg = legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1);
|
||
leg.ItemTokenSize(1) = 15;
|
||
xlim([1, 1e4]);
|
||
ylim([1e-10, 1e-4])
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_cubic_decentralized_dL.pdf', 'width', 'half', 'height', 'normal');
|
||
#+end_src
|
||
|
||
#+name: fig:detail_kinematics_decentralized_dL
|
||
#+caption: Bode plot of the transfer functions from actuator force to relative displacement sensor in each strut. Both for a non-cubic architecture (\subref{fig:detail_kinematics_non_cubic_decentralized_dL}) and for a cubic architecture (\subref{fig:detail_kinematics_cubic_decentralized_dL})
|
||
#+attr_latex: :options [htbp]
|
||
#+begin_figure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_non_cubic_decentralized_dL}Non cubic architecture}
|
||
#+attr_latex: :options {0.48\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.95\linewidth
|
||
[[file:figs/detail_kinematics_non_cubic_decentralized_dL.png]]
|
||
#+end_subfigure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_cubic_decentralized_dL}Cubic architecture}
|
||
#+attr_latex: :options {0.48\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.95\linewidth
|
||
[[file:figs/detail_kinematics_cubic_decentralized_dL.png]]
|
||
#+end_subfigure
|
||
#+end_figure
|
||
|
||
**** Force Sensors
|
||
|
||
Similarly, the transfer functions from actuator force to force sensors included in each strut are extracted both for the cubic and non-cubic Stewart platforms.
|
||
|
||
The results are shown in Figure ref:fig:detail_kinematics_decentralized_fn.
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Decentralized plant - Actuator force to strut force sensor - Cubic Architecture
|
||
freqs = logspace(0, 4, 1000);
|
||
figure;
|
||
tiledlayout(1, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
||
ax1 = nexttile();
|
||
hold on;
|
||
for i = 1:5
|
||
for j = i+1:6
|
||
plot(freqs, abs(squeeze(freqresp(G_non_cubic(sprintf('fn%i',i), sprintf('f%i',j)), freqs, 'Hz'))), 'color', [colors(1,:), 0.1], ...
|
||
'HandleVisibility', 'off');
|
||
end
|
||
end
|
||
plot(freqs, abs(squeeze(freqresp(G_non_cubic('fn1', 'f1'), freqs, 'Hz'))), 'color', [colors(1,:)], 'linewidth', 2.5, ...
|
||
'DisplayName', '$f_{m,i}/f_i$');
|
||
plot(freqs, abs(squeeze(freqresp(G_non_cubic('fn2', 'f1'), freqs, 'Hz'))), 'color', [colors(1,:), 0.1], ...
|
||
'DisplayName', '$f_{m,i}/f_j$');
|
||
hold off;
|
||
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
||
xlabel('Frequency [Hz]'); ylabel('Amplitude [N/N]');
|
||
leg = legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1);
|
||
leg.ItemTokenSize(1) = 15;
|
||
xlim([1, 1e4]); ylim([1e-4, 1e2]);
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_non_cubic_decentralized_fn.pdf', 'width', 'half', 'height', 'normal');
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Decentralized plant - Actuator force to strut force sensor - Cubic Architecture
|
||
freqs = logspace(0, 4, 1000);
|
||
figure;
|
||
tiledlayout(1, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
||
ax1 = nexttile();
|
||
hold on;
|
||
for i = 1:5
|
||
for j = i+1:6
|
||
plot(freqs, abs(squeeze(freqresp(G_cubic(sprintf('fn%i',i), sprintf('f%i',j)), freqs, 'Hz'))), 'color', [colors(2,:), 0.1], ...
|
||
'HandleVisibility', 'off');
|
||
end
|
||
end
|
||
plot(freqs, abs(squeeze(freqresp(G_cubic('fn1', 'f1'), freqs, 'Hz'))), 'color', [colors(2,:)], 'linewidth', 2.5, ...
|
||
'DisplayName', '$f_{m,i}/f_i$');
|
||
plot(freqs, abs(squeeze(freqresp(G_cubic('fn2', 'f1'), freqs, 'Hz'))), 'color', [colors(2,:), 0.1], ...
|
||
'DisplayName', '$f_{m,i}/f_j$');
|
||
hold off;
|
||
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
||
xlabel('Frequency [Hz]'); ylabel('Amplitude [N/N]');
|
||
leg = legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1);
|
||
leg.ItemTokenSize(1) = 15;
|
||
xlim([1, 1e4]); ylim([1e-4, 1e2]);
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_cubic_decentralized_fn.pdf', 'width', 'half', 'height', 'normal');
|
||
#+end_src
|
||
|
||
#+name: fig:detail_kinematics_decentralized_fn
|
||
#+caption: Bode plot of the transfer functions from actuator force to force sensor in each strut. Both for a non-cubic architecture (\subref{fig:detail_kinematics_non_cubic_decentralized_fn}) and for a cubic architecture (\subref{fig:detail_kinematics_cubic_decentralized_fn})
|
||
#+attr_latex: :options [htbp]
|
||
#+begin_figure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_non_cubic_decentralized_fn}Non cubic architecture}
|
||
#+attr_latex: :options {0.48\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.95\linewidth
|
||
[[file:figs/detail_kinematics_non_cubic_decentralized_fn.png]]
|
||
#+end_subfigure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_cubic_decentralized_fn}Cubic architecture}
|
||
#+attr_latex: :options {0.48\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.95\linewidth
|
||
[[file:figs/detail_kinematics_cubic_decentralized_fn.png]]
|
||
#+end_subfigure
|
||
#+end_figure
|
||
|
||
**** Cubic with centered payload :noexport:
|
||
|
||
It seems having the payload at the center of the cube makes things worst for decentralized control.
|
||
|
||
#+begin_src matlab
|
||
%% Cubic Stewart platform with payload above the top platform
|
||
H = 200e-3;
|
||
MO_B = -100e-3; % Position {B} with respect to {M} [m]
|
||
|
||
stewart = initializeStewartPlatform();
|
||
stewart = initializeFramesPositions(stewart, 'H', H, 'MO_B', MO_B);
|
||
stewart = generateCubicConfiguration(stewart, 'Hc', H, 'FOc', H/2, 'FHa', 25e-3, 'MHb', 25e-3);
|
||
stewart = computeJointsPose(stewart);
|
||
stewart = initializeStrutDynamics(stewart, 'k', 1e6, 'c', 1e1);
|
||
stewart = initializeJointDynamics(stewart, 'type_F', '2dof', 'type_M', '3dof');
|
||
stewart = computeJacobian(stewart);
|
||
stewart = initializeStewartPose(stewart);
|
||
stewart = initializeCylindricalPlatforms(stewart, ...
|
||
'Mpm', 1e-6, ... % Massless platform
|
||
'Fpm', 1e-6, ... % Massless platform
|
||
'Mph', 20e-3, ... % Thin platform
|
||
'Fph', 20e-3, ... % Thin platform
|
||
'Mpr', 1.2*max(vecnorm(stewart.platform_M.Mb)), ...
|
||
'Fpr', 1.2*max(vecnorm(stewart.platform_F.Fa)));
|
||
stewart = initializeCylindricalStruts(stewart, ...
|
||
'Fsm', 1e-6, ... % Massless strut
|
||
'Msm', 1e-6, ... % Massless strut
|
||
'Fsh', stewart.geometry.l(1)/2, ...
|
||
'Msh', stewart.geometry.l(1)/2 ...
|
||
);
|
||
|
||
% Sample at the Center of the cube
|
||
sample = initializeSample('type', 'cylindrical', 'm', 10, 'H', 100e-3, 'H_offset', -H/2-50e-3);
|
||
|
||
% Run the linearization
|
||
G_CoM_CoK = linearize(mdl, io)*inv(stewart.kinematics.J.');
|
||
G_CoM_CoK.InputName = {'f1', 'f2', 'f3', 'f4', 'f5', 'f6'};
|
||
G_CoM_CoK.OutputName = {'dL1', 'dL2', 'dL3', 'dL4', 'dL5', 'dL6', ...
|
||
'fn1', 'fn2', 'fn3', 'fn4', 'fn5', 'fn6'};
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Coupling in the cartesian frame for a Non_cubic Stewart platform - Frame {B} is at the center of mass of the payload
|
||
freqs = logspace(0, 4, 1000);
|
||
figure;
|
||
tiledlayout(1, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
||
ax1 = nexttile();
|
||
hold on;
|
||
for i = 1:5
|
||
for j = i+1:6
|
||
plot(freqs, abs(squeeze(freqresp(G_non_cubic(sprintf('fn%i',i), sprintf('f%i',j)), freqs, 'Hz'))), 'color', [colors(2,:), 0.1], ...
|
||
'HandleVisibility', 'off');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK(sprintf('fn%i',i), sprintf('f%i',j)), freqs, 'Hz'))), 'color', [colors(3,:), 0.1], ...
|
||
'HandleVisibility', 'off');
|
||
end
|
||
end
|
||
plot(freqs, abs(squeeze(freqresp(G_non_cubic('fn1', 'f1'), freqs, 'Hz'))), 'color', [colors(2,:)], 'linewidth', 2.5, ...
|
||
'DisplayName', '$L_i/F_i$');
|
||
plot(freqs, abs(squeeze(freqresp(G_non_cubic('fn2', 'f1'), freqs, 'Hz'))), 'color', [colors(2,:), 0.1], ...
|
||
'DisplayName', '$L_i/F_j$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK('fn1', 'f1'), freqs, 'Hz'))), 'color', [colors(3,:)], 'linewidth', 2.5, ...
|
||
'DisplayName', '$L_i/F_i$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK('fn2', 'f1'), freqs, 'Hz'))), 'color', [colors(3,:), 0.1], ...
|
||
'DisplayName', '$L_i/F_j$');
|
||
hold off;
|
||
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
||
xlabel('Frequency [Hz]'); ylabel('Amplitude [N/N]');
|
||
leg = legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 2);
|
||
leg.ItemTokenSize(1) = 15;
|
||
xlim([1, 1e4]);
|
||
ylim([1e-3, 1e2])
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Coupling in the cartesian frame for a Non_cubic Stewart platform - Frame {B} is at the center of mass of the payload
|
||
freqs = logspace(0, 4, 1000);
|
||
figure;
|
||
tiledlayout(1, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
||
ax1 = nexttile();
|
||
hold on;
|
||
for i = 1:5
|
||
for j = i+1:6
|
||
plot(freqs, abs(squeeze(freqresp(G_non_cubic(sprintf('dL%i',i), sprintf('f%i',j)), freqs, 'Hz'))), 'color', [colors(1,:), 0.1], ...
|
||
'HandleVisibility', 'off');
|
||
plot(freqs, abs(squeeze(freqresp(G_cubic(sprintf('dL%i',i), sprintf('f%i',j)), freqs, 'Hz'))), 'color', [colors(2,:), 0.1], ...
|
||
'HandleVisibility', 'off');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK(sprintf('dL%i',i), sprintf('f%i',j)), freqs, 'Hz'))), 'color', [colors(3,:), 0.1], ...
|
||
'HandleVisibility', 'off');
|
||
end
|
||
end
|
||
plot(freqs, abs(squeeze(freqresp(G_non_cubic('dL1', 'f1'), freqs, 'Hz'))), 'color', [colors(1,:)], 'linewidth', 2.5, ...
|
||
'DisplayName', '$L_i/F_i$');
|
||
plot(freqs, abs(squeeze(freqresp(G_non_cubic('dL2', 'f1'), freqs, 'Hz'))), 'color', [colors(1,:), 0.1], ...
|
||
'DisplayName', '$L_i/F_j$');
|
||
plot(freqs, abs(squeeze(freqresp(G_cubic('dL1', 'f1'), freqs, 'Hz'))), 'color', [colors(2,:)], 'linewidth', 2.5, ...
|
||
'DisplayName', '$L_i/F_i$');
|
||
plot(freqs, abs(squeeze(freqresp(G_cubic('dL2', 'f1'), freqs, 'Hz'))), 'color', [colors(2,:), 0.1], ...
|
||
'DisplayName', '$L_i/F_j$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK('dL1', 'f1'), freqs, 'Hz'))), 'color', [colors(3,:)], 'linewidth', 2.5, ...
|
||
'DisplayName', '$L_i/F_i$');
|
||
plot(freqs, abs(squeeze(freqresp(G_CoM_CoK('dL2', 'f1'), freqs, 'Hz'))), 'color', [colors(3,:), 0.1], ...
|
||
'DisplayName', '$L_i/F_j$');
|
||
hold off;
|
||
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
||
xlabel('Frequency [Hz]'); ylabel('Amplitude [m/N]');
|
||
leg = legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 2);
|
||
leg.ItemTokenSize(1) = 15;
|
||
xlim([1, 1e4]);
|
||
ylim([1e-10, 2e-3])
|
||
#+end_src
|
||
|
||
|
||
**** Conclusion
|
||
|
||
The Cubic architecture seems to not have any significant effect on the coupling between actuator and sensors of each strut and thus provides no advantages for decentralized control.
|
||
|
||
** Cubic architecture with Cube's center above the top platform
|
||
<<ssec:detail_kinematics_cubic_design>>
|
||
**** Introduction :ignore:
|
||
|
||
As was shown in Section ref:ssec:detail_kinematics_cubic_dynamic, the cubic architecture can have very interesting dynamical properties when the center of mass of the moving body is at the cube's center.
|
||
|
||
This is because, both the mass and stiffness matrices are diagonal.
|
||
As shown in in section ref:ssec:detail_kinematics_cubic_static, the stiffness matrix is diagonal when the considered B frame is located at the cube's center.
|
||
|
||
Or, typically the $\{B\}$ frame is taken above the top platform where forces are applied and where displacements are expressed.
|
||
|
||
In this section, modifications of the Cubic architectures are proposed in order to be able to have the payload above the top platform while still benefiting from interesting dynamical properties of the cubic architecture.
|
||
|
||
There are three key parameters:
|
||
- $H$ height of the Stewart platform (distance from fix base to mobile platform)
|
||
- $H_c$ height of the cube, as shown in Figure ref:fig:detail_kinematics_cubic_schematic_full
|
||
- $H_{CoM}$ height of the center of mass with respect to the mobile platform. It is also the cube's center.
|
||
|
||
# Say a $H = 100\,mm$ tall Stewart platform needs to be designed with the CoM of the payload $H_{CoM} = 20\,mm$ above the top platform.
|
||
# The cube's center therefore needs to be positioned 20mm above the top platform.
|
||
|
||
The obtained design depends on the considered size of the cube $H_c$ with respect to $H$ and $H_{CoM}$.
|
||
|
||
#+begin_src matlab
|
||
%% Cubic configurations with center of the cube above the top platform
|
||
H = 100e-3; % height of the Stewart platform [m]
|
||
MO_B = 20e-3; % Position {B} with respect to {M} [m]
|
||
FOc = H + MO_B; % Center of the cube with respect to {F}
|
||
#+end_src
|
||
|
||
**** Small cube
|
||
|
||
When the considered cube size is smaller than twice the height of the CoM, the obtained design looks like Figure ref:fig:detail_kinematics_cubic_above_small.
|
||
|
||
\begin{equation}\label{eq:detail_kinematics_cube_small}
|
||
H_c < 2 H_{CoM}
|
||
\end{equation}
|
||
|
||
This is similar to [[cite:&furutani04_nanom_cuttin_machin_using_stewar]], even though it is not mentioned that the system has a cubic configuration.
|
||
# TODO - Add link to Figure ref:fig:nhexa_stewart_piezo_furutani (page pageref:fig:nhexa_stewart_piezo_furutani)
|
||
|
||
Adjacent struts are parallel to each other, which is quite different from the typical architecture in which parallel struts are opposite to each other.
|
||
|
||
#+begin_src matlab
|
||
%% Small cube
|
||
Hc = 2*MO_B; % Size of the useful part of the cube [m]
|
||
|
||
stewart_small = initializeStewartPlatform();
|
||
stewart_small = initializeFramesPositions(stewart_small, 'H', H, 'MO_B', MO_B);
|
||
stewart_small = generateCubicConfiguration(stewart_small, 'Hc', Hc, 'FOc', FOc, 'FHa', 5e-3, 'MHb', 5e-3);
|
||
stewart_small = computeJointsPose(stewart_small);
|
||
stewart_small = initializeStrutDynamics(stewart_small, 'k', 1);
|
||
stewart_small = computeJacobian(stewart_small);
|
||
stewart_small = initializeCylindricalPlatforms(stewart_small, 'Fpr', 1.1*max(vecnorm(stewart_small.platform_F.Fa)), 'Mpr', 1.1*max(vecnorm(stewart_small.platform_M.Mb)));
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% ISO View
|
||
displayArchitecture(stewart_small, 'labels', false, 'frames', false);
|
||
plotCube(stewart_small, 'Hc', Hc, 'FOc', FOc, 'color', [0,0,0,0.2], 'link_to_struts', true);
|
||
scatter3(0, 0, FOc, 200, 'kh');
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_cubic_above_small_iso.pdf', 'width', 'normal', 'height', 'full');
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Side view
|
||
displayArchitecture(stewart_small, 'labels', false, 'frames', false);
|
||
plotCube(stewart_small, 'Hc', Hc, 'FOc', FOc, 'color', [0, 0, 0, 0.2], 'link_to_struts', true);
|
||
scatter3(0, 0, FOc, 200, 'kh');
|
||
view([90,0])
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_cubic_above_small_side.pdf', 'width', 'half', 'height', 'full');
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Top view
|
||
displayArchitecture(stewart_small, 'labels', false, 'frames', false);
|
||
plotCube(stewart_small, 'Hc', Hc, 'FOc', FOc, 'color', [0, 0, 0, 0.2], 'link_to_struts', true);
|
||
scatter3(0, 0, FOc, 200, 'kh');
|
||
view([0,90])
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_cubic_above_small_top.pdf', 'width', 'half', 'height', 'full');
|
||
#+end_src
|
||
|
||
#+name: fig:detail_kinematics_cubic_above_small
|
||
#+caption: Cubic architecture with cube's center above the top platform. A cube height of 40mm is used.
|
||
#+attr_latex: :options [htbp]
|
||
#+begin_figure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_cubic_above_small_iso}Isometric view}
|
||
#+attr_latex: :options {0.36\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.9\linewidth
|
||
[[file:figs/detail_kinematics_cubic_above_small_iso.png]]
|
||
#+end_subfigure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_cubic_above_small_side}Side view}
|
||
#+attr_latex: :options {0.30\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.9\linewidth
|
||
[[file:figs/detail_kinematics_cubic_above_small_side.png]]
|
||
#+end_subfigure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_cubic_above_small_top}Top view}
|
||
#+attr_latex: :options {0.30\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.9\linewidth
|
||
[[file:figs/detail_kinematics_cubic_above_small_top.png]]
|
||
#+end_subfigure
|
||
#+end_figure
|
||
|
||
**** Medium sized cube
|
||
|
||
Increasing the cube size with an height close to the stewart platform height leads to an architecture in which the struts are crossing.
|
||
|
||
\begin{equation}\label{eq:detail_kinematics_cube_medium}
|
||
2 H_{CoM} < H_c < 2 (H_{CoM} + H)
|
||
\end{equation}
|
||
|
||
This is similar to cite:yang19_dynam_model_decoup_contr_flexib (Figure ref:fig:detail_kinematics_yang19 in page pageref:fig:detail_kinematics_yang19), even though it is not cubic (but the struts are crossing).
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Example of a cubic architecture with cube's center above the top platform - Medium cube size
|
||
Hc = H + 2*MO_B; % Size of the useful part of the cube [m]
|
||
|
||
stewart_medium = initializeStewartPlatform();
|
||
stewart_medium = initializeFramesPositions(stewart_medium, 'H', H, 'MO_B', MO_B);
|
||
stewart_medium = generateCubicConfiguration(stewart_medium, 'Hc', Hc, 'FOc', FOc, 'FHa', 5e-3, 'MHb', 5e-3);
|
||
stewart_medium = computeJointsPose(stewart_medium);
|
||
stewart_medium = initializeStrutDynamics(stewart_medium, 'k', 1);
|
||
stewart_medium = computeJacobian(stewart_medium);
|
||
stewart_medium = initializeCylindricalPlatforms(stewart_medium, 'Fpr', 1.1*max(vecnorm(stewart_medium.platform_F.Fa)), 'Mpr', 1.1*max(vecnorm(stewart_medium.platform_M.Mb)));
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% ISO View
|
||
displayArchitecture(stewart_medium, 'labels', false, 'frames', false);
|
||
plotCube(stewart_medium, 'Hc', Hc, 'FOc', FOc, 'color', [0,0,0,0.2], 'link_to_struts', true);
|
||
scatter3(0, 0, FOc, 200, 'kh');
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_cubic_above_medium_iso.pdf', 'width', 'normal', 'height', 'full');
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Side view
|
||
displayArchitecture(stewart_medium, 'labels', false, 'frames', false);
|
||
plotCube(stewart_medium, 'Hc', Hc, 'FOc', FOc, 'color', [0, 0, 0, 0.2], 'link_to_struts', true);
|
||
scatter3(0, 0, FOc, 200, 'kh');
|
||
view([90,0])
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_cubic_above_medium_side.pdf', 'width', 'half', 'height', 'full');
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Top view
|
||
displayArchitecture(stewart_medium, 'labels', false, 'frames', false);
|
||
plotCube(stewart_medium, 'Hc', Hc, 'FOc', FOc, 'color', [0, 0, 0, 0.2], 'link_to_struts', true);
|
||
scatter3(0, 0, FOc, 200, 'kh');
|
||
view([0,90])
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_cubic_above_medium_top.pdf', 'width', 'half', 'height', 'full');
|
||
#+end_src
|
||
|
||
#+name: fig:detail_kinematics_cubic_above_medium
|
||
#+caption: Cubic architecture with cube's center above the top platform. A cube height of 140mm is used.
|
||
#+attr_latex: :options [htbp]
|
||
#+begin_figure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_cubic_above_medium_iso}Isometric view}
|
||
#+attr_latex: :options {0.36\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.9\linewidth
|
||
[[file:figs/detail_kinematics_cubic_above_medium_iso.png]]
|
||
#+end_subfigure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_cubic_above_medium_side}Side view}
|
||
#+attr_latex: :options {0.30\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.9\linewidth
|
||
[[file:figs/detail_kinematics_cubic_above_medium_side.png]]
|
||
#+end_subfigure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_cubic_above_medium_top}Top view}
|
||
#+attr_latex: :options {0.30\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.9\linewidth
|
||
[[file:figs/detail_kinematics_cubic_above_medium_top.png]]
|
||
#+end_subfigure
|
||
#+end_figure
|
||
|
||
**** Large cube
|
||
|
||
When the cube's height is more than twice the platform height added to the CoM height, the architecture shown in Figure ref:fig:detail_kinematics_cubic_above_large is obtained.
|
||
|
||
\begin{equation}\label{eq:detail_kinematics_cube_large}
|
||
2 (H_{CoM} + H) < H_c
|
||
\end{equation}
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Example of a cubic architecture with cube's center above the top platform - Large cube size
|
||
Hc = 2*(H + MO_B); % Size of the useful part of the cube [m]
|
||
|
||
stewart_large = initializeStewartPlatform();
|
||
stewart_large = initializeFramesPositions(stewart_large, 'H', H, 'MO_B', MO_B);
|
||
stewart_large = generateCubicConfiguration(stewart_large, 'Hc', Hc, 'FOc', FOc, 'FHa', 5e-3, 'MHb', 5e-3);
|
||
stewart_large = computeJointsPose(stewart_large);
|
||
stewart_large = initializeStrutDynamics(stewart_large, 'k', 1);
|
||
stewart_large = computeJacobian(stewart_large);
|
||
stewart_large = initializeCylindricalPlatforms(stewart_large, 'Fpr', 1.1*max(vecnorm(stewart_large.platform_F.Fa)), 'Mpr', 1.1*max(vecnorm(stewart_large.platform_M.Mb)));
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% ISO View
|
||
displayArchitecture(stewart_large, 'labels', false, 'frames', false);
|
||
plotCube(stewart_large, 'Hc', Hc, 'FOc', FOc, 'color', [0,0,0,0.2], 'link_to_struts', true);
|
||
scatter3(0, 0, FOc, 200, 'kh');
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_cubic_above_large_iso.pdf', 'width', 'normal', 'height', 'full');
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Side view
|
||
displayArchitecture(stewart_large, 'labels', false, 'frames', false);
|
||
plotCube(stewart_large, 'Hc', Hc, 'FOc', FOc, 'color', [0, 0, 0, 0.2], 'link_to_struts', true);
|
||
scatter3(0, 0, FOc, 200, 'kh');
|
||
view([90,0])
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_cubic_above_large_side.pdf', 'width', 'half', 'height', 'full');
|
||
#+end_src
|
||
|
||
#+begin_src matlab :exports none :results none
|
||
%% Top view
|
||
displayArchitecture(stewart_large, 'labels', false, 'frames', false);
|
||
plotCube(stewart_large, 'Hc', Hc, 'FOc', FOc, 'color', [0, 0, 0, 0.2], 'link_to_struts', true);
|
||
scatter3(0, 0, FOc, 200, 'kh');
|
||
view([0,90])
|
||
#+end_src
|
||
|
||
#+begin_src matlab :tangle no :exports results :results file none
|
||
exportFig('figs/detail_kinematics_cubic_above_large_top.pdf', 'width', 'half', 'height', 'full');
|
||
#+end_src
|
||
|
||
#+name: fig:detail_kinematics_cubic_above_large
|
||
#+caption: Cubic architecture with cube's center above the top platform. A cube height of 240mm is used.
|
||
#+attr_latex: :options [htbp]
|
||
#+begin_figure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_cubic_above_large_iso}Isometric view}
|
||
#+attr_latex: :options {0.36\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.9\linewidth
|
||
[[file:figs/detail_kinematics_cubic_above_large_iso.png]]
|
||
#+end_subfigure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_cubic_above_large_side}Side view}
|
||
#+attr_latex: :options {0.30\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.9\linewidth
|
||
[[file:figs/detail_kinematics_cubic_above_large_side.png]]
|
||
#+end_subfigure
|
||
#+attr_latex: :caption \subcaption{\label{fig:detail_kinematics_cubic_above_large_top}Top view}
|
||
#+attr_latex: :options {0.30\textwidth}
|
||
#+begin_subfigure
|
||
#+attr_latex: :width 0.9\linewidth
|
||
[[file:figs/detail_kinematics_cubic_above_large_top.png]]
|
||
#+end_subfigure
|
||
#+end_figure
|
||
|
||
**** Platform size
|
||
|
||
#+begin_src matlab
|
||
%% Get the analytical formula for the location of the top and bottom joints
|
||
% Define symbolic variables
|
||
syms k Hc Hcom alpha H
|
||
|
||
assume(k > 0); % k is positive real
|
||
assume(Hcom > 0); % k is positive real
|
||
assume(Hc > 0); % Hc is real
|
||
assume(H > 0); % H is real
|
||
assume(alpha, 'real'); % alpha is real
|
||
|
||
% Define si matrix (edges of the cubes)
|
||
si = 1/sqrt(3)*[
|
||
[ sqrt(2), 0, 1]; ...
|
||
[-sqrt(2)/2, -sqrt(3/2), 1]; ...
|
||
[-sqrt(2)/2, sqrt(3/2), 1]; ...
|
||
[ sqrt(2), 0, 1]; ...
|
||
[-sqrt(2)/2, -sqrt(3/2), 1]; ...
|
||
[-sqrt(2)/2, sqrt(3/2), 1] ...
|
||
];
|
||
|
||
% Define ci matrix (vertices of the cubes)
|
||
ci = Hc * [
|
||
[1/sqrt(2), -sqrt(3)/sqrt(2), 0.5]; ...
|
||
[1/sqrt(2), -sqrt(3)/sqrt(2), 0.5]; ...
|
||
[1/sqrt(2), sqrt(3)/sqrt(2), 0.5]; ...
|
||
[1/sqrt(2), sqrt(3)/sqrt(2), 0.5]; ...
|
||
[-sqrt(2), 0, 0.5]; ...
|
||
[-sqrt(2), 0, 0.5] ...
|
||
];
|
||
|
||
% Apply vertical shift to ci
|
||
ci = ci + (H + Hcom) * [0, 0, 1];
|
||
|
||
% Calculate bi vectors (Stewart platform top joints)
|
||
bi = ci + alpha * si;
|
||
|
||
|
||
% Extract the z-component value from the first row of ci
|
||
% (all rows have the same z-component)
|
||
ci_z = ci(1, 3);
|
||
|
||
% The z-component of si is 1 for all rows
|
||
si_z = si(1, 3);
|
||
|
||
alpha_for_0 = solve(ci_z + alpha * si_z == 0, alpha);
|
||
alpha_for_H = solve(ci_z + alpha * si_z == H, alpha);
|
||
|
||
% Verify the results
|
||
% Substitute alpha values and check the resulting bi_z values
|
||
bi_z_0 = ci + alpha_for_0 * si;
|
||
disp('Verification bi_z = 0:');
|
||
disp(simplify(bi_z_0));
|
||
|
||
bi_z_H = ci + alpha_for_H * si;
|
||
disp('Verification bi_z = H:');
|
||
disp(simplify(bi_z_H));
|
||
|
||
% Compute radius
|
||
simplify(sqrt(bi_z_H(:,1).^2 + bi_z_H(:,2).^2))
|
||
simplify(sqrt(bi_z_0(:,1).^2 + bi_z_0(:,2).^2))
|
||
#+end_src
|
||
|
||
The top joints $\bm{b}_i$ are located on a circle with radius $R_{b_i}$ eqref:eq:detail_kinematics_cube_top_joints.
|
||
The bottom joints $\bm{a}_i$ are located on a circle with radius $R_{a_i}$ eqref:eq:detail_kinematics_cube_bot_joints.
|
||
|
||
\begin{subequations}\label{eq:detail_kinematics_cube_joints}
|
||
\begin{align}
|
||
R_{b_i} &= \sqrt{\frac{3}{2} H_c^2 + 2 H_{CoM}^2} \label{eq:detail_kinematics_cube_top_joints} \\
|
||
R_{a_i} &= \sqrt{\frac{3}{2} H_c^2 + 2 (H_{CoM} + H)^2} \label{eq:detail_kinematics_cube_bot_joints}
|
||
\end{align}
|
||
\end{subequations}
|
||
|
||
The size of the platforms increase with the cube's size and the height of the location of the center of mass (also coincident with the cube's center).
|
||
The size of the bottom platform also increases with the height of the Stewart platform.
|
||
|
||
As the rotational stiffness for the cubic architecture is scaled as the square of the cube's height eqref:eq:detail_kinematics_cubic_stiffness, the cube's size can be determined from the requirements in terms of rotational stiffness.
|
||
Then, using eqref:eq:detail_kinematics_cube_joints, the size of the top and bottom platforms can be determined.
|
||
|
||
**** Conclusion
|
||
|
||
For each of the configuration, the Stiffness matrix is diagonal with $k_x = k_y = k_y = 2k$ with $k$ is the stiffness of each strut.
|
||
However, the rotational stiffnesses are increasing with the cube's size but the required size of the platform is also increasing, so there is a trade-off here.
|
||
|
||
We found that we can have a diagonal stiffness matrix using the cubic architecture when $\{A\}$ and $\{B\}$ are located above the top platform.
|
||
Depending on the cube's size, we obtain 3 different configurations.
|
||
|
||
** Conclusion
|
||
:PROPERTIES:
|
||
:UNNUMBERED: t
|
||
:END:
|
||
|
||
Cubic architecture can be interesting when specific payloads are being used.
|
||
In that case, the center of mass of the payload should be placed at the center of the cube.
|
||
For the classical architecture, it is often not possible.
|
||
|
||
Architectures with the center of the cube about the top platform are proposed to overcome this issue.
|
||
|
||
Cubic architecture are attributed a number of properties that were found to be incorrect:
|
||
- Uniform mobility
|
||
- Easy for decentralized control
|
||
|
||
* Nano Hexapod
|
||
:PROPERTIES:
|
||
:HEADER-ARGS:matlab+: :tangle matlab/detail_kinematics_3_nano_hexapod.m
|
||
:END:
|
||
<<sec:detail_kinematics_nano_hexapod>>
|
||
** Introduction :ignore:
|
||
|
||
For the NASS, the chosen frame $\{A\}$ and $\{B\}$ coincide with the sample's point of interest, which is $150\,mm$ above the top platform.
|
||
|
||
Requirements:
|
||
- The nano-hexapod should fit within a cylinder with radius of $120\,mm$ and with a height of $95\,mm$.
|
||
- In terms of mobility: uniform mobility in XYZ directions (100um)
|
||
- In terms of stiffness: ??
|
||
- In terms of dynamics:
|
||
- be able to apply IFF in a decentralized way with good robustness and performances (good damping of modes)
|
||
- good decoupling for the HAC
|
||
|
||
For the NASS, the payloads can have various inertia, with masses ranging from 1 to 50kg.
|
||
It is therefore not possible to have one geometry that gives good dynamical properties for all the payloads.
|
||
|
||
** 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
|
||
|
||
#+begin_src matlab :tangle no :noweb yes
|
||
<<m-init-path>>
|
||
#+end_src
|
||
|
||
#+begin_src matlab :eval no :noweb yes
|
||
<<m-init-path-tangle>>
|
||
#+end_src
|
||
|
||
#+begin_src matlab :noweb yes
|
||
<<m-init-simscape>>
|
||
#+end_src
|
||
|
||
#+begin_src matlab :noweb yes
|
||
<<m-init-other>>
|
||
#+end_src
|
||
|
||
** Obtained Geometry
|
||
|
||
Take both platforms at maximum size.
|
||
Make reasonable choice (close to the final choice).
|
||
Say that it is good enough to make all the calculations.
|
||
The geometry will be slightly refined during the detailed mechanical design for several reason: easy of mount, manufacturability, ...
|
||
|
||
#+begin_src matlab
|
||
%% Obtained Nano Hexapod Design
|
||
nano_hexapod = initializeStewartPlatform();
|
||
nano_hexapod = initializeFramesPositions(nano_hexapod, ...
|
||
'H', 95e-3, ...
|
||
'MO_B', 150e-3);
|
||
|
||
nano_hexapod = generateGeneralConfiguration(nano_hexapod, ...
|
||
'FH', 15e-3, ...
|
||
'FR', 120e-3, ...
|
||
'FTh', [220, 320, 340, 80, 100, 200]*(pi/180), ...
|
||
'MH', 15e-3, ...
|
||
'MR', 110e-3, ...
|
||
'MTh', [255, 285, 15, 45, 135, 165]*(pi/180));
|
||
nano_hexapod = computeJointsPose(nano_hexapod);
|
||
nano_hexapod = initializeStrutDynamics(nano_hexapod, 'k', 1);
|
||
nano_hexapod = computeJacobian(nano_hexapod);
|
||
nano_hexapod = initializeCylindricalPlatforms(nano_hexapod, 'Fpr', 130e-3, 'Mpr', 120e-3);
|
||
|
||
displayArchitecture(nano_hexapod, 'labels', true);
|
||
#+end_src
|
||
|
||
- [ ] Show the obtained geometry and the main parameters.
|
||
|
||
This geometry will be used for:
|
||
- estimate required actuator stroke
|
||
- estimate flexible joint stroke
|
||
- when performing noise budgeting for the choice of instrumentation
|
||
- for control purposes
|
||
It is only when the complete mechanical design is finished (Section ...), that the model will be updated.
|
||
|
||
** Required Actuator stroke
|
||
|
||
The actuator stroke to have the wanted mobility is computed.
|
||
|
||
Wanted mobility:
|
||
- Combined translations in the xyz directions of +/-50um (basically "cube")
|
||
- At any point of the cube, be able to do combined Rx and Ry rotations of +/-50urad
|
||
- Rz is always at 0
|
||
- Say that it is frame B with respect to frame A, but it is motion expressed at the point of interest (at the focus point of the light)
|
||
|
||
First the minimum actuator stroke to have the wanted mobility is computed.
|
||
With the chosen geometry, an actuator stroke of +/-94um is found.
|
||
|
||
#+begin_src matlab
|
||
max_translation = 50e-6;
|
||
max_rotation = 50e-6;
|
||
|
||
Dxs = linspace(-max_translation, max_translation, 3);
|
||
Dys = linspace(-max_translation, max_translation, 3);
|
||
Dzs = linspace(-max_translation, max_translation, 3);
|
||
Rxs = linspace(-max_rotation, max_rotation, 3);
|
||
Rys = linspace(-max_rotation, max_rotation, 3);
|
||
|
||
L_min = 0;
|
||
L_max = 0;
|
||
|
||
for Dx = Dxs
|
||
for Dy = Dys
|
||
for Dz = Dzs
|
||
for Rx = Rxs
|
||
for Ry = Rys
|
||
ARB = [ cos(Ry) 0 sin(Ry);
|
||
0 1 0;
|
||
-sin(Ry) 0 cos(Ry)] * ...
|
||
[ 1 0 0;
|
||
0 cos(Rx) -sin(Rx);
|
||
0 sin(Rx) cos(Rx)];
|
||
|
||
[~, Ls] = inverseKinematics(nano_hexapod, 'AP', [Dx;Dy;Dz], 'ARB', ARB);
|
||
|
||
if min(Ls) < L_min
|
||
L_min = min(Ls);
|
||
end
|
||
if max(Ls) > L_max
|
||
L_max = max(Ls);
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
sprintf('Actuator stroke should be from %.0f um to %.0f um', 1e6*L_min, 1e6*L_max)
|
||
#+end_src
|
||
|
||
Considering combined rotations and translations, the wanted mobility and the obtained mobility of the Nano hexapod are shown in Figure ...
|
||
|
||
It can be seen that just wanted mobility (displayed as a cube), just fits inside the obtained mobility.
|
||
Here the worst case scenario is considered, meaning that whatever the angular position in Rx and Ry (in the range +/-50urad), the top platform can be positioned anywhere inside the cube.
|
||
|
||
#+begin_src matlab
|
||
%% Compute mobility in translation with combined angular motion
|
||
% L_max = 100e-6; % Actuator Stroke (+/-)
|
||
|
||
% Direction of motion (spherical coordinates)
|
||
thetas = linspace(0, pi, 100);
|
||
phis = linspace(0, 2*pi, 100);
|
||
|
||
% Considered Rotations
|
||
Rxs = linspace(-max_rotation, max_rotation, 3);
|
||
Rys = linspace(-max_rotation, max_rotation, 3);
|
||
|
||
% Maximum distance that can be reached in the direction of motion
|
||
% Considering combined angular motion and limited actuator stroke
|
||
rs = zeros(length(thetas), length(phis));
|
||
worst_rx_ry = zeros(length(thetas), length(phis), 2);
|
||
|
||
for i = 1:length(thetas)
|
||
for j = 1:length(phis)
|
||
% Compute unitary motion in the considered direction
|
||
Tx = sin(thetas(i))*cos(phis(j));
|
||
Ty = sin(thetas(i))*sin(phis(j));
|
||
Tz = cos(thetas(i));
|
||
% Start without considering rotations
|
||
dL_lin = nano_hexapod.kinematics.J*[Tx; Ty; Tz; 0; 0; 0];
|
||
% Strut motion for maximum displacement in the considered direction
|
||
dL_lin_max = L_max*dL_lin/max(abs(dL_lin));
|
||
|
||
% Find rotation that gives worst case stroke
|
||
dL_worst = max(abs(dL_lin_max)); % This should be equal to L_max
|
||
dL_rot_max = zeros(6,1);
|
||
% Perform (small) rotations, and find the (worst) case requiring maximum strut motion
|
||
for Rx = Rxs
|
||
for Ry = Rys
|
||
dL_rot = nano_hexapod.kinematics.J*[0; 0; 0; Rx; Ry; 0];
|
||
if max(abs(dL_lin_max + dL_rot)) > dL_worst
|
||
dL_worst = max(abs(dL_lin_max + dL_rot));
|
||
dL_rot_max = dL_rot;
|
||
worst_rx_ry(i,j,:) = [Rx, Ry];
|
||
end
|
||
end
|
||
end
|
||
|
||
stroke_ratio = min(abs([( L_max - dL_rot_max) ./ dL_lin_max; (-L_max - dL_rot_max) ./ dL_lin_max]));
|
||
dL_real = dL_lin_max*stroke_ratio + dL_rot_max;
|
||
|
||
% % Obtained maximum displacement in the considered direction with angular motion
|
||
% rs(i, j) = stroke_ratio*max(abs(dL_lin_max));
|
||
rs(i, j) = stroke_ratio*L_max/max(abs(dL_lin));
|
||
end
|
||
end
|
||
|
||
min(min(rs))
|
||
max(max(rs))
|
||
|
||
[phi_grid, theta_grid] = meshgrid(phis, thetas);
|
||
X = 1e6 * rs .* sin(theta_grid) .* cos(phi_grid);
|
||
Y = 1e6 * rs .* sin(theta_grid) .* sin(phi_grid);
|
||
Z = 1e6 * rs .* cos(theta_grid);
|
||
|
||
vertices = 1e6*max_translation*[
|
||
-1 -1 -1; % vertex 1
|
||
1 -1 -1; % vertex 2
|
||
1 1 -1; % vertex 3
|
||
-1 1 -1; % vertex 4
|
||
-1 -1 1; % vertex 5
|
||
1 -1 1; % vertex 6
|
||
1 1 1; % vertex 7
|
||
-1 1 1 % vertex 8
|
||
];
|
||
|
||
% Define the faces using the vertex indices
|
||
faces = [
|
||
1 2 3 4; % bottom face
|
||
5 6 7 8; % top face
|
||
1 2 6 5; % front face
|
||
2 3 7 6; % right face
|
||
3 4 8 7; % back face
|
||
4 1 5 8 % left face
|
||
];
|
||
|
||
figure;
|
||
hold on;
|
||
s = surf(X, Y, Z, 'FaceColor', 'none');
|
||
s.EdgeColor = colors(2, :);
|
||
patch('Vertices', vertices, 'Faces', faces, ...
|
||
'FaceColor', [0.7 0.7 0.7], ...
|
||
'EdgeColor', 'black', ...
|
||
'FaceAlpha', 1);
|
||
hold off;
|
||
axis equal;
|
||
grid on;
|
||
xlabel('X Translation [$\mu$m]'); ylabel('Y Translation [$\mu$m]'); zlabel('Z Translation [$\mu$m]');
|
||
xlim(2e6*[-L_max, L_max]); ylim(2e6*[-L_max, L_max]); zlim(2e6*[-L_max, L_max]);
|
||
#+end_src
|
||
|
||
Therefore, in Section ..., the specification for actuator stroke is +/-100um
|
||
|
||
** Required Joint angular stroke
|
||
|
||
Now that the mobility of the Stewart platform is know, the corresponding flexible joint stroke can be estimated.
|
||
|
||
- conclude on the required joint angle: 1mrad?
|
||
Will be used to design flexible joints.
|
||
|
||
#+begin_src matlab
|
||
%% Estimation of the required flexible joint angular stroke
|
||
max_angles = zeros(1,6);
|
||
|
||
% Compute initial strut orientation
|
||
nano_hexapod = computeJointsPose(nano_hexapod, 'AP', zeros(3,1), 'ARB', eye(3));
|
||
As = nano_hexapod.geometry.As;
|
||
|
||
% Only consider translations, but add maximum expected top platform rotation
|
||
for i = 1:length(thetas)
|
||
for j = 1:length(phis)
|
||
% Maximum translations
|
||
Tx = rs(i,j)*sin(thetas(i))*cos(phis(j));
|
||
Ty = rs(i,j)*sin(thetas(i))*sin(phis(j));
|
||
Tz = rs(i,j)*cos(thetas(i));
|
||
|
||
nano_hexapod = computeJointsPose(nano_hexapod, 'AP', [Tx; Ty; Tz], 'ARB', eye(3));
|
||
|
||
angles = acos(dot(As, nano_hexapod.geometry.As));
|
||
larger_angles = abs(angles) > max_angles;
|
||
max_angles(larger_angles) = angles(larger_angles);
|
||
end
|
||
end
|
||
|
||
sprintf('Maximum flexible joint angle is %.1f mrad', 1e3*max(max_angles))
|
||
#+end_src
|
||
|
||
* Conclusion
|
||
<<sec:detail_kinematics_conclusion>>
|
||
|
||
Inertia used for experiments will be very broad => difficult to optimize the dynamics
|
||
Specific geometry is not found to have a huge impact on performances.
|
||
Practical implementation is important.
|
||
|
||
Geometry impacts the static and dynamical characteristics of the Stewart platform.
|
||
Considering the design constrains, the slight change of geometry will not significantly impact the obtained results.
|
||
|
||
* Bibliography :ignore:
|
||
#+latex: \printbibliography[heading=bibintoc,title={Bibliography}]
|
||
|
||
* Matlab Functions :noexport:
|
||
** =generateCubicConfiguration=: Generate a Cubic Configuration
|
||
#+begin_src matlab :tangle matlab/src/generateCubicConfiguration.m :comments none :mkdirp yes :eval no
|
||
function [stewart] = generateCubicConfiguration(stewart, args)
|
||
% generateCubicConfiguration - Generate a Cubic Configuration
|
||
%
|
||
% Syntax: [stewart] = generateCubicConfiguration(stewart, args)
|
||
%
|
||
% Inputs:
|
||
% - stewart - A structure with the following fields
|
||
% - geometry.H [1x1] - Total height of the platform [m]
|
||
% - args - Can have the following fields:
|
||
% - Hc [1x1] - Height of the "useful" part of the cube [m]
|
||
% - FOc [1x1] - Height of the center of the cube with respect to {F} [m]
|
||
% - FHa [1x1] - Height of the plane joining the points ai with respect to the frame {F} [m]
|
||
% - MHb [1x1] - Height of the plane joining the points bi with respect to the frame {M} [m]
|
||
%
|
||
% Outputs:
|
||
|
||
% - stewart - updated Stewart structure with the added fields:
|
||
% - platform_F.Fa [3x6] - Its i'th column is the position vector of joint ai with respect to {F}
|
||
% - platform_M.Mb [3x6] - Its i'th column is the position vector of joint bi with respect to {M}
|
||
|
||
arguments
|
||
stewart
|
||
args.Hc (1,1) double {mustBeNumeric, mustBePositive} = 60e-3
|
||
args.FOc (1,1) double {mustBeNumeric} = 50e-3
|
||
args.FHa (1,1) double {mustBeNumeric, mustBeNonnegative} = 15e-3
|
||
args.MHb (1,1) double {mustBeNumeric, mustBeNonnegative} = 15e-3
|
||
end
|
||
|
||
assert(isfield(stewart.geometry, 'H'), 'stewart.geometry should have attribute H')
|
||
H = stewart.geometry.H;
|
||
|
||
% We define the useful points of the cube with respect to the Cube's center.
|
||
% ${}^{C}C$ are the 6 vertices of the cubes expressed in a frame {C} which is located at the center of the cube and aligned with {F} and {M}.
|
||
|
||
sx = [ 2; -1; -1];
|
||
sy = [ 0; 1; -1];
|
||
sz = [ 1; 1; 1];
|
||
|
||
R = [sx, sy, sz]./vecnorm([sx, sy, sz]);
|
||
|
||
L = args.Hc*sqrt(3);
|
||
|
||
Cc = R'*[[0;0;L],[L;0;L],[L;0;0],[L;L;0],[0;L;0],[0;L;L]] - [0;0;1.5*args.Hc];
|
||
|
||
CCf = [Cc(:,1), Cc(:,3), Cc(:,3), Cc(:,5), Cc(:,5), Cc(:,1)]; % CCf(:,i) corresponds to the bottom cube's vertice corresponding to the i'th leg
|
||
CCm = [Cc(:,2), Cc(:,2), Cc(:,4), Cc(:,4), Cc(:,6), Cc(:,6)]; % CCm(:,i) corresponds to the top cube's vertice corresponding to the i'th leg
|
||
|
||
% We can compute the vector of each leg ${}^{C}\hat{\bm{s}}_{i}$ (unit vector from ${}^{C}C_{f}$ to ${}^{C}C_{m}$).
|
||
|
||
CSi = (CCm - CCf)./vecnorm(CCm - CCf);
|
||
|
||
% We now which to compute the position of the joints $a_{i}$ and $b_{i}$.
|
||
Fa = CCf + [0; 0; args.FOc] + ((args.FHa-(args.FOc-args.Hc/2))./CSi(3,:)).*CSi;
|
||
Mb = CCf + [0; 0; args.FOc-H] + ((H-args.MHb-(args.FOc-args.Hc/2))./CSi(3,:)).*CSi;
|
||
|
||
stewart.platform_F.Fa = Fa;
|
||
stewart.platform_M.Mb = Mb;
|
||
#+end_src
|
||
|
||
** =plotCube=: Plot the Cube
|
||
#+begin_src matlab :tangle matlab/src/plotCube.m :comments none :mkdirp yes :eval no
|
||
function [] = plotCube(stewart, args)
|
||
|
||
arguments
|
||
stewart
|
||
args.Hc (1,1) double {mustBeNumeric, mustBePositive} = 60e-3
|
||
args.FOc (1,1) double {mustBeNumeric} = 50e-3
|
||
args.color (4,1) double {mustBeNumeric} = [0,0,0,0.5]
|
||
args.linewidth (1,1) double {mustBeNumeric, mustBePositive} = 2.5
|
||
args.link_to_struts logical {mustBeNumericOrLogical} = false
|
||
end
|
||
|
||
sx = [ 2; -1; -1];
|
||
sy = [ 0; 1; -1];
|
||
sz = [ 1; 1; 1];
|
||
|
||
R = [sx, sy, sz]./vecnorm([sx, sy, sz]);
|
||
|
||
L = args.Hc*sqrt(3);
|
||
|
||
p_xyz = R'*[[0;0;0],[L;0;0],[L;L;0],[0;L;0],[0;0;L],[L;0;L],[L;L;L],[0;L;L]] - [0;0;1.5*args.Hc];
|
||
|
||
% Position center of the cube
|
||
p_xyz = p_xyz + args.FOc*[0;0;1]*ones(1,8);
|
||
|
||
edges_order = [1 2 3 4 1];
|
||
plot3(p_xyz(1,edges_order), p_xyz(2,edges_order), p_xyz(3,edges_order), '-', 'color', args.color, 'linewidth', args.linewidth);
|
||
edges_order = [5 6 7 8 5];
|
||
plot3(p_xyz(1,edges_order), p_xyz(2,edges_order), p_xyz(3,edges_order), '-', 'color', args.color, 'linewidth', args.linewidth);
|
||
edges_order = [1 5];
|
||
plot3(p_xyz(1,edges_order), p_xyz(2,edges_order), p_xyz(3,edges_order), '-', 'color', args.color, 'linewidth', args.linewidth);
|
||
edges_order = [2 6];
|
||
plot3(p_xyz(1,edges_order), p_xyz(2,edges_order), p_xyz(3,edges_order), '-', 'color', args.color, 'linewidth', args.linewidth);
|
||
edges_order = [3 7];
|
||
plot3(p_xyz(1,edges_order), p_xyz(2,edges_order), p_xyz(3,edges_order), '-', 'color', args.color, 'linewidth', args.linewidth);
|
||
edges_order = [4 8];
|
||
plot3(p_xyz(1,edges_order), p_xyz(2,edges_order), p_xyz(3,edges_order), '-', 'color', args.color, 'linewidth', args.linewidth);
|
||
|
||
if args.link_to_struts
|
||
Fb = stewart.platform_M.Mb + stewart.geometry.FO_M;
|
||
plot3([Fb(1,1), p_xyz(1,5)],...
|
||
[Fb(2,1), p_xyz(2,5)],...
|
||
[Fb(3,1), p_xyz(3,5)], '--', 'color', args.color, 'linewidth', args.linewidth);
|
||
plot3([Fb(1,2), p_xyz(1,2)],...
|
||
[Fb(2,2), p_xyz(2,2)],...
|
||
[Fb(3,2), p_xyz(3,2)], '--', 'color', args.color, 'linewidth', args.linewidth);
|
||
plot3([Fb(1,3), p_xyz(1,2)],...
|
||
[Fb(2,3), p_xyz(2,2)],...
|
||
[Fb(3,3), p_xyz(3,2)], '--', 'color', args.color, 'linewidth', args.linewidth);
|
||
plot3([Fb(1,4), p_xyz(1,4)],...
|
||
[Fb(2,4), p_xyz(2,4)],...
|
||
[Fb(3,4), p_xyz(3,4)], '--', 'color', args.color, 'linewidth', args.linewidth);
|
||
plot3([Fb(1,5), p_xyz(1,4)],...
|
||
[Fb(2,5), p_xyz(2,4)],...
|
||
[Fb(3,5), p_xyz(3,4)], '--', 'color', args.color, 'linewidth', args.linewidth);
|
||
plot3([Fb(1,6), p_xyz(1,5)],...
|
||
[Fb(2,6), p_xyz(2,5)],...
|
||
[Fb(3,6), p_xyz(3,5)], '--', 'color', args.color, 'linewidth', args.linewidth);
|
||
end
|
||
#+end_src
|
||
|
||
** =plotCylindricalPayload=: Plot a cylindrical Payload
|
||
#+begin_src matlab :tangle matlab/src/plotCylindricalPayload.m :comments none :mkdirp yes :eval no
|
||
function [] = plotCylindricalPayload(stewart, args)
|
||
|
||
arguments
|
||
stewart
|
||
args.H (1,1) double {mustBeNumeric, mustBePositive} = 100e-3
|
||
args.R (1,1) double {mustBeNumeric, mustBePositive} = 50e-3
|
||
args.H_offset (1,1) double {mustBeNumeric} = 0
|
||
args.color (3,1) double {mustBeNumeric} = [0.5,0.5,0.5]
|
||
end
|
||
|
||
[X,Y,Z] = cylinder(args.R);
|
||
Z = args.H*Z + args.H_offset;
|
||
surf(X, Y, Z, 'facecolor', args.color, 'edgecolor', 'none')
|
||
fill3(X(1,:), Y(1,:), Z(1,:), 'k', 'facecolor', args.color)
|
||
fill3(X(2,:), Y(2,:), Z(2,:), 'k', 'facecolor', args.color)
|
||
#+end_src
|
||
|
||
** =computeJacobian=: Compute the Jacobian Matrix
|
||
#+begin_src matlab :tangle matlab/src/computeJacobian.m :comments none :mkdirp yes :eval no
|
||
function [stewart] = computeJacobian(stewart)
|
||
% computeJacobian -
|
||
%
|
||
% Syntax: [stewart] = computeJacobian(stewart)
|
||
%
|
||
% Inputs:
|
||
% - stewart - With at least the following fields:
|
||
% - geometry.As [3x6] - The 6 unit vectors for each strut expressed in {A}
|
||
% - geometry.Ab [3x6] - The 6 position of the joints bi expressed in {A}
|
||
% - actuators.K [6x1] - Total stiffness of the actuators
|
||
%
|
||
% Outputs:
|
||
% - stewart - With the 3 added field:
|
||
% - kinematics.J [6x6] - The Jacobian Matrix
|
||
% - kinematics.K [6x6] - The Stiffness Matrix
|
||
% - kinematics.C [6x6] - The Compliance Matrix
|
||
|
||
assert(isfield(stewart.geometry, 'As'), 'stewart.geometry should have attribute As')
|
||
As = stewart.geometry.As;
|
||
|
||
assert(isfield(stewart.geometry, 'Ab'), 'stewart.geometry should have attribute Ab')
|
||
Ab = stewart.geometry.Ab;
|
||
|
||
assert(isfield(stewart.actuators, 'k'), 'stewart.actuators should have attribute k')
|
||
Ki = stewart.actuators.k*eye(6);
|
||
|
||
J = [As' , cross(Ab, As)'];
|
||
|
||
K = J'*Ki*J;
|
||
|
||
C = inv(K);
|
||
|
||
stewart.kinematics.J = J;
|
||
stewart.kinematics.K = K;
|
||
stewart.kinematics.C = C;
|
||
#+end_src
|
||
|
||
** =inverseKinematics=: Compute Inverse Kinematics
|
||
|
||
#+begin_src matlab :tangle matlab/src/inverseKinematics.m :comments none :mkdirp yes :eval no
|
||
function [Li, dLi] = inverseKinematics(stewart, args)
|
||
% inverseKinematics - Compute the needed length of each strut to have the wanted position and orientation of {B} with respect to {A}
|
||
%
|
||
% Syntax: [stewart] = inverseKinematics(stewart)
|
||
%
|
||
% Inputs:
|
||
% - stewart - A structure with the following fields
|
||
% - geometry.Aa [3x6] - The positions ai expressed in {A}
|
||
% - geometry.Bb [3x6] - The positions bi expressed in {B}
|
||
% - geometry.l [6x1] - Length of each strut
|
||
% - args - Can have the following fields:
|
||
% - AP [3x1] - The wanted position of {B} with respect to {A}
|
||
% - ARB [3x3] - The rotation matrix that gives the wanted orientation of {B} with respect to {A}
|
||
%
|
||
% Outputs:
|
||
% - Li [6x1] - The 6 needed length of the struts in [m] to have the wanted pose of {B} w.r.t. {A}
|
||
% - dLi [6x1] - The 6 needed displacement of the struts from the initial position in [m] to have the wanted pose of {B} w.r.t. {A}
|
||
|
||
arguments
|
||
stewart
|
||
args.AP (3,1) double {mustBeNumeric} = zeros(3,1)
|
||
args.ARB (3,3) double {mustBeNumeric} = eye(3)
|
||
end
|
||
|
||
assert(isfield(stewart.geometry, 'Aa'), 'stewart.geometry should have attribute Aa')
|
||
Aa = stewart.geometry.Aa;
|
||
|
||
assert(isfield(stewart.geometry, 'Bb'), 'stewart.geometry should have attribute Bb')
|
||
Bb = stewart.geometry.Bb;
|
||
|
||
assert(isfield(stewart.geometry, 'l'), 'stewart.geometry should have attribute l')
|
||
l = stewart.geometry.l;
|
||
|
||
Li = sqrt(args.AP'*args.AP + diag(Bb'*Bb) + diag(Aa'*Aa) - (2*args.AP'*Aa)' + (2*args.AP'*(args.ARB*Bb))' - diag(2*(args.ARB*Bb)'*Aa));
|
||
|
||
dLi = Li-l;
|
||
#+end_src
|
||
|
||
** =forwardKinematicsApprox=: Compute the Approximate Forward Kinematics
|
||
|
||
#+begin_src matlab :tangle matlab/src/forwardKinematicsApprox.m :comments none :mkdirp yes :eval no
|
||
function [P, R] = forwardKinematicsApprox(stewart, args)
|
||
% forwardKinematicsApprox - Computed the approximate pose of {B} with respect to {A} from the length of each strut and using
|
||
% the Jacobian Matrix
|
||
%
|
||
% Syntax: [P, R] = forwardKinematicsApprox(stewart, args)
|
||
%
|
||
% Inputs:
|
||
% - stewart - A structure with the following fields
|
||
% - kinematics.J [6x6] - The Jacobian Matrix
|
||
% - args - Can have the following fields:
|
||
% - dL [6x1] - Displacement of each strut [m]
|
||
%
|
||
% Outputs:
|
||
% - P [3x1] - The estimated position of {B} with respect to {A}
|
||
% - R [3x3] - The estimated rotation matrix that gives the orientation of {B} with respect to {A}
|
||
|
||
arguments
|
||
stewart
|
||
args.dL (6,1) double {mustBeNumeric} = zeros(6,1)
|
||
end
|
||
|
||
assert(isfield(stewart.kinematics, 'J'), 'stewart.kinematics should have attribute J')
|
||
J = stewart.kinematics.J;
|
||
|
||
X = J\args.dL;
|
||
|
||
P = X(1:3);
|
||
|
||
theta = norm(X(4:6));
|
||
s = X(4:6)/theta;
|
||
|
||
R = [s(1)^2*(1-cos(theta)) + cos(theta) , s(1)*s(2)*(1-cos(theta)) - s(3)*sin(theta), s(1)*s(3)*(1-cos(theta)) + s(2)*sin(theta);
|
||
s(2)*s(1)*(1-cos(theta)) + s(3)*sin(theta), s(2)^2*(1-cos(theta)) + cos(theta), s(2)*s(3)*(1-cos(theta)) - s(1)*sin(theta);
|
||
s(3)*s(1)*(1-cos(theta)) - s(2)*sin(theta), s(3)*s(2)*(1-cos(theta)) + s(1)*sin(theta), s(3)^2*(1-cos(theta)) + cos(theta)];
|
||
#+end_src
|
||
|
||
** =initializeStewartPlatform=: Initialize the Stewart Platform structure
|
||
#+begin_src matlab :tangle matlab/src/initializeStewartPlatform.m :comments none :mkdirp yes :eval no
|
||
function [stewart] = initializeStewartPlatform()
|
||
% initializeStewartPlatform - Initialize the stewart structure
|
||
%
|
||
% Syntax: [stewart] = initializeStewartPlatform(args)
|
||
%
|
||
% Outputs:
|
||
% - stewart - A structure with the following sub-structures:
|
||
% - platform_F -
|
||
% - platform_M -
|
||
% - joints_F -
|
||
% - joints_M -
|
||
% - struts_F -
|
||
% - struts_M -
|
||
% - actuators -
|
||
% - geometry -
|
||
% - properties -
|
||
|
||
stewart = struct();
|
||
stewart.platform_F = struct();
|
||
stewart.platform_M = struct();
|
||
stewart.joints_F = struct();
|
||
stewart.joints_M = struct();
|
||
stewart.struts_F = struct();
|
||
stewart.struts_M = struct();
|
||
stewart.actuators = struct();
|
||
stewart.sensors = struct();
|
||
stewart.sensors.inertial = struct();
|
||
stewart.sensors.force = struct();
|
||
stewart.sensors.relative = struct();
|
||
stewart.geometry = struct();
|
||
stewart.kinematics = struct();
|
||
#+end_src
|
||
|
||
** =initializeFramesPositions=: Initialize the positions of frames {A}, {B}, {F} and {M}
|
||
#+begin_src matlab :tangle matlab/src/initializeFramesPositions.m :comments none :mkdirp yes :eval no
|
||
function [stewart] = initializeFramesPositions(stewart, args)
|
||
% initializeFramesPositions - Initialize the positions of frames {A}, {B}, {F} and {M}
|
||
%
|
||
% Syntax: [stewart] = initializeFramesPositions(stewart, args)
|
||
%
|
||
% Inputs:
|
||
% - args - Can have the following fields:
|
||
% - H [1x1] - Total Height of the Stewart Platform (height from {F} to {M}) [m]
|
||
% - MO_B [1x1] - Height of the frame {B} with respect to {M} [m]
|
||
%
|
||
% Outputs:
|
||
% - stewart - A structure with the following fields:
|
||
% - geometry.H [1x1] - Total Height of the Stewart Platform [m]
|
||
% - geometry.FO_M [3x1] - Position of {M} with respect to {F} [m]
|
||
% - platform_M.MO_B [3x1] - Position of {B} with respect to {M} [m]
|
||
% - platform_F.FO_A [3x1] - Position of {A} with respect to {F} [m]
|
||
|
||
arguments
|
||
stewart
|
||
args.H (1,1) double {mustBeNumeric, mustBePositive} = 90e-3
|
||
args.MO_B (1,1) double {mustBeNumeric} = 50e-3
|
||
end
|
||
|
||
H = args.H; % Total Height of the Stewart Platform [m]
|
||
|
||
FO_M = [0; 0; H]; % Position of {M} with respect to {F} [m]
|
||
|
||
MO_B = [0; 0; args.MO_B]; % Position of {B} with respect to {M} [m]
|
||
|
||
FO_A = MO_B + FO_M; % Position of {A} with respect to {F} [m]
|
||
|
||
stewart.geometry.H = H;
|
||
stewart.geometry.FO_M = FO_M;
|
||
stewart.platform_M.MO_B = MO_B;
|
||
stewart.platform_F.FO_A = FO_A;
|
||
#+end_src
|
||
|
||
** =generateGeneralConfiguration=: Generate a Very General Configuration
|
||
#+begin_src matlab :tangle matlab/src/generateGeneralConfiguration.m :comments none :mkdirp yes :eval no
|
||
function [stewart] = generateGeneralConfiguration(stewart, args)
|
||
% generateGeneralConfiguration - Generate a Very General Configuration
|
||
%
|
||
% Syntax: [stewart] = generateGeneralConfiguration(stewart, args)
|
||
%
|
||
% Inputs:
|
||
% - args - Can have the following fields:
|
||
% - FH [1x1] - Height of the position of the fixed joints with respect to the frame {F} [m]
|
||
% - FR [1x1] - Radius of the position of the fixed joints in the X-Y [m]
|
||
% - FTh [6x1] - Angles of the fixed joints in the X-Y plane with respect to the X axis [rad]
|
||
% - MH [1x1] - Height of the position of the mobile joints with respect to the frame {M} [m]
|
||
% - FR [1x1] - Radius of the position of the mobile joints in the X-Y [m]
|
||
% - MTh [6x1] - Angles of the mobile joints in the X-Y plane with respect to the X axis [rad]
|
||
%
|
||
% Outputs:
|
||
% - stewart - updated Stewart structure with the added fields:
|
||
% - platform_F.Fa [3x6] - Its i'th column is the position vector of joint ai with respect to {F}
|
||
% - platform_M.Mb [3x6] - Its i'th column is the position vector of joint bi with respect to {M}
|
||
|
||
arguments
|
||
stewart
|
||
args.FH (1,1) double {mustBeNumeric, mustBeNonnegative} = 15e-3
|
||
args.FR (1,1) double {mustBeNumeric, mustBePositive} = 115e-3;
|
||
args.FTh (6,1) double {mustBeNumeric} = [-10, 10, 120-10, 120+10, 240-10, 240+10]*(pi/180);
|
||
args.MH (1,1) double {mustBeNumeric, mustBeNonnegative} = 15e-3
|
||
args.MR (1,1) double {mustBeNumeric, mustBePositive} = 90e-3;
|
||
args.MTh (6,1) double {mustBeNumeric} = [-60+10, 60-10, 60+10, 180-10, 180+10, -60-10]*(pi/180);
|
||
end
|
||
|
||
Fa = zeros(3,6);
|
||
Mb = zeros(3,6);
|
||
|
||
for i = 1:6
|
||
Fa(:,i) = [args.FR*cos(args.FTh(i)); args.FR*sin(args.FTh(i)); args.FH];
|
||
Mb(:,i) = [args.MR*cos(args.MTh(i)); args.MR*sin(args.MTh(i)); -args.MH];
|
||
end
|
||
|
||
stewart.platform_F.Fa = Fa;
|
||
stewart.platform_M.Mb = Mb;
|
||
#+end_src
|
||
|
||
** =computeJointsPose=: Compute the Pose of the Joints
|
||
#+begin_src matlab :tangle matlab/src/computeJointsPose.m :comments none :mkdirp yes :eval no
|
||
function [stewart] = computeJointsPose(stewart, args)
|
||
% computeJointsPose -
|
||
%
|
||
% Syntax: [stewart] = computeJointsPose(stewart, args)
|
||
%
|
||
% Inputs:
|
||
% - stewart - A structure with the following fields
|
||
% - platform_F.Fa [3x6] - Its i'th column is the position vector of joint ai with respect to {F}
|
||
% - platform_M.Mb [3x6] - Its i'th column is the position vector of joint bi with respect to {M}
|
||
% - platform_F.FO_A [3x1] - Position of {A} with respect to {F}
|
||
% - platform_M.MO_B [3x1] - Position of {B} with respect to {M}
|
||
% - geometry.FO_M [3x1] - Position of {M} with respect to {F}
|
||
% - args - Can have the following fields:
|
||
% - AP [3x1] - The wanted position of {B} with respect to {A}
|
||
% - ARB [3x3] - The rotation matrix that gives the wanted orientation of {B} with respect to {A}
|
||
%
|
||
% Outputs:
|
||
% - stewart - A structure with the following added fields
|
||
% - geometry.Aa [3x6] - The i'th column is the position of ai with respect to {A}
|
||
% - geometry.Ab [3x6] - The i'th column is the position of bi with respect to {A}
|
||
% - geometry.Ba [3x6] - The i'th column is the position of ai with respect to {B}
|
||
% - geometry.Bb [3x6] - The i'th column is the position of bi with respect to {B}
|
||
% - geometry.l [6x1] - The i'th element is the initial length of strut i
|
||
% - geometry.As [3x6] - The i'th column is the unit vector of strut i expressed in {A}
|
||
% - geometry.Bs [3x6] - The i'th column is the unit vector of strut i expressed in {B}
|
||
% - struts_F.l [6x1] - Length of the Fixed part of the i'th strut
|
||
% - struts_M.l [6x1] - Length of the Mobile part of the i'th strut
|
||
% - platform_F.FRa [3x3x6] - The i'th 3x3 array is the rotation matrix to orientate the bottom of the i'th strut from {F}
|
||
% - platform_M.MRb [3x3x6] - The i'th 3x3 array is the rotation matrix to orientate the top of the i'th strut from {M}
|
||
|
||
arguments
|
||
stewart
|
||
args.AP (3,1) double {mustBeNumeric} = zeros(3,1)
|
||
args.ARB (3,3) double {mustBeNumeric} = eye(3)
|
||
end
|
||
|
||
assert(isfield(stewart.platform_F, 'Fa'), 'stewart.platform_F should have attribute Fa')
|
||
Fa = stewart.platform_F.Fa;
|
||
|
||
assert(isfield(stewart.platform_M, 'Mb'), 'stewart.platform_M should have attribute Mb')
|
||
Mb = stewart.platform_M.Mb;
|
||
|
||
assert(isfield(stewart.platform_F, 'FO_A'), 'stewart.platform_F should have attribute FO_A')
|
||
FO_A = stewart.platform_F.FO_A;
|
||
|
||
assert(isfield(stewart.platform_M, 'MO_B'), 'stewart.platform_M should have attribute MO_B')
|
||
MO_B = stewart.platform_M.MO_B;
|
||
|
||
assert(isfield(stewart.geometry, 'FO_M'), 'stewart.geometry should have attribute FO_M')
|
||
FO_M = stewart.geometry.FO_M;
|
||
|
||
Aa = Fa - repmat(FO_A, [1, 6]);
|
||
Bb = Mb - repmat(MO_B, [1, 6]);
|
||
|
||
Ab = Bb - repmat(-MO_B-FO_M+FO_A, [1, 6]);
|
||
Ba = Aa - repmat( MO_B+FO_M-FO_A, [1, 6]);
|
||
|
||
Ab = args.ARB *Bb - repmat(-args.AP, [1, 6]);
|
||
Ba = args.ARB'*Aa - repmat( args.AP, [1, 6]);
|
||
|
||
As = (Ab - Aa)./vecnorm(Ab - Aa); % As_i is the i'th vector of As
|
||
|
||
l = vecnorm(Ab - Aa)';
|
||
|
||
Bs = (Bb - Ba)./vecnorm(Bb - Ba);
|
||
|
||
FRa = zeros(3,3,6);
|
||
MRb = zeros(3,3,6);
|
||
|
||
for i = 1:6
|
||
FRa(:,:,i) = [cross([0;1;0], As(:,i)) , cross(As(:,i), cross([0;1;0], As(:,i))) , As(:,i)];
|
||
FRa(:,:,i) = FRa(:,:,i)./vecnorm(FRa(:,:,i));
|
||
|
||
MRb(:,:,i) = [cross([0;1;0], Bs(:,i)) , cross(Bs(:,i), cross([0;1;0], Bs(:,i))) , Bs(:,i)];
|
||
MRb(:,:,i) = MRb(:,:,i)./vecnorm(MRb(:,:,i));
|
||
end
|
||
|
||
stewart.geometry.Aa = Aa;
|
||
stewart.geometry.Ab = Ab;
|
||
stewart.geometry.Ba = Ba;
|
||
stewart.geometry.Bb = Bb;
|
||
stewart.geometry.As = As;
|
||
stewart.geometry.Bs = Bs;
|
||
stewart.geometry.l = l;
|
||
|
||
stewart.struts_F.l = l/2;
|
||
stewart.struts_M.l = l/2;
|
||
|
||
stewart.platform_F.FRa = FRa;
|
||
stewart.platform_M.MRb = MRb;
|
||
#+end_src
|
||
|
||
** =initializeStewartPose=: Determine the initial stroke in each leg to have the wanted pose
|
||
#+begin_src matlab :tangle matlab/src/initializeStewartPose.m :comments none :mkdirp yes :eval no
|
||
function [stewart] = initializeStewartPose(stewart, args)
|
||
% initializeStewartPose - Determine the initial stroke in each leg to have the wanted pose
|
||
% It uses the inverse kinematic
|
||
%
|
||
% Syntax: [stewart] = initializeStewartPose(stewart, args)
|
||
%
|
||
% Inputs:
|
||
% - stewart - A structure with the following fields
|
||
% - Aa [3x6] - The positions ai expressed in {A}
|
||
% - Bb [3x6] - The positions bi expressed in {B}
|
||
% - args - Can have the following fields:
|
||
% - AP [3x1] - The wanted position of {B} with respect to {A}
|
||
% - ARB [3x3] - The rotation matrix that gives the wanted orientation of {B} with respect to {A}
|
||
%
|
||
% Outputs:
|
||
% - stewart - updated Stewart structure with the added fields:
|
||
% - actuators.Leq [6x1] - The 6 needed displacement of the struts from the initial position in [m] to have the wanted pose of {B} w.r.t. {A}
|
||
|
||
arguments
|
||
stewart
|
||
args.AP (3,1) double {mustBeNumeric} = zeros(3,1)
|
||
args.ARB (3,3) double {mustBeNumeric} = eye(3)
|
||
end
|
||
|
||
[Li, dLi] = inverseKinematics(stewart, 'AP', args.AP, 'ARB', args.ARB);
|
||
|
||
stewart.actuators.Leq = dLi;
|
||
#+end_src
|
||
|
||
** =initializeCylindricalPlatforms=: Initialize the geometry of the Fixed and Mobile Platforms
|
||
#+begin_src matlab :tangle matlab/src/initializeCylindricalPlatforms.m :comments none :mkdirp yes :eval no
|
||
function [stewart] = initializeCylindricalPlatforms(stewart, args)
|
||
% initializeCylindricalPlatforms - Initialize the geometry of the Fixed and Mobile Platforms
|
||
%
|
||
% Syntax: [stewart] = initializeCylindricalPlatforms(args)
|
||
%
|
||
% Inputs:
|
||
% - args - Structure with the following fields:
|
||
% - Fpm [1x1] - Fixed Platform Mass [kg]
|
||
% - Fph [1x1] - Fixed Platform Height [m]
|
||
% - Fpr [1x1] - Fixed Platform Radius [m]
|
||
% - Mpm [1x1] - Mobile Platform Mass [kg]
|
||
% - Mph [1x1] - Mobile Platform Height [m]
|
||
% - Mpr [1x1] - Mobile Platform Radius [m]
|
||
%
|
||
% Outputs:
|
||
% - stewart - updated Stewart structure with the added fields:
|
||
% - platform_F [struct] - structure with the following fields:
|
||
% - type = 1
|
||
% - M [1x1] - Fixed Platform Mass [kg]
|
||
% - I [3x3] - Fixed Platform Inertia matrix [kg*m^2]
|
||
% - H [1x1] - Fixed Platform Height [m]
|
||
% - R [1x1] - Fixed Platform Radius [m]
|
||
% - platform_M [struct] - structure with the following fields:
|
||
% - M [1x1] - Mobile Platform Mass [kg]
|
||
% - I [3x3] - Mobile Platform Inertia matrix [kg*m^2]
|
||
% - H [1x1] - Mobile Platform Height [m]
|
||
% - R [1x1] - Mobile Platform Radius [m]
|
||
|
||
arguments
|
||
stewart
|
||
args.Fpm (1,1) double {mustBeNumeric, mustBePositive} = 1
|
||
args.Fph (1,1) double {mustBeNumeric, mustBePositive} = 10e-3
|
||
args.Fpr (1,1) double {mustBeNumeric, mustBePositive} = 125e-3
|
||
args.Mpm (1,1) double {mustBeNumeric, mustBePositive} = 1
|
||
args.Mph (1,1) double {mustBeNumeric, mustBePositive} = 10e-3
|
||
args.Mpr (1,1) double {mustBeNumeric, mustBePositive} = 100e-3
|
||
end
|
||
|
||
I_F = diag([1/12*args.Fpm * (3*args.Fpr^2 + args.Fph^2), ...
|
||
1/12*args.Fpm * (3*args.Fpr^2 + args.Fph^2), ...
|
||
1/2 *args.Fpm * args.Fpr^2]);
|
||
|
||
I_M = diag([1/12*args.Mpm * (3*args.Mpr^2 + args.Mph^2), ...
|
||
1/12*args.Mpm * (3*args.Mpr^2 + args.Mph^2), ...
|
||
1/2 *args.Mpm * args.Mpr^2]);
|
||
|
||
stewart.platform_F.type = 1;
|
||
|
||
stewart.platform_F.I = I_F;
|
||
stewart.platform_F.M = args.Fpm;
|
||
stewart.platform_F.R = args.Fpr;
|
||
stewart.platform_F.H = args.Fph;
|
||
|
||
stewart.platform_M.type = 1;
|
||
|
||
stewart.platform_M.I = I_M;
|
||
stewart.platform_M.M = args.Mpm;
|
||
stewart.platform_M.R = args.Mpr;
|
||
stewart.platform_M.H = args.Mph;
|
||
#+end_src
|
||
|
||
** =initializeStrutDynamics=: Add Stiffness and Damping properties of each strut
|
||
|
||
#+begin_src matlab :tangle matlab/src/initializeStrutDynamics.m :comments none :mkdirp yes :eval no
|
||
function [stewart] = initializeStrutDynamics(stewart, args)
|
||
% initializeStrutDynamics - Add Stiffness and Damping properties of each strut
|
||
%
|
||
% Syntax: [stewart] = initializeStrutDynamics(args)
|
||
%
|
||
% Inputs:
|
||
% - args - Structure with the following fields:
|
||
% - K [6x1] - Stiffness of each strut [N/m]
|
||
% - C [6x1] - Damping of each strut [N/(m/s)]
|
||
%
|
||
% Outputs:
|
||
% - stewart - updated Stewart structure with the added fields:
|
||
% - actuators.type = 1
|
||
% - actuators.K [6x1] - Stiffness of each strut [N/m]
|
||
% - actuators.C [6x1] - Damping of each strut [N/(m/s)]
|
||
|
||
arguments
|
||
stewart
|
||
args.type char {mustBeMember(args.type,{'1dof', '2dof', 'flexible'})} = '1dof'
|
||
args.k (1,1) double {mustBeNumeric, mustBeNonnegative} = 20e6
|
||
args.kp (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
|
||
args.ke (1,1) double {mustBeNumeric, mustBeNonnegative} = 5e6
|
||
args.ka (1,1) double {mustBeNumeric, mustBeNonnegative} = 60e6
|
||
args.c (1,1) double {mustBeNumeric, mustBeNonnegative} = 2e1
|
||
args.cp (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
|
||
args.ce (1,1) double {mustBeNumeric, mustBeNonnegative} = 1e6
|
||
args.ca (1,1) double {mustBeNumeric, mustBeNonnegative} = 10
|
||
|
||
args.F_gain (1,1) double {mustBeNumeric} = 1
|
||
args.me (1,1) double {mustBeNumeric} = 0.01
|
||
args.ma (1,1) double {mustBeNumeric} = 0.01
|
||
end
|
||
|
||
if strcmp(args.type, '1dof')
|
||
stewart.actuators.type = 1;
|
||
elseif strcmp(args.type, '2dof')
|
||
stewart.actuators.type = 2;
|
||
elseif strcmp(args.type, 'flexible')
|
||
stewart.actuators.type = 3;
|
||
end
|
||
|
||
stewart.actuators.k = args.k;
|
||
stewart.actuators.c = args.c;
|
||
|
||
% Parallel stiffness
|
||
stewart.actuators.kp = args.kp;
|
||
stewart.actuators.cp = args.cp;
|
||
|
||
stewart.actuators.ka = args.ka;
|
||
stewart.actuators.ca = args.ca;
|
||
|
||
stewart.actuators.ke = args.ke;
|
||
stewart.actuators.ce = args.ce;
|
||
|
||
stewart.actuators.F_gain = args.F_gain;
|
||
|
||
stewart.actuators.ma = args.ma;
|
||
stewart.actuators.me = args.me;
|
||
|
||
end
|
||
#+end_src
|
||
|
||
|
||
** =displayArchitecture=: 3D plot of the Stewart platform architecture
|
||
#+begin_src matlab :tangle matlab/src/displayArchitecture.m :comments none :mkdirp yes :eval no
|
||
function [] = displayArchitecture(stewart, args)
|
||
% displayArchitecture - 3D plot of the Stewart platform architecture
|
||
%
|
||
% Syntax: [] = displayArchitecture(args)
|
||
%
|
||
% Inputs:
|
||
% - stewart
|
||
% - args - Structure with the following fields:
|
||
% - AP [3x1] - The wanted position of {B} with respect to {A}
|
||
% - ARB [3x3] - The rotation matrix that gives the wanted orientation of {B} with respect to {A}
|
||
% - ARB [3x3] - The rotation matrix that gives the wanted orientation of {B} with respect to {A}
|
||
% - F_color [color] - Color used for the Fixed elements
|
||
% - M_color [color] - Color used for the Mobile elements
|
||
% - L_color [color] - Color used for the Legs elements
|
||
% - frames [true/false] - Display the Frames
|
||
% - legs [true/false] - Display the Legs
|
||
% - joints [true/false] - Display the Joints
|
||
% - labels [true/false] - Display the Labels
|
||
% - platforms [true/false] - Display the Platforms
|
||
% - views ['all', 'xy', 'yz', 'xz', 'default'] -
|
||
%
|
||
% Outputs:
|
||
|
||
arguments
|
||
stewart
|
||
args.AP (3,1) double {mustBeNumeric} = zeros(3,1)
|
||
args.ARB (3,3) double {mustBeNumeric} = eye(3)
|
||
args.F_color = [0 0.4470 0.7410]
|
||
args.M_color = [0.8500 0.3250 0.0980]
|
||
args.L_color = [0 0 0]
|
||
args.frames logical {mustBeNumericOrLogical} = true
|
||
args.legs logical {mustBeNumericOrLogical} = true
|
||
args.joints logical {mustBeNumericOrLogical} = true
|
||
args.labels logical {mustBeNumericOrLogical} = true
|
||
args.platforms logical {mustBeNumericOrLogical} = true
|
||
args.views char {mustBeMember(args.views,{'all', 'xy', 'xz', 'yz', 'default'})} = 'default'
|
||
end
|
||
|
||
assert(isfield(stewart.platform_F, 'FO_A'), 'stewart.platform_F should have attribute FO_A')
|
||
FO_A = stewart.platform_F.FO_A;
|
||
|
||
assert(isfield(stewart.platform_M, 'MO_B'), 'stewart.platform_M should have attribute MO_B')
|
||
MO_B = stewart.platform_M.MO_B;
|
||
|
||
assert(isfield(stewart.geometry, 'H'), 'stewart.geometry should have attribute H')
|
||
H = stewart.geometry.H;
|
||
|
||
assert(isfield(stewart.platform_F, 'Fa'), 'stewart.platform_F should have attribute Fa')
|
||
Fa = stewart.platform_F.Fa;
|
||
|
||
assert(isfield(stewart.platform_M, 'Mb'), 'stewart.platform_M should have attribute Mb')
|
||
Mb = stewart.platform_M.Mb;
|
||
|
||
% The reference frame of the 3d plot corresponds to the frame $\{F\}$.
|
||
if ~strcmp(args.views, 'all')
|
||
figure;
|
||
else
|
||
f = figure('visible', 'off');
|
||
end
|
||
|
||
hold on;
|
||
|
||
% We first compute homogeneous matrices that will be useful to position elements on the figure where the reference frame is $\{F\}$.
|
||
FTa = [eye(3), FO_A; ...
|
||
zeros(1,3), 1];
|
||
ATb = [args.ARB, args.AP; ...
|
||
zeros(1,3), 1];
|
||
BTm = [eye(3), -MO_B; ...
|
||
zeros(1,3), 1];
|
||
|
||
FTm = FTa*ATb*BTm;
|
||
|
||
% Let's define a parameter that define the length of the unit vectors used to display the frames.
|
||
d_unit_vector = H/4;
|
||
|
||
% Let's define a parameter used to position the labels with respect to the center of the element.
|
||
d_label = H/20;
|
||
% Let's first plot the frame $\{F\}$.
|
||
Ff = [0, 0, 0];
|
||
if args.frames
|
||
quiver3(Ff(1)*ones(1,3), Ff(2)*ones(1,3), Ff(3)*ones(1,3), ...
|
||
[d_unit_vector 0 0], [0 d_unit_vector 0], [0 0 d_unit_vector], '-', 'Color', args.F_color)
|
||
|
||
if args.labels
|
||
text(Ff(1) + d_label, ...
|
||
Ff(2) + d_label, ...
|
||
Ff(3) + d_label, '$\{F\}$', 'Color', args.F_color);
|
||
end
|
||
end
|
||
|
||
% Now plot the frame $\{A\}$ fixed to the Base.
|
||
if args.frames
|
||
quiver3(FO_A(1)*ones(1,3), FO_A(2)*ones(1,3), FO_A(3)*ones(1,3), ...
|
||
[d_unit_vector 0 0], [0 d_unit_vector 0], [0 0 d_unit_vector], '-', 'Color', args.F_color)
|
||
|
||
if args.labels
|
||
text(FO_A(1) + d_label, ...
|
||
FO_A(2) + d_label, ...
|
||
FO_A(3) + d_label, '$\{A\}$', 'Color', args.F_color);
|
||
end
|
||
end
|
||
|
||
% Let's then plot the circle corresponding to the shape of the Fixed base.
|
||
if args.platforms && stewart.platform_F.type == 1
|
||
theta = [0:0.1:2*pi+0.1]; % Angles [rad]
|
||
v = null([0; 0; 1]'); % Two vectors that are perpendicular to the circle normal
|
||
center = [0; 0; 0]; % Center of the circle
|
||
radius = stewart.platform_F.R; % Radius of the circle [m]
|
||
|
||
points = center*ones(1, length(theta)) + radius*(v(:,1)*cos(theta) + v(:,2)*sin(theta));
|
||
|
||
plot3(points(1,:), ...
|
||
points(2,:), ...
|
||
points(3,:), '-', 'Color', args.F_color);
|
||
end
|
||
|
||
% Let's now plot the position and labels of the Fixed Joints
|
||
if args.joints
|
||
scatter3(Fa(1,:), ...
|
||
Fa(2,:), ...
|
||
Fa(3,:), 'MarkerEdgeColor', args.F_color);
|
||
if args.labels
|
||
for i = 1:size(Fa,2)
|
||
text(Fa(1,i) + d_label, ...
|
||
Fa(2,i), ...
|
||
Fa(3,i), sprintf('$a_{%i}$', i), 'Color', args.F_color);
|
||
end
|
||
end
|
||
end
|
||
|
||
% Plot the frame $\{M\}$.
|
||
Fm = FTm*[0; 0; 0; 1]; % Get the position of frame {M} w.r.t. {F}
|
||
|
||
if args.frames
|
||
FM_uv = FTm*[d_unit_vector*eye(3); zeros(1,3)]; % Rotated Unit vectors
|
||
quiver3(Fm(1)*ones(1,3), Fm(2)*ones(1,3), Fm(3)*ones(1,3), ...
|
||
FM_uv(1,1:3), FM_uv(2,1:3), FM_uv(3,1:3), '-', 'Color', args.M_color)
|
||
|
||
if args.labels
|
||
text(Fm(1) + d_label, ...
|
||
Fm(2) + d_label, ...
|
||
Fm(3) + d_label, '$\{M\}$', 'Color', args.M_color);
|
||
end
|
||
end
|
||
|
||
% Plot the frame $\{B\}$.
|
||
FB = FO_A + args.AP;
|
||
|
||
if args.frames
|
||
FB_uv = FTm*[d_unit_vector*eye(3); zeros(1,3)]; % Rotated Unit vectors
|
||
quiver3(FB(1)*ones(1,3), FB(2)*ones(1,3), FB(3)*ones(1,3), ...
|
||
FB_uv(1,1:3), FB_uv(2,1:3), FB_uv(3,1:3), '-', 'Color', args.M_color)
|
||
|
||
if args.labels
|
||
text(FB(1) - d_label, ...
|
||
FB(2) + d_label, ...
|
||
FB(3) + d_label, '$\{B\}$', 'Color', args.M_color);
|
||
end
|
||
end
|
||
|
||
% Let's then plot the circle corresponding to the shape of the Mobile platform.
|
||
if args.platforms && stewart.platform_M.type == 1
|
||
theta = [0:0.1:2*pi+0.1]; % Angles [rad]
|
||
v = null((FTm(1:3,1:3)*[0;0;1])'); % Two vectors that are perpendicular to the circle normal
|
||
center = Fm(1:3); % Center of the circle
|
||
radius = stewart.platform_M.R; % Radius of the circle [m]
|
||
|
||
points = center*ones(1, length(theta)) + radius*(v(:,1)*cos(theta) + v(:,2)*sin(theta));
|
||
|
||
plot3(points(1,:), ...
|
||
points(2,:), ...
|
||
points(3,:), '-', 'Color', args.M_color);
|
||
end
|
||
|
||
% Plot the position and labels of the rotation joints fixed to the mobile platform.
|
||
if args.joints
|
||
Fb = FTm*[Mb;ones(1,6)];
|
||
|
||
scatter3(Fb(1,:), ...
|
||
Fb(2,:), ...
|
||
Fb(3,:), 'MarkerEdgeColor', args.M_color);
|
||
|
||
if args.labels
|
||
for i = 1:size(Fb,2)
|
||
text(Fb(1,i) + d_label, ...
|
||
Fb(2,i), ...
|
||
Fb(3,i), sprintf('$b_{%i}$', i), 'Color', args.M_color);
|
||
end
|
||
end
|
||
end
|
||
|
||
% Plot the legs connecting the joints of the fixed base to the joints of the mobile platform.
|
||
if args.legs
|
||
for i = 1:6
|
||
plot3([Fa(1,i), Fb(1,i)], ...
|
||
[Fa(2,i), Fb(2,i)], ...
|
||
[Fa(3,i), Fb(3,i)], '-', 'Color', args.L_color);
|
||
|
||
if args.labels
|
||
text((Fa(1,i)+Fb(1,i))/2 + d_label, ...
|
||
(Fa(2,i)+Fb(2,i))/2, ...
|
||
(Fa(3,i)+Fb(3,i))/2, sprintf('$%i$', i), 'Color', args.L_color);
|
||
end
|
||
end
|
||
end
|
||
|
||
switch args.views
|
||
case 'default'
|
||
view([1 -0.6 0.4]);
|
||
case 'xy'
|
||
view([0 0 1]);
|
||
case 'xz'
|
||
view([0 -1 0]);
|
||
case 'yz'
|
||
view([1 0 0]);
|
||
end
|
||
axis equal;
|
||
axis off;
|
||
|
||
if strcmp(args.views, 'all')
|
||
hAx = findobj('type', 'axes');
|
||
|
||
figure;
|
||
s1 = subplot(2,2,1);
|
||
copyobj(get(hAx(1), 'Children'), s1);
|
||
view([0 0 1]);
|
||
axis equal;
|
||
axis off;
|
||
title('Top')
|
||
|
||
s2 = subplot(2,2,2);
|
||
copyobj(get(hAx(1), 'Children'), s2);
|
||
view([1 -0.6 0.4]);
|
||
axis equal;
|
||
axis off;
|
||
|
||
s3 = subplot(2,2,3);
|
||
copyobj(get(hAx(1), 'Children'), s3);
|
||
view([1 0 0]);
|
||
axis equal;
|
||
axis off;
|
||
title('Front')
|
||
|
||
s4 = subplot(2,2,4);
|
||
copyobj(get(hAx(1), 'Children'), s4);
|
||
view([0 -1 0]);
|
||
axis equal;
|
||
axis off;
|
||
title('Side')
|
||
|
||
close(f);
|
||
end
|
||
#+end_src
|
||
|
||
** =describeStewartPlatform=: Display some text describing the current defined Stewart Platform
|
||
#+begin_src matlab :tangle matlab/src/describeStewartPlatform.m :comments none :mkdirp yes :eval no
|
||
function [] = describeStewartPlatform(stewart)
|
||
% describeStewartPlatform - Display some text describing the current defined Stewart Platform
|
||
%
|
||
% Syntax: [] = describeStewartPlatform(args)
|
||
%
|
||
% Inputs:
|
||
% - stewart
|
||
%
|
||
% Outputs:
|
||
|
||
arguments
|
||
stewart
|
||
end
|
||
|
||
fprintf('GEOMETRY:\n')
|
||
fprintf('- The height between the fixed based and the top platform is %.3g [mm].\n', 1e3*stewart.geometry.H)
|
||
|
||
if stewart.platform_M.MO_B(3) > 0
|
||
fprintf('- Frame {A} is located %.3g [mm] above the top platform.\n', 1e3*stewart.platform_M.MO_B(3))
|
||
else
|
||
fprintf('- Frame {A} is located %.3g [mm] below the top platform.\n', - 1e3*stewart.platform_M.MO_B(3))
|
||
end
|
||
|
||
fprintf('- The initial length of the struts are:\n')
|
||
fprintf('\t %.3g, %.3g, %.3g, %.3g, %.3g, %.3g [mm]\n', 1e3*stewart.geometry.l)
|
||
fprintf('\n')
|
||
|
||
fprintf('ACTUATORS:\n')
|
||
if stewart.actuators.type == 1
|
||
fprintf('- The actuators are classical.\n')
|
||
fprintf('- The Stiffness and Damping of each actuators is:\n')
|
||
fprintf('\t k = %.0e [N/m] \t c = %.0e [N/(m/s)]\n', stewart.actuators.k, stewart.actuators.c)
|
||
elseif stewart.actuators.type == 2
|
||
fprintf('- The actuators are mechanicaly amplified.\n')
|
||
end
|
||
fprintf('\n')
|
||
|
||
fprintf('JOINTS:\n')
|
||
|
||
switch stewart.joints_F.type
|
||
case 1
|
||
fprintf('- The joints on the fixed based are universal joints\n')
|
||
case 2
|
||
fprintf('- The joints on the fixed based are spherical joints\n')
|
||
case 3
|
||
fprintf('- The joints on the fixed based are perfect universal joints\n')
|
||
case 4
|
||
fprintf('- The joints on the fixed based are perfect spherical joints\n')
|
||
end
|
||
|
||
switch stewart.joints_M.type
|
||
case 1
|
||
fprintf('- The joints on the mobile based are universal joints\n')
|
||
case 2
|
||
fprintf('- The joints on the mobile based are spherical joints\n')
|
||
case 3
|
||
fprintf('- The joints on the mobile based are perfect universal joints\n')
|
||
case 4
|
||
fprintf('- The joints on the mobile based are perfect spherical joints\n')
|
||
end
|
||
|
||
fprintf('- The position of the joints on the fixed based with respect to {F} are (in [mm]):\n')
|
||
fprintf('\t % .3g \t % .3g \t % .3g\n', 1e3*stewart.platform_F.Fa)
|
||
|
||
fprintf('- The position of the joints on the mobile based with respect to {M} are (in [mm]):\n')
|
||
fprintf('\t % .3g \t % .3g \t % .3g\n', 1e3*stewart.platform_M.Mb)
|
||
fprintf('\n')
|
||
|
||
fprintf('KINEMATICS:\n')
|
||
|
||
if isfield(stewart.kinematics, 'K')
|
||
fprintf('- The Stiffness matrix K is (in [N/m]):\n')
|
||
fprintf('\t % .0e \t % .0e \t % .0e \t % .0e \t % .0e \t % .0e\n', stewart.kinematics.K)
|
||
end
|
||
|
||
if isfield(stewart.kinematics, 'C')
|
||
fprintf('- The Damping matrix C is (in [m/N]):\n')
|
||
fprintf('\t % .0e \t % .0e \t % .0e \t % .0e \t % .0e \t % .0e\n', stewart.kinematics.C)
|
||
end
|
||
#+end_src
|
||
|
||
** =initializeCylindricalStruts=: Define the inertia of cylindrical struts
|
||
|
||
#+begin_src matlab :tangle matlab/src/initializeCylindricalStruts.m :comments none :mkdirp yes :eval no
|
||
function [stewart] = initializeCylindricalStruts(stewart, args)
|
||
% initializeCylindricalStruts - Define the mass and moment of inertia of cylindrical struts
|
||
%
|
||
% Syntax: [stewart] = initializeCylindricalStruts(args)
|
||
%
|
||
% Inputs:
|
||
% - args - Structure with the following fields:
|
||
% - Fsm [1x1] - Mass of the Fixed part of the struts [kg]
|
||
% - Fsh [1x1] - Height of cylinder for the Fixed part of the struts [m]
|
||
% - Fsr [1x1] - Radius of cylinder for the Fixed part of the struts [m]
|
||
% - Msm [1x1] - Mass of the Mobile part of the struts [kg]
|
||
% - Msh [1x1] - Height of cylinder for the Mobile part of the struts [m]
|
||
% - Msr [1x1] - Radius of cylinder for the Mobile part of the struts [m]
|
||
%
|
||
% Outputs:
|
||
% - stewart - updated Stewart structure with the added fields:
|
||
% - struts_F [struct] - structure with the following fields:
|
||
% - M [6x1] - Mass of the Fixed part of the struts [kg]
|
||
% - I [3x3x6] - Moment of Inertia for the Fixed part of the struts [kg*m^2]
|
||
% - H [6x1] - Height of cylinder for the Fixed part of the struts [m]
|
||
% - R [6x1] - Radius of cylinder for the Fixed part of the struts [m]
|
||
% - struts_M [struct] - structure with the following fields:
|
||
% - M [6x1] - Mass of the Mobile part of the struts [kg]
|
||
% - I [3x3x6] - Moment of Inertia for the Mobile part of the struts [kg*m^2]
|
||
% - H [6x1] - Height of cylinder for the Mobile part of the struts [m]
|
||
% - R [6x1] - Radius of cylinder for the Mobile part of the struts [m]
|
||
|
||
arguments
|
||
stewart
|
||
args.Fsm (1,1) double {mustBeNumeric, mustBePositive} = 0.1
|
||
args.Fsh (1,1) double {mustBeNumeric, mustBePositive} = 50e-3
|
||
args.Fsr (1,1) double {mustBeNumeric, mustBePositive} = 5e-3
|
||
args.Msm (1,1) double {mustBeNumeric, mustBePositive} = 0.1
|
||
args.Msh (1,1) double {mustBeNumeric, mustBePositive} = 50e-3
|
||
args.Msr (1,1) double {mustBeNumeric, mustBePositive} = 5e-3
|
||
end
|
||
|
||
stewart.struts_M.type = 1;
|
||
|
||
stewart.struts_M.M = args.Msm;
|
||
stewart.struts_M.R = args.Msr;
|
||
stewart.struts_M.H = args.Msh;
|
||
|
||
stewart.struts_F.type = 1;
|
||
|
||
stewart.struts_F.M = args.Fsm;
|
||
stewart.struts_F.R = args.Fsr;
|
||
stewart.struts_F.H = args.Fsh;
|
||
|
||
end
|
||
#+end_src
|
||
|
||
** =initializeJointDynamics=: Add Stiffness and Damping properties for spherical joints
|
||
|
||
#+begin_src matlab :tangle matlab/src/initializeJointDynamics.m :comments none :mkdirp yes :eval no
|
||
function [stewart] = initializeJointDynamics(stewart, args)
|
||
% initializeJointDynamics - Add Stiffness and Damping properties for the spherical joints
|
||
%
|
||
% Syntax: [stewart] = initializeJointDynamics(args)
|
||
%
|
||
% Inputs:
|
||
% - args - Structure with the following fields:
|
||
% - type_F - 'universal', 'spherical', 'universal_p', 'spherical_p'
|
||
% - type_M - 'universal', 'spherical', 'universal_p', 'spherical_p'
|
||
% - Kf_M [6x1] - Bending (Rx, Ry) Stiffness for each top joints [(N.m)/rad]
|
||
% - Kt_M [6x1] - Torsion (Rz) Stiffness for each top joints [(N.m)/rad]
|
||
% - Cf_M [6x1] - Bending (Rx, Ry) Damping of each top joint [(N.m)/(rad/s)]
|
||
% - Ct_M [6x1] - Torsion (Rz) Damping of each top joint [(N.m)/(rad/s)]
|
||
% - Kf_F [6x1] - Bending (Rx, Ry) Stiffness for each bottom joints [(N.m)/rad]
|
||
% - Kt_F [6x1] - Torsion (Rz) Stiffness for each bottom joints [(N.m)/rad]
|
||
% - Cf_F [6x1] - Bending (Rx, Ry) Damping of each bottom joint [(N.m)/(rad/s)]
|
||
% - Cf_F [6x1] - Torsion (Rz) Damping of each bottom joint [(N.m)/(rad/s)]
|
||
%
|
||
% Outputs:
|
||
% - stewart - updated Stewart structure with the added fields:
|
||
% - stewart.joints_F and stewart.joints_M:
|
||
% - type - 1 (universal), 2 (spherical), 3 (universal perfect), 4 (spherical perfect)
|
||
% - Kx, Ky, Kz [6x1] - Translation (Tx, Ty, Tz) Stiffness [N/m]
|
||
% - Kf [6x1] - Flexion (Rx, Ry) Stiffness [(N.m)/rad]
|
||
% - Kt [6x1] - Torsion (Rz) Stiffness [(N.m)/rad]
|
||
% - Cx, Cy, Cz [6x1] - Translation (Rx, Ry) Damping [N/(m/s)]
|
||
% - Cf [6x1] - Flexion (Rx, Ry) Damping [(N.m)/(rad/s)]
|
||
% - Cb [6x1] - Torsion (Rz) Damping [(N.m)/(rad/s)]
|
||
|
||
arguments
|
||
stewart
|
||
args.type_F char {mustBeMember(args.type_F,{'2dof', '3dof', '4dof', '6dof', 'flexible'})} = '2dof'
|
||
args.type_M char {mustBeMember(args.type_M,{'2dof', '3dof', '4dof', '6dof', 'flexible'})} = '3dof'
|
||
args.Kf_M (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
|
||
args.Cf_M (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
|
||
args.Kt_M (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
|
||
args.Ct_M (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
|
||
args.Kf_F (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
|
||
args.Cf_F (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
|
||
args.Kt_F (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
|
||
args.Ct_F (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
|
||
args.Ka_F (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
|
||
args.Ca_F (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
|
||
args.Kr_F (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
|
||
args.Cr_F (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
|
||
args.Ka_M (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
|
||
args.Ca_M (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
|
||
args.Kr_M (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
|
||
args.Cr_M (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
|
||
args.K_M double {mustBeNumeric} = zeros(6,6)
|
||
args.M_M double {mustBeNumeric} = zeros(6,6)
|
||
args.n_xyz_M double {mustBeNumeric} = zeros(2,3)
|
||
args.xi_M double {mustBeNumeric} = 0.1
|
||
args.step_file_M char {} = ''
|
||
args.K_F double {mustBeNumeric} = zeros(6,6)
|
||
args.M_F double {mustBeNumeric} = zeros(6,6)
|
||
args.n_xyz_F double {mustBeNumeric} = zeros(2,3)
|
||
args.xi_F double {mustBeNumeric} = 0.1
|
||
args.step_file_F char {} = ''
|
||
end
|
||
|
||
switch args.type_F
|
||
case '2dof'
|
||
stewart.joints_F.type = 1;
|
||
case '3dof'
|
||
stewart.joints_F.type = 2;
|
||
case '4dof'
|
||
stewart.joints_F.type = 3;
|
||
case '6dof'
|
||
stewart.joints_F.type = 4;
|
||
case 'flexible'
|
||
stewart.joints_F.type = 5;
|
||
otherwise
|
||
error("joints_F are not correctly defined")
|
||
end
|
||
|
||
switch args.type_M
|
||
case '2dof'
|
||
stewart.joints_M.type = 1;
|
||
case '3dof'
|
||
stewart.joints_M.type = 2;
|
||
case '4dof'
|
||
stewart.joints_M.type = 3;
|
||
case '6dof'
|
||
stewart.joints_M.type = 4;
|
||
case 'flexible'
|
||
stewart.joints_M.type = 5;
|
||
otherwise
|
||
error("joints_M are not correctly defined")
|
||
end
|
||
|
||
stewart.joints_M.Ka = args.Ka_M;
|
||
stewart.joints_M.Kr = args.Kr_M;
|
||
|
||
stewart.joints_F.Ka = args.Ka_F;
|
||
stewart.joints_F.Kr = args.Kr_F;
|
||
|
||
stewart.joints_M.Ca = args.Ca_M;
|
||
stewart.joints_M.Cr = args.Cr_M;
|
||
|
||
stewart.joints_F.Ca = args.Ca_F;
|
||
stewart.joints_F.Cr = args.Cr_F;
|
||
|
||
stewart.joints_M.Kf = args.Kf_M;
|
||
stewart.joints_M.Kt = args.Kt_M;
|
||
|
||
stewart.joints_F.Kf = args.Kf_F;
|
||
stewart.joints_F.Kt = args.Kt_F;
|
||
|
||
stewart.joints_M.Cf = args.Cf_M;
|
||
stewart.joints_M.Ct = args.Ct_M;
|
||
|
||
stewart.joints_F.Cf = args.Cf_F;
|
||
stewart.joints_F.Ct = args.Ct_F;
|
||
|
||
stewart.joints_F.M = args.M_F;
|
||
stewart.joints_F.K = args.K_F;
|
||
stewart.joints_F.n_xyz = args.n_xyz_F;
|
||
stewart.joints_F.xi = args.xi_F;
|
||
stewart.joints_F.xi = args.xi_F;
|
||
stewart.joints_F.step_file = args.step_file_F;
|
||
|
||
stewart.joints_M.M = args.M_M;
|
||
stewart.joints_M.K = args.K_M;
|
||
stewart.joints_M.n_xyz = args.n_xyz_M;
|
||
stewart.joints_M.xi = args.xi_M;
|
||
stewart.joints_M.step_file = args.step_file_M;
|
||
|
||
end
|
||
#+end_src
|
||
|
||
** =initializeSample=: Sample
|
||
|
||
#+begin_src matlab :tangle matlab/src/initializeSample.m :comments none :mkdirp yes :eval no
|
||
function [sample] = initializeSample(args)
|
||
|
||
arguments
|
||
args.type char {mustBeMember(args.type,{'none', 'cylindrical'})} = 'none'
|
||
args.H_offset (1,1) double {mustBeNumeric} = 0 % Vertical offset [m]
|
||
args.H (1,1) double {mustBeNumeric, mustBePositive} = 200e-3 % Height [m]
|
||
args.R (1,1) double {mustBeNumeric, mustBePositive} = 110e-3 % Radius [m]
|
||
args.m (1,1) double {mustBeNumeric, mustBePositive} = 1 % Mass [kg]
|
||
end
|
||
|
||
sample = struct();
|
||
|
||
switch args.type
|
||
case 'none'
|
||
sample.type = 0;
|
||
sample.m = 0;
|
||
case 'cylindrical'
|
||
sample.type = 1;
|
||
|
||
sample.H_offset = args.H_offset;
|
||
|
||
sample.H = args.H;
|
||
sample.R = args.R;
|
||
sample.m = args.m;
|
||
end
|
||
end
|
||
#+end_src
|
||
|
||
** =initializeController=: Initialize Controller
|
||
#+begin_src matlab :tangle matlab/src/initializeController.m :comments none :mkdirp yes :eval no
|
||
function [controller] = initializeController(args)
|
||
|
||
arguments
|
||
args.type char {mustBeMember(args.type,{'open-loop', 'iff'})} = 'open-loop'
|
||
end
|
||
|
||
controller = struct();
|
||
|
||
switch args.type
|
||
case 'open-loop'
|
||
controller.type = 1;
|
||
controller.name = 'Open-Loop';
|
||
case 'iff'
|
||
controller.type = 2;
|
||
controller.name = 'Decentralized Integral Force Feedback';
|
||
end
|
||
end
|
||
#+end_src
|
||
|
||
* Helping Functions :noexport:
|
||
** Initialize Path
|
||
#+NAME: m-init-path
|
||
#+BEGIN_SRC matlab
|
||
%% Path for functions, data and scripts
|
||
addpath('./matlab/mat/'); % Path for data
|
||
addpath('./matlab/src/'); % Path for functions
|
||
addpath('./matlab/subsystems/'); % Path for Subsystems Simulink files
|
||
addpath('./matlab/'); % Path for scripts
|
||
#+END_SRC
|
||
|
||
#+NAME: m-init-path-tangle
|
||
#+BEGIN_SRC matlab
|
||
%% Path for functions, data and scripts
|
||
addpath('./mat/'); % Path for data
|
||
addpath('./src/'); % Path for functions
|
||
addpath('./subsystems/'); % Path for Subsystems Simulink files
|
||
#+END_SRC
|
||
|
||
** Initialize Simscape Model
|
||
#+NAME: m-init-simscape
|
||
#+begin_src matlab
|
||
% Simulink Model name
|
||
mdl = 'nano_hexapod_model';
|
||
#+end_src
|
||
|
||
** Initialize other elements
|
||
#+NAME: m-init-other
|
||
#+BEGIN_SRC matlab
|
||
%% Colors for the figures
|
||
colors = colororder;
|
||
#+END_SRC
|