Initial commit

This commit is contained in:
2025-12-02 14:33:46 +01:00
commit 7f107550e7
74 changed files with 14910 additions and 0 deletions

2
.gitattributes vendored Normal file
View File

@@ -0,0 +1,2 @@
*.svg binary
*.html binary

258
.gitignore vendored Normal file
View File

@@ -0,0 +1,258 @@
ltximg/
slprj/
matlab/slprj/
*.slxc
# ============================================================
# ============================================================
# LATEX
# ============================================================
# ============================================================
## Core latex/pdflatex auxiliary files:
*.aux
*.lof
*.log
*.lot
*.fls
*.out
*.toc
*.fmt
*.fot
*.cb
*.cb2
.*.lb
## Intermediate documents:
*.dvi
*.xdv
*-converted-to.*
# these rules might exclude image files for figures etc.
# *.ps
# *.eps
# *.pdf
## Generated if empty string is given at "Please type another file name for output:"
.pdf
## Bibliography auxiliary files (bibtex/biblatex/biber):
*.bbl
*.bcf
*.blg
*-blx.aux
*-blx.bib
*.run.xml
## Build tool auxiliary files:
*.fdb_latexmk
*.synctex
*.synctex(busy)
*.synctex.gz
*.synctex.gz(busy)
*.pdfsync
## Build tool directories for auxiliary files
# latexrun
latex.out/
## Auxiliary and intermediate files from other packages:
# algorithms
*.alg
*.loa
# achemso
acs-*.bib
# amsthm
*.thm
# beamer
*.nav
*.pre
*.snm
*.vrb
# changes
*.soc
# cprotect
*.cpt
# elsarticle (documentclass of Elsevier journals)
*.spl
# endnotes
*.ent
# fixme
*.lox
# feynmf/feynmp
*.mf
*.mp
*.t[1-9]
*.t[1-9][0-9]
*.tfm
#(r)(e)ledmac/(r)(e)ledpar
*.end
*.?end
*.[1-9]
*.[1-9][0-9]
*.[1-9][0-9][0-9]
*.[1-9]R
*.[1-9][0-9]R
*.[1-9][0-9][0-9]R
*.eledsec[1-9]
*.eledsec[1-9]R
*.eledsec[1-9][0-9]
*.eledsec[1-9][0-9]R
*.eledsec[1-9][0-9][0-9]
*.eledsec[1-9][0-9][0-9]R
# glossaries
*.acn
*.acr
*.glg
*.glo
*.gls
*.glsdefs
# gnuplottex
*-gnuplottex-*
# gregoriotex
*.gaux
*.gtex
# htlatex
*.4ct
*.4tc
*.idv
*.lg
*.trc
*.xref
# hyperref
*.brf
# knitr
*-concordance.tex
# TODO Comment the next line if you want to keep your tikz graphics files
*.tikz
*-tikzDictionary
# listings
*.lol
# makeidx
*.idx
*.ilg
*.ind
*.ist
# minitoc
*.maf
*.mlf
*.mlt
*.mtc[0-9]*
*.slf[0-9]*
*.slt[0-9]*
*.stc[0-9]*
# minted
_minted*
*.pyg
# morewrites
*.mw
# nomencl
*.nlg
*.nlo
*.nls
# pax
*.pax
# pdfpcnotes
*.pdfpc
# sagetex
*.sagetex.sage
*.sagetex.py
*.sagetex.scmd
# scrwfile
*.wrt
# sympy
*.sout
*.sympy
sympy-plots-for-*.tex/
# pdfcomment
*.upa
*.upb
# pythontex
*.pytxcode
pythontex-files-*/
# thmtools
*.loe
# TikZ & PGF
*.dpth
*.md5
*.auxlock
# todonotes
*.tdo
# easy-todo
*.lod
# xmpincl
*.xmpi
# xindy
*.xdy
# xypic precompiled matrices
*.xyc
# endfloat
*.ttt
*.fff
# Latexian
TSWLatexianTemp*
## Editors:
# WinEdt
*.bak
*.sav
# Texpad
.texpadtmp
# LyX
*.lyx~
# Kile
*.backup
# KBibTeX
*~[0-9]*
# auto folder when using emacs and auctex
./auto/*
*.el
# expex forward references with \gathertags
*-tags.tex
# standalone packages
*.sta

113
.latexmkrc Normal file
View File

@@ -0,0 +1,113 @@
#!/bin/env perl
# Shebang is only to get syntax highlighting right across GitLab, GitHub and IDEs.
# This file is not meant to be run, but read by `latexmk`.
# ======================================================================================
# Perl `latexmk` configuration file
# ======================================================================================
# ======================================================================================
# PDF Generation/Building/Compilation
# ======================================================================================
@default_files=('delta-robot.tex');
# PDF-generating modes are:
# 1: pdflatex, as specified by $pdflatex variable (still largely in use)
# 2: postscript conversion, as specified by the $ps2pdf variable (useless)
# 3: dvi conversion, as specified by the $dvipdf variable (useless)
# 4: lualatex, as specified by the $lualatex variable (best)
# 5: xelatex, as specified by the $xelatex variable (second best)
$pdf_mode = 4;
# Treat undefined references and citations as well as multiply defined references as
# ERRORS instead of WARNINGS.
# This is only checked in the *last* run, since naturally, there are undefined references
# in initial runs.
# This setting is potentially annoying when debugging/editing, but highly desirable
# in the CI pipeline, where such a warning should result in a failed pipeline, since the
# final document is incomplete/corrupted.
#
# However, I could not eradicate all warnings, so that `latexmk` currently fails with
# this option enabled.
# Specifically, `microtype` fails together with `fontawesome`/`fontawesome5`, see:
# https://tex.stackexchange.com/a/547514/120853
# The fix in that answer did not help.
# Setting `verbose=silent` to mute `microtype` warnings did not work.
# Switching between `fontawesome` and `fontawesome5` did not help.
$warnings_as_errors = 0;
# Show used CPU time. Looks like: https://tex.stackexchange.com/a/312224/120853
$show_time = 0;
# Default is 5; we seem to need more owed to the complexity of the document.
# Actual documents probably don't need this many since they won't use all features,
# plus won't be compiling from cold each time.
$max_repeat=10;
# --shell-escape option (execution of code outside of latex) is required for the
#'svg' package.
# It converts raw SVG files to the PDF+PDF_TEX combo using InkScape.
#
# SyncTeX allows to jump between source (code) and output (PDF) in IDEs with support
# (many have it). A value of `1` is enabled (gzipped), `-1` is enabled but uncompressed,
# `0` is off.
# Testing in VSCode w/ LaTeX Workshop only worked for the compressed version.
# Adjust this as needed. Of course, only relevant for local use, no effect on a remote
# CI pipeline (except for slower compilation, probably).
#
# %O and %S will forward Options and the Source file, respectively, given to latexmk.
#
# `set_tex_cmds` applies to all *latex commands (latex, xelatex, lualatex, ...), so
# no need to specify these each. This allows to simply change `$pdf_mode` to get a
# different engine. Check if this works with `latexmk --commands`.
set_tex_cmds("--shell-escape -interaction=nonstopmode --synctex=1 %O %S");
# Use default pdf viewer
$pdf_update_method = 1;
$pdf_previewer = "zathura %O %S";
# option 2 is same as 1 (run biber when necessary), but also deletes the
# regeneratable bbl-file in a clenaup (`latexmk -c`). Do not use if original
# bib file is not available!
$bibtex_use = 2; # default: 1
# Change default `biber` call, help catch errors faster/clearer. See
# https://web.archive.org/web/20200526101657/https://www.semipol.de/2018/06/12/latex-best-practices.html#database-entries
$biber = "biber --validate-datamodel %O %S";
# Glossaries
add_cus_dep('glo', 'gls', 0, 'run_makeglossaries');
add_cus_dep('acn', 'acr', 0, 'run_makeglossaries');
sub run_makeglossaries {
if ( $silent ) {
system "makeglossaries -q -s '$_[0].ist' '$_[0]'";
}
else {
system "makeglossaries -s '$_[0].ist' '$_[0]'";
};
}
# ======================================================================================
# Auxiliary Files
# ======================================================================================
# Let latexmk know about generated files, so they can be used to detect if a
# rerun is required, or be deleted in a cleanup.
# loe: List of Examples (KOMAScript)
# lol: List of Listings (`listings` and `minted` packages)
# run.xml: biber runs
# glg: glossaries log
# glstex: generated from glossaries-extra
push @generated_exts, 'loe', 'lol', 'run.xml', 'glstex', 'glo', 'gls', 'glg', 'acn', 'acr', 'alg';
# Also delete the *.glstex files from package glossaries-extra. Problem is,
# that that package generates files of the form "basename-digit.glstex" if
# multiple glossaries are present. Latexmk looks for "basename.glstex" and so
# does not find those. For that purpose, use wildcard.
# Also delete files generated by gnuplot/pgfplots contour plots
# (.dat, .script, .table).
$clean_ext = "%R-*.glstex %R_contourtmp*.*";

889
delta-robot.html Normal file
View File

@@ -0,0 +1,889 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<!-- 2025-12-02 Tue 14:32 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>Delta Robot</title>
<meta name="author" content="Dehaeze Thomas" />
<meta name="generator" content="Org Mode" />
<link rel="stylesheet" type="text/css" href="https://research.tdehaeze.xyz/css/style.css"/>
<script type="text/javascript" src="https://research.tdehaeze.xyz/js/script.js"></script>
<script>
MathJax = {
svg: {
scale: 1,
fontCache: "global"
},
tex: {
tags: "%AUTONUMBER",
multlineWidth: "%MULTLINEWIDTH",
tagSide: "right",
macros: {bm: ["\\boldsymbol{#1}",1],},
tagIndent: ".8em"
}
};
</script>
<script id="MathJax-script" async
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js"></script>
</head>
<body>
<div id="org-div-home-and-up">
<a accesskey="h" href="../index.html"> UP </a>
|
<a accesskey="H" href="../index.html"> HOME </a>
</div><div id="content" class="content">
<h1 class="title">Delta Robot</h1>
<div id="table-of-contents" role="doc-toc">
<h2>Table of Contents</h2>
<div id="text-table-of-contents" role="doc-toc">
<ul>
<li><a href="#org9dbd6be">1. Geometry</a></li>
<li><a href="#org8130b11">2. Kinematics: Jacobian Matrix and Mobility</a></li>
<li><a href="#org4dd69f9">3. Kinematics: Degrees of Freedom</a></li>
<li><a href="#org25e6eb0">4. Kinematics: Number of modes</a></li>
<li><a href="#org494f6d0">5. Flexible Joint Design</a>
<ul>
<li><a href="#org4834fcb">5.1. Studied Geometry</a></li>
<li><a href="#orgcf04565">5.2. Stiffness seen by the actuator</a></li>
<li><a href="#org8e8af24">5.3. Bending Stiffness</a></li>
<li><a href="#org6d455b1">5.4. Axial Stiffness</a></li>
<li><a href="#orgd75f092">5.5. Torsional Stiffness</a></li>
<li><a href="#org9700eaf">5.6. Shear Stiffness</a></li>
<li><a href="#orgbed5ca4">5.7. Effect of cube&rsquo;s size</a>
<ul>
<li><a href="#org531ae45">5.7.1. Effect on the plant dynamics</a></li>
<li><a href="#org9a49c2b">5.7.2. Effect on the compliance</a></li>
</ul>
</li>
<li><a href="#org14884a8">5.8. Effect of the strut length ?</a>
<ul>
<li><a href="#orgea1bcc5">5.8.1. Effect on the plant dynamics</a></li>
<li><a href="#orga760c24">5.8.2. Effect on the compliance</a></li>
</ul>
</li>
<li><a href="#org1693b06">5.9. Having the Center of Mass at the cube&rsquo;s center</a></li>
<li><a href="#org9065437">5.10. Conclusion</a></li>
</ul>
</li>
<li><a href="#org41e56de">6. Conclusion</a></li>
</ul>
</div>
</div>
<p>
<a id="org2b67556"></a>
</p>
<div id="outline-container-org9dbd6be" class="outline-2">
<h2 id="org9dbd6be"><span class="section-number-2">1.</span> Geometry</h2>
<div class="outline-text-2" id="text-1">
<p>
The Delta Robot geometry is defined as shown in Figure <a href="ref:fig:delta_robot_schematic">ref:fig:delta_robot_schematic</a>.
</p>
<p>
The geometry is fully defined by three parameters:
</p>
<ul class="org-ul">
<li><code>d</code>: Cube&rsquo;s size (i.e., the length of the cube edge)</li>
<li><code>a</code>: Distance from cube&rsquo;s vertex to top flexible joint</li>
<li><code>L</code>: Distance between two flexible joints (i.e., the length of the struts)</li>
</ul>
<div id="orgf0c5783" class="figure">
<p><img src="figs/delta_robot_schematic.png" alt="delta_robot_schematic.png" />
</p>
<p><span class="figure-number">Figure 1: </span>Schematic of the Delta Robot</p>
</div>
<p>
Several frames are defined:
</p>
<ul class="org-ul">
<li>\(\{C\}\): Cube&rsquo;s center</li>
<li>\(\{M\}\): Frame attached to the mobile platform, and located at the height of the top flexible joints</li>
<li>\(\{F\}\): Frame attached to the fixed platform, and located at the height of the bottom flexible joints</li>
</ul>
<p>
Several points are defined:
</p>
<ul class="org-ul">
<li>\(c_i\): vertices of the cubes which are relevant for the Delta Robot</li>
<li>\(b_i\): location of the top flexible joints</li>
<li>\(a_i\): location of the bottom flexible joints</li>
<li>\(\hat{s}_i\): unit vector aligned with the struts</li>
</ul>
<p>
Static properties:
</p>
<ul class="org-ul">
<li>All top and bottom flexible joints are identical.
The following properties can be specified:
<ul class="org-ul">
<li>\(k_a\): Axial stiffness</li>
<li>\(k_r\): Radial stiffness</li>
<li>\(k_b\): Bending stiffness</li>
<li>\(k_t\): Torsion stiffness</li>
</ul></li>
<li>The guiding mechanism of the actuator is here supposed to be perfect (i.e. 1dof system without any stiffness)</li>
<li>The Actuator is modelled as a 1DoF or 2DoF (good to model APA):
<ul class="org-ul">
<li>The custom developed APA has an axial stiffness of \(1.3\,N/\mu m\)</li>
</ul></li>
</ul>
<p>
Dynamical properties:
</p>
<ul class="org-ul">
<li>Top platform inertia:
It has a mass of ~300g</li>
<li>Payloads: payloads can weight up to 1kg</li>
</ul>
<p>
Let&rsquo;s initialize a Delta Robot architecture, and plot the obtained geometry (Figures <a href="ref:fig:delta_robot_architecture">ref:fig:delta_robot_architecture</a> and <a href="ref:fig:delta_robot_architecture_top">ref:fig:delta_robot_architecture_top</a>).
</p>
<div id="org31ec0d3" class="figure">
<p><img src="figs/delta_robot_architecture.png" alt="delta_robot_architecture.png" />
</p>
<p><span class="figure-number">Figure 2: </span>Delta Robot Architecture</p>
</div>
<div id="org80c1e20" class="figure">
<p><img src="figs/delta_robot_architecture_top.png" alt="delta_robot_architecture_top.png" />
</p>
<p><span class="figure-number">Figure 3: </span>Delta Robot Architecture - Top View</p>
</div>
</div>
</div>
<div id="outline-container-org8130b11" class="outline-2">
<h2 id="org8130b11"><span class="section-number-2">2.</span> Kinematics: Jacobian Matrix and Mobility</h2>
<div class="outline-text-2" id="text-2">
<p>
Jacobian matrix between actuator displacement and top platform displacement.
</p>
<p>
There are three actuators in the following directions \(\hat{s}_1\), \(\hat{s}_2\) and \(\hat{s}_3\);
</p>
\begin{equation}\label{eq:detail_kinematics_cubic_s}
\hat{\bm{s}}_1 = \begin{bmatrix} \frac{-1}{\sqrt{6}} \\ \frac{-1}{\sqrt{2}} \\ \frac{1}{\sqrt{3}} \end{bmatrix} \quad
\hat{\bm{s}}_2 = \begin{bmatrix} \frac{\sqrt{2}}{\sqrt{3}} \\ 0 \\ \frac{1}{\sqrt{3}} \end{bmatrix} \quad
\hat{\bm{s}}_3 = \begin{bmatrix} \frac{-1}{\sqrt{6}} \\ \frac{ 1}{\sqrt{2}} \\ \frac{1}{\sqrt{3}} \end{bmatrix}
\end{equation}
\begin{equation}
\bm{J} = \begin{bmatrix}
\hat{\bm{s}}_1^T \\ \hat{\bm{s}}_2^T \\ \hat{\bm{s}}_3^T
\end{bmatrix}
\end{equation}
\begin{equation}
d\mathcal{L} = J d\mathcal{L}
\end{equation}
\begin{equation}
d\mathcal{X} = J^{-1} d\mathcal{L}
\end{equation}
<p>
The achievable workspace is a cube whose edge length is equal to the actuator stroke.
</p>
<div id="org7052783" class="figure">
<p><img src="figs/delta_robot_3d_workspace.png" alt="delta_robot_3d_workspace.png" />
</p>
<p><span class="figure-number">Figure 4: </span>3D workspace</p>
</div>
<p>
As most likely, the system will be used to perform YZ scans, it is interesting to see the mobility of the system in the ZY plane.
</p>
<p>
Depending on how the YZ plane is oriented (i.e., depending on the Rz angle of the delta robot with respect to the beam, defining the x direction), we get different mobility.
</p>
<div id="org40b9c06" class="figure">
<p><img src="figs/delta_robot_2d_workspace.png" alt="delta_robot_2d_workspace.png" />
</p>
<p><span class="figure-number">Figure 5: </span>2D mobility for different orientations</p>
</div>
<pre class="example">
Maximum YZ mobility for an angle of 270 degrees, square with edge size of 117 um
</pre>
<div id="org02a87d6" class="figure">
<p><img src="figs/delta_robot_2d_workspace_optimal.png" alt="delta_robot_2d_workspace_optimal.png" />
</p>
<p><span class="figure-number">Figure 6: </span>2D mobility for the optimal Rz angle</p>
</div>
</div>
</div>
<div id="outline-container-org4dd69f9" class="outline-2">
<h2 id="org4dd69f9"><span class="section-number-2">3.</span> Kinematics: Degrees of Freedom</h2>
<div class="outline-text-2" id="text-3">
<p>
In the perfect case (flexible joints having no stiffness in bending, and infinite stiffness in torsion and in the axial direction), the top platform is allowed to move only in the X, Y and Z directions while the three rotations are fixed.
</p>
<p>
In order to have some compliance in rotation, the flexible joints need to have some compliance in torsion <b>and</b> in the axial direction.
If only the torsional compliance is considered, or only the axial compliance, the top platform will still not be able to do any rotation.
</p>
<p>
This is shown below with the Simscape model:
</p>
<p>
Perfect Delta Robot:
</p>
<ul class="org-ul">
<li>infinite axial stiffness</li>
<li>infinite torsional stiffness</li>
<li>no bending stiffness</li>
</ul>
<p>
It gives infinite stiffness in rotations, and a stiffness of \(1\,N/\mu m\) in X, Y and Z directions (i.e. equal to the actuator stiffness).
</p>
<pre class="example">
Stiffness in X,Y and Z directions: 1.0 N/um
</pre>
<p>
If we consider the torsion of the flexible joints:
</p>
<ul class="org-ul">
<li>infinite axial stiffness</li>
<li>finite torsional stiffness</li>
<li>no bending stiffness</li>
</ul>
<p>
We get the same result.
</p>
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
<colgroup>
<col class="org-right" />
<col class="org-right" />
<col class="org-right" />
<col class="org-right" />
<col class="org-right" />
<col class="org-right" />
</colgroup>
<tbody>
<tr>
<td class="org-right">1.00000000008084e-06</td>
<td class="org-right">5.61161767954149e-17</td>
<td class="org-right">1.71532908969278e-16</td>
<td class="org-right">-5.07840362381474e-20</td>
<td class="org-right">6.66481298362927e-20</td>
<td class="org-right">-2.97485996797085e-20</td>
</tr>
<tr>
<td class="org-right">9.44550093013109e-17</td>
<td class="org-right">9.99999999981042e-07</td>
<td class="org-right">-1.31365181854596e-16</td>
<td class="org-right">2.20736442292089e-20</td>
<td class="org-right">-8.27761658859861e-20</td>
<td class="org-right">-5.51841106039072e-20</td>
</tr>
<tr>
<td class="org-right">1.5172479677791e-16</td>
<td class="org-right">7.57916759433382e-18</td>
<td class="org-right">9.9999999983089e-07</td>
<td class="org-right">2.71965732539802e-20</td>
<td class="org-right">-5.0088900526952e-21</td>
<td class="org-right">4.20708731166142e-20</td>
</tr>
<tr>
<td class="org-right">3.7990974483635e-15</td>
<td class="org-right">-1.49195278352597e-15</td>
<td class="org-right">1.09166051384021e-15</td>
<td class="org-right">-4.60992688885629e-28</td>
<td class="org-right">4.46894514064728e-28</td>
<td class="org-right">-6.04202812027976e-29</td>
</tr>
<tr>
<td class="org-right">1.92223678174906e-15</td>
<td class="org-right">3.62267008376981e-15</td>
<td class="org-right">-5.42452104276465e-15</td>
<td class="org-right">3.7737029650938e-28</td>
<td class="org-right">-2.99601307180469e-28</td>
<td class="org-right">-3.30297132145485e-28</td>
</tr>
<tr>
<td class="org-right">3.79407058351761e-16</td>
<td class="org-right">-3.46944690994006e-17</td>
<td class="org-right">9.05659407516431e-16</td>
<td class="org-right">-1.33615244419949e-28</td>
<td class="org-right">6.31115609464934e-29</td>
<td class="org-right">-1.07596265815569e-29</td>
</tr>
</tbody>
</table>
<p>
If we consider the axial of the flexible joints:
</p>
<ul class="org-ul">
<li>finite axial stiffness</li>
<li>infinite torsional stiffness</li>
<li>no bending stiffness</li>
</ul>
<p>
We get the same result.
</p>
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
<colgroup>
<col class="org-right" />
<col class="org-right" />
<col class="org-right" />
<col class="org-right" />
<col class="org-right" />
<col class="org-right" />
</colgroup>
<tbody>
<tr>
<td class="org-right">1.0100082922792e-06</td>
<td class="org-right">-8.23544084894984e-12</td>
<td class="org-right">-1.12982601885747e-11</td>
<td class="org-right">-1.30123733161505e-19</td>
<td class="org-right">3.61079565098929e-21</td>
<td class="org-right">-2.56479299609534e-20</td>
</tr>
<tr>
<td class="org-right">-8.23691147427908e-12</td>
<td class="org-right">1.01002426764947e-06</td>
<td class="org-right">1.16488393394949e-11</td>
<td class="org-right">-9.17271935353013e-20</td>
<td class="org-right">-1.39093131659514e-20</td>
<td class="org-right">-8.92049690205949e-21</td>
</tr>
<tr>
<td class="org-right">-1.12984563170605e-11</td>
<td class="org-right">1.1646579416975e-11</td>
<td class="org-right">1.01001628184113e-06</td>
<td class="org-right">-1.2624013403036e-19</td>
<td class="org-right">-4.41063676650963e-22</td>
<td class="org-right">2.01282903077792e-20</td>
</tr>
<tr>
<td class="org-right">3.25566266033832e-16</td>
<td class="org-right">7.02470264849632e-18</td>
<td class="org-right">1.34879235410707e-17</td>
<td class="org-right">-4.42814771779206e-29</td>
<td class="org-right">1.06332319737688e-30</td>
<td class="org-right">-8.04051214064698e-30</td>
</tr>
<tr>
<td class="org-right">-2.34669385520782e-15</td>
<td class="org-right">1.03658500184429e-16</td>
<td class="org-right">2.10026418149746e-15</td>
<td class="org-right">3.04125606965025e-29</td>
<td class="org-right">-1.07347740796227e-29</td>
<td class="org-right">1.00530401393662e-28</td>
</tr>
<tr>
<td class="org-right">-2.76788049700945e-16</td>
<td class="org-right">-3.49174266014038e-17</td>
<td class="org-right">1.36253386200494e-15</td>
<td class="org-right">-1.31490052587614e-28</td>
<td class="org-right">-1.10493913866777e-30</td>
<td class="org-right">3.45058758900066e-29</td>
</tr>
</tbody>
</table>
<p>
No we consider both finite torsional stiffness and finite axial stiffness.
In that case we get some compliance in rotation.
So it is a combination of axial and torsion stiffness that gives some rotational stiffness of the top platform.
</p>
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
<colgroup>
<col class="org-right" />
<col class="org-right" />
<col class="org-right" />
<col class="org-right" />
<col class="org-right" />
<col class="org-right" />
</colgroup>
<tbody>
<tr>
<td class="org-right">1.01000347398415e-06</td>
<td class="org-right">1.08760660507374e-12</td>
<td class="org-right">6.48998902114602e-12</td>
<td class="org-right">-1.68758827983914e-12</td>
<td class="org-right">2.72734564017018e-12</td>
<td class="org-right">-1.13327901508316e-12</td>
</tr>
<tr>
<td class="org-right">-1.7269667100718e-13</td>
<td class="org-right">1.01000152837256e-06</td>
<td class="org-right">4.09018170284123e-13</td>
<td class="org-right">-9.80286569772779e-13</td>
<td class="org-right">-9.94629340226498e-13</td>
<td class="org-right">8.3468855003368e-13</td>
</tr>
<tr>
<td class="org-right">5.40707734744154e-12</td>
<td class="org-right">-1.46859567258244e-12</td>
<td class="org-right">1.0099981133678e-06</td>
<td class="org-right">3.34755457607493e-12</td>
<td class="org-right">-6.56764113866634e-12</td>
<td class="org-right">1.26237249518737e-12</td>
</tr>
<tr>
<td class="org-right">2.67935189951885e-13</td>
<td class="org-right">-6.64493555908236e-14</td>
<td class="org-right">7.44661955503977e-13</td>
<td class="org-right">1.59744415094004e-05</td>
<td class="org-right">-6.97585818773949e-13</td>
<td class="org-right">1.44845764745933e-13</td>
</tr>
<tr>
<td class="org-right">1.91880640934689e-14</td>
<td class="org-right">-1.31284160978049e-13</td>
<td class="org-right">-5.83827721443037e-13</td>
<td class="org-right">4.97550111979747e-13</td>
<td class="org-right">1.5974440506229e-05</td>
<td class="org-right">8.27388125221276e-14</td>
</tr>
<tr>
<td class="org-right">1.63302978397554e-14</td>
<td class="org-right">-6.29948151015302e-14</td>
<td class="org-right">1.11798835985125e-13</td>
<td class="org-right">-4.74438363934587e-14</td>
<td class="org-right">-1.39110944875938e-13</td>
<td class="org-right">3.99840072236264e-06</td>
</tr>
</tbody>
</table>
<p>
Therefore, to model some compliance of the top platform in rotation, both the axial compliance and the torsional compliance of the flexible joints should be considered.
</p>
</div>
</div>
<div id="outline-container-org25e6eb0" class="outline-2">
<h2 id="org25e6eb0"><span class="section-number-2">4.</span> Kinematics: Number of modes</h2>
<div class="outline-text-2" id="text-4">
<p>
In the perfect condition (i.e. infinite stiffness in torsion and in compression of the flexible joints), the system has 6 states (i.e. 3 modes, one for each DoF: X, Y and Z).
</p>
<p>
When considering some compliance in torsion of the flexible joints, 12 states are added (one internal mode of the struts).
To remove these internal states (that might not be interesting but that could slow the simulations), one of the joint can have this torsional compliance while the other can have the torsional DoF constrained.
</p>
<pre class="example">
State-space model with 3 outputs, 3 inputs, and 6 states.
</pre>
</div>
</div>
<div id="outline-container-org494f6d0" class="outline-2">
<h2 id="org494f6d0"><span class="section-number-2">5.</span> Flexible Joint Design</h2>
<div class="outline-text-2" id="text-5">
<p>
<a id="org1d3485b"></a>
</p>
<p>
The goal is to extract specifications for the flexible joints of the six struts.
</p>
<p>
The two most critical flexible joints imperfections are:
</p>
<ul class="org-ul">
<li>The axial stiffness, that should be high enough</li>
<li>The bending stiffness, that should be low enough</li>
</ul>
<p>
The shear and torsional stiffnesses are not foreseen to be very problematic, but their impact will be evaluated.
</p>
<p>
First, the dynamics of a &ldquo;perfect&rdquo; Delta-Robot is identified (i.e. with perfect 2DoF rotational joints).
</p>
<p>
Then, the impact of the flexible joint&rsquo;s imperfections will be studied.
</p>
</div>
<div id="outline-container-org4834fcb" class="outline-3">
<h3 id="org4834fcb"><span class="section-number-3">5.1.</span> Studied Geometry</h3>
<div class="outline-text-3" id="text-5-1">
<p>
The cube&rsquo;s edge length is equal to 50mm, the distance between cube&rsquo;s vertices and top joints is 20mm and the length of the struts (i.e. the distance between the two flexible joints of the same strut) is 50mm.
The actuator stiffness is \(1\,N/\mu m\).
</p>
<p>
The obtained geometry is shown in Figure <a href="ref:fig:delta_robot_studied_geometry">ref:fig:delta_robot_studied_geometry</a>.
</p>
<div id="org0edf7cb" class="figure">
<p><img src="figs/delta_robot_studied_geometry.png" alt="delta_robot_studied_geometry.png" />
</p>
<p><span class="figure-number">Figure 7: </span>Geometry of the studied Delta Robot</p>
</div>
<p>
The dynamics is first identified in perfect conditions (infinite axial stiffness of the joints, zero bending stiffness).
We get <code>State-space model with 3 outputs, 3 inputs, and 6 states.</code>
We get a perfectly decoupled system, with three identical modes in the X, Y and Z directions.
The dynamics is shown in Figure <a href="ref:fig:delta_robot_dynamics_perfect">ref:fig:delta_robot_dynamics_perfect</a>.
</p>
<div id="org0ef4cae" class="figure">
<p><img src="figs/delta_robot_dynamics_perfect.png" alt="delta_robot_dynamics_perfect.png" />
</p>
<p><span class="figure-number">Figure 8: </span>Dynamics of the delta robot with perfect joints</p>
</div>
</div>
</div>
<div id="outline-container-orgcf04565" class="outline-3">
<h3 id="orgcf04565"><span class="section-number-3">5.2.</span> Stiffness seen by the actuator</h3>
<div class="outline-text-3" id="text-5-2">
<p>
Because the flexible joints will have some bending stiffness, the actuator in one direction will &ldquo;see&rdquo; some stiffness due to the struts in the other directions.
This will limit its effective stroke.
We want this parallel stiffness to be much smaller than the stiffness of the actuator.
</p>
<p>
The parallel stiffness seen by the actuator as a function of the bending stiffness of the flexible joints is computed and shown in Figure <a href="ref:fig:delta_robot_bending_stiffness_parallel_k">ref:fig:delta_robot_bending_stiffness_parallel_k</a>.
</p>
<div id="orgef85bd9" class="figure">
<p><img src="figs/delta_robot_bending_stiffness_parallel_k.png" alt="delta_robot_bending_stiffness_parallel_k.png" />
</p>
<p><span class="figure-number">Figure 9: </span>Effect of the bending stiffness of the flexible joints on the stiffness seen by the actuators</p>
</div>
<p>
The parallel stiffness is therefore proportional to the bending stiffness.
The &ldquo;linear coefficient&rdquo; depend on the geometry, and it is here equal to \(3200 \frac{N/m}{Nm/\text{rad}}\).
</p>
<p>
If we want the parallel stiffness to be much smaller than the stiffness of the actuator (\(k_p \ll k_a = 1.6\,N/\mu m\)), the bending stiffness should be \(\ll 500\,Nm/\text{rad}\).
Therefore, we should aim at \(k_f < 50\,Nm/\text{rad}\).
</p>
<p>
This should be validated with the final geometry.
</p>
</div>
</div>
<div id="outline-container-org8e8af24" class="outline-3">
<h3 id="org8e8af24"><span class="section-number-3">5.3.</span> Bending Stiffness</h3>
<div class="outline-text-3" id="text-5-3">
<p>
Then, the dynamics is identified for a bending Stiffness of \(50\,Nm/\text{rad}\) and compared with a Delta robot with no bending stiffness in Figure <a href="ref:fig:delta_robot_bending_stiffness_dynamics">ref:fig:delta_robot_bending_stiffness_dynamics</a>.
</p>
<p>
It can be seen that the DC gain is a bit lower when the bending stiffness is considered and the resonance frequency is increased.
This simply means that the system stiffness is increased.
It is not critical from a dynamical point of view, it just decreases the achievable stroke as explained in the previous section.
</p>
<div id="org3b5ebdd" class="figure">
<p><img src="figs/delta_robot_bending_stiffness_dynamics.png" alt="delta_robot_bending_stiffness_dynamics.png" />
</p>
<p><span class="figure-number">Figure 10: </span>Effect of the bending stiffness on the dynamics</p>
</div>
</div>
</div>
<div id="outline-container-org6d455b1" class="outline-3">
<h3 id="org6d455b1"><span class="section-number-3">5.4.</span> Axial Stiffness</h3>
<div class="outline-text-3" id="text-5-4">
<p>
Now, the effect of the axial stiffness on the dynamics is studied (Figure <a href="ref:fig:delta_robot_axial_stiffness_dynamics">ref:fig:delta_robot_axial_stiffness_dynamics</a>).
Additional modes can be observed on the plant dynamics, which could limit the achievable bandwidth.
Therefore the axial stiffness should be maximized.
Having the axial stiffness 100 times stiffer than the actuator stiffness seems reasonable.
Therefore, we should aim at \(k_a > 100\,N/\mu m\).
</p>
<div id="org1f7d588" class="figure">
<p><img src="figs/delta_robot_axial_stiffness_dynamics.png" alt="delta_robot_axial_stiffness_dynamics.png" />
</p>
<p><span class="figure-number">Figure 11: </span>Effect of the joint&rsquo;s axial stiffness on the plant dynamics</p>
</div>
</div>
</div>
<div id="outline-container-orgd75f092" class="outline-3">
<h3 id="orgd75f092"><span class="section-number-3">5.5.</span> Torsional Stiffness</h3>
<div class="outline-text-3" id="text-5-5">
<p>
Now the compliance in torsion of the flexible joints is considered.
</p>
<p>
If we look at the compliance of the delta robot in rotation as a function of the torsional stiffness of the flexible joints (Figure <a href="ref:fig:delta_robot_kt_compliance">ref:fig:delta_robot_kt_compliance</a>), we see almost no effect: the system is not made more stiff by increasing the torsional stiffness of the joints.
</p>
<div id="orgfec2a22" class="figure">
<p><img src="figs/delta_robot_kt_compliance.png" alt="delta_robot_kt_compliance.png" />
</p>
<p><span class="figure-number">Figure 12: </span>Effect of the joint&rsquo;s torsional stiffness on the Delta Robot compliance</p>
</div>
<p>
If we have a look at the effect of the torsional stiffness on the plant dynamics (Figure <a href="ref:fig:delta_robot_kt_dynamics">ref:fig:delta_robot_kt_dynamics</a>), we see almost no effect, except when super high values are reached (\(10^6\,Nm/\text{rad}\)), which are unrealistic.
</p>
<div id="org919b485" class="figure">
<p><img src="figs/delta_robot_kt_dynamics.png" alt="delta_robot_kt_dynamics.png" />
</p>
<p><span class="figure-number">Figure 13: </span>Effect of the joint&rsquo;s torsional stiffness on the Delta Robot plant dynamics</p>
</div>
<p>
Therefore, the torsional stiffness is not a super important metric for the design of the delta robot.
</p>
</div>
</div>
<div id="outline-container-org9700eaf" class="outline-3">
<h3 id="org9700eaf"><span class="section-number-3">5.6.</span> Shear Stiffness</h3>
<div class="outline-text-3" id="text-5-6">
<p>
As shown in Figure <a href="ref:fig:delta_robot_shear_stiffness_compliance">ref:fig:delta_robot_shear_stiffness_compliance</a>, the shear stiffness of the flexible joints has some effect on the compliance in translation and almost no effect on the compliance in rotation.
</p>
<p>
This is quite logical, and so the shear stiffness should be maximized.
A value of \(100\,N/\mu m\) seems reasonable.
</p>
<div id="org47b9f27" class="figure">
<p><img src="figs/delta_robot_shear_stiffness_compliance.png" alt="delta_robot_shear_stiffness_compliance.png" />
</p>
<p><span class="figure-number">Figure 14: </span>Effect of the shear stiffness of the flexible joints on the Delta Robot compliance</p>
</div>
</div>
</div>
<div id="outline-container-orgbed5ca4" class="outline-3">
<h3 id="orgbed5ca4"><span class="section-number-3">5.7.</span> Effect of cube&rsquo;s size</h3>
<div class="outline-text-3" id="text-5-7">
<p>
Let&rsquo;s choose reasonable values for the flexible joints:
</p>
<ul class="org-ul">
<li>Bending stiffness of 50Nm/rad</li>
<li>Torsional stiffness of 500Nm/rad</li>
<li>Axial stiffness of 100N/um</li>
<li>Shear stiffness of 100N/um</li>
</ul>
<p>
And we see the effect of changing the cube&rsquo;s size.
</p>
</div>
<div id="outline-container-org531ae45" class="outline-4">
<h4 id="org531ae45"><span class="section-number-4">5.7.1.</span> Effect on the plant dynamics</h4>
<div class="outline-text-4" id="text-5-7-1">
<ul class="org-ul">
<li class="off"><code>[&#xa0;]</code> <b>Understand why such different dynamics between 3dof_a joints and 6dof joints with very high shear stiffnesses</b></li>
</ul>
<p>
The effect of the cube&rsquo;s size on the plant dynamics is shown in Figure <a href="ref:fig:delta_robot_cube_size_plant_dynamics">ref:fig:delta_robot_cube_size_plant_dynamics</a>:
</p>
<ul class="org-ul">
<li>coupling decreases with the cube&rsquo;s size</li>
<li>one resonance frequency increases with the cube&rsquo;s size (resonances in rotation), which may be beneficial from a control point of view</li>
<li>coupling at the main resonance varies with the cube&rsquo;s size, but it may also depend on the relative position between the CoM and the cube&rsquo;s center</li>
</ul>
<div id="org55507e2" class="figure">
<p><img src="figs/delta_robot_cube_size_plant_dynamics.png" alt="delta_robot_cube_size_plant_dynamics.png" />
</p>
<p><span class="figure-number">Figure 15: </span>Effect of the cube&rsquo;s size on the plant dynamics</p>
</div>
</div>
</div>
<div id="outline-container-org9a49c2b" class="outline-4">
<h4 id="org9a49c2b"><span class="section-number-4">5.7.2.</span> Effect on the compliance</h4>
<div class="outline-text-4" id="text-5-7-2">
<p>
As shown in Figure <a href="ref:fig:delta_robot_cube_size_compliance_rotation">ref:fig:delta_robot_cube_size_compliance_rotation</a>, the stiffness of the delta robot in rotation increases with the cube&rsquo;s size.
</p>
<div id="org6c387e6" class="figure">
<p><img src="figs/delta_robot_cube_size_compliance_rotation.png" alt="delta_robot_cube_size_compliance_rotation.png" />
</p>
<p><span class="figure-number">Figure 16: </span>Effect of the cube&rsquo;s size on the rotational compliance of the top platform</p>
</div>
<p>
With a cube size of 50mm, the resonance frequency is already above 1kHz with seems reasonable.
</p>
</div>
</div>
</div>
<div id="outline-container-org14884a8" class="outline-3">
<h3 id="org14884a8"><span class="section-number-3">5.8.</span> Effect of the strut length ?</h3>
<div class="outline-text-3" id="text-5-8">
<p>
Let&rsquo;s choose reasonable values for the flexible joints:
</p>
<ul class="org-ul">
<li>Bending stiffness of 50Nm/rad</li>
<li>Torsional stiffness of 500Nm/rad</li>
<li>Axial stiffness of 100N/um</li>
</ul>
<p>
And we see the effect of changing the strut length.
</p>
</div>
<div id="outline-container-orgea1bcc5" class="outline-4">
<h4 id="orgea1bcc5"><span class="section-number-4">5.8.1.</span> Effect on the plant dynamics</h4>
<div class="outline-text-4" id="text-5-8-1">
<p>
As shown in Figure <a href="ref:fig:delta_robot_strut_length_plant_dynamics">ref:fig:delta_robot_strut_length_plant_dynamics</a>, having longer struts:
</p>
<ul class="org-ul">
<li>decreases the main resonance frequency: this means that the stiffness in the X,Y and Z directions is decreased when the length of the strut is longer.
This is reasonable as the &ldquo;lever&rdquo; arm is getting larger, so the bending stiffness and compression of the flexible joints have a larger effect on the top platform compliance.</li>
<li>decreases the low frequency coupling: this effect is more difficult to physically understand</li>
</ul>
<p>
But even with relatively short struts (20mm and above), the low frequency decoupling is already around two orders of magnitude, which is enough from a control point of view.
So, the struts length can be optimized to not decrease too much the stiffness of the platform while still getting good low frequency decoupling.
</p>
<div id="org52ddd53" class="figure">
<p><img src="figs/delta_robot_strut_length_plant_dynamics.png" alt="delta_robot_strut_length_plant_dynamics.png" />
</p>
<p><span class="figure-number">Figure 17: </span>Effect of the cube&rsquo;s size on the plant dynamics</p>
</div>
</div>
</div>
<div id="outline-container-orga760c24" class="outline-4">
<h4 id="orga760c24"><span class="section-number-4">5.8.2.</span> Effect on the compliance</h4>
<div class="outline-text-4" id="text-5-8-2">
<p>
As shown in Figure <a href="ref:fig:delta_robot_strut_length_compliance_rotation">ref:fig:delta_robot_strut_length_compliance_rotation</a>, the strut length has an effect on the system stiffness in translation (left plot) but almost not in rotation (right plot).
</p>
<div id="org170bf64" class="figure">
<p><img src="figs/delta_robot_strut_length_compliance_rotation.png" alt="delta_robot_strut_length_compliance_rotation.png" />
</p>
<p><span class="figure-number">Figure 18: </span>Effect of the cube&rsquo;s size on the rotational compliance of the top platform</p>
</div>
</div>
</div>
</div>
<div id="outline-container-org1693b06" class="outline-3">
<h3 id="org1693b06"><span class="section-number-3">5.9.</span> Having the Center of Mass at the cube&rsquo;s center</h3>
<div class="outline-text-3" id="text-5-9">
<p>
To make things easier, we take a top platform with no mass, mass-less struts, and we put a payload on top of the platform.
</p>
<p>
As shown in Figure <a href="ref:fig:delta_robot_CoM_pos_effect_plant">ref:fig:delta_robot_CoM_pos_effect_plant</a>, having the CoM of the payload at the cube&rsquo;s center allow to have better decoupling properties above the suspension mode of the system (i.e. above the first mode).
This could allow to have a bandwidth exceeding the frequency of the first mode.
But how sensitive this decoupling is to the exact position of the CoM still need to be studied.
</p>
<div id="orgab013d8" class="figure">
<p><img src="figs/delta_robot_CoM_pos_effect_plant.png" alt="delta_robot_CoM_pos_effect_plant.png" />
</p>
<p><span class="figure-number">Figure 19: </span>Effect of the payload&rsquo;s Center of Mass position with respect to the cube&rsquo;s size on the plant dynamics</p>
</div>
</div>
</div>
<div id="outline-container-org9065437" class="outline-3">
<h3 id="org9065437"><span class="section-number-3">5.10.</span> Conclusion</h3>
</div>
</div>
<div id="outline-container-org41e56de" class="outline-2">
<h2 id="org41e56de"><span class="section-number-2">6.</span> Conclusion</h2>
</div>
</div>
<div id="postamble" class="status">
<p class="author">Author: Dehaeze Thomas</p>
<p class="date">Created: 2025-12-02 Tue 14:32</p>
</div>
</body>
</html>

2638
delta-robot.org Normal file

File diff suppressed because it is too large Load Diff

BIN
delta-robot.pdf Normal file

Binary file not shown.

457
delta-robot.tex Normal file
View File

@@ -0,0 +1,457 @@
% Created 2025-12-02 Tue 14:32
% Intended LaTeX compiler: pdflatex
\documentclass[a4paper, 10pt, DIV=12, parskip=full, bibliography=totoc]{scrreprt}
\input{preamble.tex}
\input{preamble_extra.tex}
\author{Dehaeze Thomas}
\date{\today}
\title{Delta Robot}
\hypersetup{
pdfauthor={Dehaeze Thomas},
pdftitle={Delta Robot},
pdfkeywords={},
pdfsubject={},
pdfcreator={Emacs 30.2 (Org mode 9.7.34)},
pdflang={English}}
\usepackage{biblatex}
\begin{document}
\maketitle
\tableofcontents
\clearpage
\label{sec:delta_robot_introduction}
\chapter{Geometry}
The Delta Robot geometry is defined as shown in Figure \ref{fig:delta_robot_schematic}.
The geometry is fully defined by three parameters:
\begin{itemize}
\item \texttt{d}: Cube's size (i.e., the length of the cube edge)
\item \texttt{a}: Distance from cube's vertex to top flexible joint
\item \texttt{L}: Distance between two flexible joints (i.e., the length of the struts)
\end{itemize}
\begin{figure}[htbp]
\centering
\includegraphics[scale=1]{figs/delta_robot_schematic.png}
\caption{\label{fig:delta_robot_schematic}Schematic of the Delta Robot}
\end{figure}
Several frames are defined:
\begin{itemize}
\item \(\{C\}\): Cube's center
\item \(\{M\}\): Frame attached to the mobile platform, and located at the height of the top flexible joints
\item \(\{F\}\): Frame attached to the fixed platform, and located at the height of the bottom flexible joints
\end{itemize}
Several points are defined:
\begin{itemize}
\item \(c_i\): vertices of the cubes which are relevant for the Delta Robot
\item \(b_i\): location of the top flexible joints
\item \(a_i\): location of the bottom flexible joints
\item \(\hat{s}_i\): unit vector aligned with the struts
\end{itemize}
Static properties:
\begin{itemize}
\item All top and bottom flexible joints are identical.
The following properties can be specified:
\begin{itemize}
\item \(k_a\): Axial stiffness
\item \(k_r\): Radial stiffness
\item \(k_b\): Bending stiffness
\item \(k_t\): Torsion stiffness
\end{itemize}
\item The guiding mechanism of the actuator is here supposed to be perfect (i.e. 1dof system without any stiffness)
\item The Actuator is modelled as a 1DoF or 2DoF (good to model APA):
\begin{itemize}
\item The custom developed APA has an axial stiffness of \(1.3\,N/\mu m\)
\end{itemize}
\end{itemize}
Dynamical properties:
\begin{itemize}
\item Top platform inertia:
It has a mass of \textasciitilde{}300g
\item Payloads: payloads can weight up to 1kg
\end{itemize}
Let's initialize a Delta Robot architecture, and plot the obtained geometry (Figures \ref{fig:delta_robot_architecture} and \ref{fig:delta_robot_architecture_top}).
\begin{figure}[htbp]
\centering
\includegraphics[scale=1]{figs/delta_robot_architecture.png}
\caption{\label{fig:delta_robot_architecture}Delta Robot Architecture}
\end{figure}
\begin{figure}[htbp]
\centering
\includegraphics[scale=1]{figs/delta_robot_architecture_top.png}
\caption{\label{fig:delta_robot_architecture_top}Delta Robot Architecture - Top View}
\end{figure}
\chapter{Kinematics: Jacobian Matrix and Mobility}
Jacobian matrix between actuator displacement and top platform displacement.
There are three actuators in the following directions \(\hat{s}_1\), \(\hat{s}_2\) and \(\hat{s}_3\);
\begin{equation}\label{eq:detail_kinematics_cubic_s}
\hat{\bm{s}}_1 = \begin{bmatrix} \frac{-1}{\sqrt{6}} \\ \frac{-1}{\sqrt{2}} \\ \frac{1}{\sqrt{3}} \end{bmatrix} \quad
\hat{\bm{s}}_2 = \begin{bmatrix} \frac{\sqrt{2}}{\sqrt{3}} \\ 0 \\ \frac{1}{\sqrt{3}} \end{bmatrix} \quad
\hat{\bm{s}}_3 = \begin{bmatrix} \frac{-1}{\sqrt{6}} \\ \frac{ 1}{\sqrt{2}} \\ \frac{1}{\sqrt{3}} \end{bmatrix}
\end{equation}
\begin{equation}
\bm{J} = \begin{bmatrix}
\hat{\bm{s}}_1^T \\ \hat{\bm{s}}_2^T \\ \hat{\bm{s}}_3^T
\end{bmatrix}
\end{equation}
\begin{equation}
d\mathcal{L} = J d\mathcal{L}
\end{equation}
\begin{equation}
d\mathcal{X} = J^{-1} d\mathcal{L}
\end{equation}
The achievable workspace is a cube whose edge length is equal to the actuator stroke.
\begin{figure}[htbp]
\centering
\includegraphics[scale=1]{figs/delta_robot_3d_workspace.png}
\caption{\label{fig:delta_robot_3d_workspace}3D workspace}
\end{figure}
As most likely, the system will be used to perform YZ scans, it is interesting to see the mobility of the system in the ZY plane.
Depending on how the YZ plane is oriented (i.e., depending on the Rz angle of the delta robot with respect to the beam, defining the x direction), we get different mobility.
\begin{figure}[htbp]
\centering
\includegraphics[scale=1]{figs/delta_robot_2d_workspace.png}
\caption{\label{fig:delta_robot_2d_workspace}2D mobility for different orientations}
\end{figure}
\phantomsection
\label{}
\begin{verbatim}
Maximum YZ mobility for an angle of 270 degrees, square with edge size of 117 um
\end{verbatim}
\begin{figure}[htbp]
\centering
\includegraphics[scale=1]{figs/delta_robot_2d_workspace_optimal.png}
\caption{\label{fig:delta_robot_2d_workspace_optimal}2D mobility for the optimal Rz angle}
\end{figure}
\chapter{Kinematics: Degrees of Freedom}
In the perfect case (flexible joints having no stiffness in bending, and infinite stiffness in torsion and in the axial direction), the top platform is allowed to move only in the X, Y and Z directions while the three rotations are fixed.
In order to have some compliance in rotation, the flexible joints need to have some compliance in torsion \textbf{and} in the axial direction.
If only the torsional compliance is considered, or only the axial compliance, the top platform will still not be able to do any rotation.
This is shown below with the Simscape model:
Perfect Delta Robot:
\begin{itemize}
\item infinite axial stiffness
\item infinite torsional stiffness
\item no bending stiffness
\end{itemize}
It gives infinite stiffness in rotations, and a stiffness of \(1\,N/\mu m\) in X, Y and Z directions (i.e. equal to the actuator stiffness).
\phantomsection
\label{}
\begin{verbatim}
Stiffness in X,Y and Z directions: 1.0 N/um
\end{verbatim}
If we consider the torsion of the flexible joints:
\begin{itemize}
\item infinite axial stiffness
\item finite torsional stiffness
\item no bending stiffness
\end{itemize}
We get the same result.
\begin{table}[htbp]
\label{}
\centering
\begin{tabular}{rrrrrr}
1.00000000008084e-06 & 5.61161767954149e-17 & 1.71532908969278e-16 & -5.07840362381474e-20 & 6.66481298362927e-20 & -2.97485996797085e-20\\
9.44550093013109e-17 & 9.99999999981042e-07 & -1.31365181854596e-16 & 2.20736442292089e-20 & -8.27761658859861e-20 & -5.51841106039072e-20\\
1.5172479677791e-16 & 7.57916759433382e-18 & 9.9999999983089e-07 & 2.71965732539802e-20 & -5.0088900526952e-21 & 4.20708731166142e-20\\
3.7990974483635e-15 & -1.49195278352597e-15 & 1.09166051384021e-15 & -4.60992688885629e-28 & 4.46894514064728e-28 & -6.04202812027976e-29\\
1.92223678174906e-15 & 3.62267008376981e-15 & -5.42452104276465e-15 & 3.7737029650938e-28 & -2.99601307180469e-28 & -3.30297132145485e-28\\
3.79407058351761e-16 & -3.46944690994006e-17 & 9.05659407516431e-16 & -1.33615244419949e-28 & 6.31115609464934e-29 & -1.07596265815569e-29\\
\end{tabular}
\end{table}
If we consider the axial of the flexible joints:
\begin{itemize}
\item finite axial stiffness
\item infinite torsional stiffness
\item no bending stiffness
\end{itemize}
We get the same result.
\begin{table}[htbp]
\label{}
\centering
\begin{tabular}{rrrrrr}
1.0100082922792e-06 & -8.23544084894984e-12 & -1.12982601885747e-11 & -1.30123733161505e-19 & 3.61079565098929e-21 & -2.56479299609534e-20\\
-8.23691147427908e-12 & 1.01002426764947e-06 & 1.16488393394949e-11 & -9.17271935353013e-20 & -1.39093131659514e-20 & -8.92049690205949e-21\\
-1.12984563170605e-11 & 1.1646579416975e-11 & 1.01001628184113e-06 & -1.2624013403036e-19 & -4.41063676650963e-22 & 2.01282903077792e-20\\
3.25566266033832e-16 & 7.02470264849632e-18 & 1.34879235410707e-17 & -4.42814771779206e-29 & 1.06332319737688e-30 & -8.04051214064698e-30\\
-2.34669385520782e-15 & 1.03658500184429e-16 & 2.10026418149746e-15 & 3.04125606965025e-29 & -1.07347740796227e-29 & 1.00530401393662e-28\\
-2.76788049700945e-16 & -3.49174266014038e-17 & 1.36253386200494e-15 & -1.31490052587614e-28 & -1.10493913866777e-30 & 3.45058758900066e-29\\
\end{tabular}
\end{table}
No we consider both finite torsional stiffness and finite axial stiffness.
In that case we get some compliance in rotation.
So it is a combination of axial and torsion stiffness that gives some rotational stiffness of the top platform.
\begin{table}[htbp]
\label{}
\centering
\begin{tabular}{rrrrrr}
1.01000347398415e-06 & 1.08760660507374e-12 & 6.48998902114602e-12 & -1.68758827983914e-12 & 2.72734564017018e-12 & -1.13327901508316e-12\\
-1.7269667100718e-13 & 1.01000152837256e-06 & 4.09018170284123e-13 & -9.80286569772779e-13 & -9.94629340226498e-13 & 8.3468855003368e-13\\
5.40707734744154e-12 & -1.46859567258244e-12 & 1.0099981133678e-06 & 3.34755457607493e-12 & -6.56764113866634e-12 & 1.26237249518737e-12\\
2.67935189951885e-13 & -6.64493555908236e-14 & 7.44661955503977e-13 & 1.59744415094004e-05 & -6.97585818773949e-13 & 1.44845764745933e-13\\
1.91880640934689e-14 & -1.31284160978049e-13 & -5.83827721443037e-13 & 4.97550111979747e-13 & 1.5974440506229e-05 & 8.27388125221276e-14\\
1.63302978397554e-14 & -6.29948151015302e-14 & 1.11798835985125e-13 & -4.74438363934587e-14 & -1.39110944875938e-13 & 3.99840072236264e-06\\
\end{tabular}
\end{table}
Therefore, to model some compliance of the top platform in rotation, both the axial compliance and the torsional compliance of the flexible joints should be considered.
\chapter{Kinematics: Number of modes}
In the perfect condition (i.e. infinite stiffness in torsion and in compression of the flexible joints), the system has 6 states (i.e. 3 modes, one for each DoF: X, Y and Z).
When considering some compliance in torsion of the flexible joints, 12 states are added (one internal mode of the struts).
To remove these internal states (that might not be interesting but that could slow the simulations), one of the joint can have this torsional compliance while the other can have the torsional DoF constrained.
\phantomsection
\label{}
\begin{verbatim}
State-space model with 3 outputs, 3 inputs, and 6 states.
\end{verbatim}
\chapter{Flexible Joint Design}
\label{sec:delta_robot_flexible_joints}
The goal is to extract specifications for the flexible joints of the six struts.
The two most critical flexible joints imperfections are:
\begin{itemize}
\item The axial stiffness, that should be high enough
\item The bending stiffness, that should be low enough
\end{itemize}
The shear and torsional stiffnesses are not foreseen to be very problematic, but their impact will be evaluated.
First, the dynamics of a ``perfect'' Delta-Robot is identified (i.e. with perfect 2DoF rotational joints).
Then, the impact of the flexible joint's imperfections will be studied.
\section{Studied Geometry}
The cube's edge length is equal to 50mm, the distance between cube's vertices and top joints is 20mm and the length of the struts (i.e. the distance between the two flexible joints of the same strut) is 50mm.
The actuator stiffness is \(1\,N/\mu m\).
The obtained geometry is shown in Figure \ref{fig:delta_robot_studied_geometry}.
\begin{figure}[htbp]
\centering
\includegraphics[scale=1]{figs/delta_robot_studied_geometry.png}
\caption{\label{fig:delta_robot_studied_geometry}Geometry of the studied Delta Robot}
\end{figure}
The dynamics is first identified in perfect conditions (infinite axial stiffness of the joints, zero bending stiffness).
We get \texttt{State-space model with 3 outputs, 3 inputs, and 6 states.}
We get a perfectly decoupled system, with three identical modes in the X, Y and Z directions.
The dynamics is shown in Figure \ref{fig:delta_robot_dynamics_perfect}.
\begin{figure}[htbp]
\centering
\includegraphics[scale=1]{figs/delta_robot_dynamics_perfect.png}
\caption{\label{fig:delta_robot_dynamics_perfect}Dynamics of the delta robot with perfect joints}
\end{figure}
\section{Stiffness seen by the actuator}
Because the flexible joints will have some bending stiffness, the actuator in one direction will ``see'' some stiffness due to the struts in the other directions.
This will limit its effective stroke.
We want this parallel stiffness to be much smaller than the stiffness of the actuator.
The parallel stiffness seen by the actuator as a function of the bending stiffness of the flexible joints is computed and shown in Figure \ref{fig:delta_robot_bending_stiffness_parallel_k}.
\begin{figure}[htbp]
\centering
\includegraphics[scale=1]{figs/delta_robot_bending_stiffness_parallel_k.png}
\caption{\label{fig:delta_robot_bending_stiffness_parallel_k}Effect of the bending stiffness of the flexible joints on the stiffness seen by the actuators}
\end{figure}
The parallel stiffness is therefore proportional to the bending stiffness.
The ``linear coefficient'' depend on the geometry, and it is here equal to \(3200 \frac{N/m}{Nm/\text{rad}}\).
If we want the parallel stiffness to be much smaller than the stiffness of the actuator (\(k_p \ll k_a = 1.6\,N/\mu m\)), the bending stiffness should be \(\ll 500\,Nm/\text{rad}\).
Therefore, we should aim at \(k_f < 50\,Nm/\text{rad}\).
This should be validated with the final geometry.
\section{Bending Stiffness}
Then, the dynamics is identified for a bending Stiffness of \(50\,Nm/\text{rad}\) and compared with a Delta robot with no bending stiffness in Figure \ref{fig:delta_robot_bending_stiffness_dynamics}.
It can be seen that the DC gain is a bit lower when the bending stiffness is considered and the resonance frequency is increased.
This simply means that the system stiffness is increased.
It is not critical from a dynamical point of view, it just decreases the achievable stroke as explained in the previous section.
\begin{figure}[htbp]
\centering
\includegraphics[scale=1]{figs/delta_robot_bending_stiffness_dynamics.png}
\caption{\label{fig:delta_robot_bending_stiffness_dynamics}Effect of the bending stiffness on the dynamics}
\end{figure}
\section{Axial Stiffness}
Now, the effect of the axial stiffness on the dynamics is studied (Figure \ref{fig:delta_robot_axial_stiffness_dynamics}).
Additional modes can be observed on the plant dynamics, which could limit the achievable bandwidth.
Therefore the axial stiffness should be maximized.
Having the axial stiffness 100 times stiffer than the actuator stiffness seems reasonable.
Therefore, we should aim at \(k_a > 100\,N/\mu m\).
\begin{figure}[htbp]
\centering
\includegraphics[scale=1]{figs/delta_robot_axial_stiffness_dynamics.png}
\caption{\label{fig:delta_robot_axial_stiffness_dynamics}Effect of the joint's axial stiffness on the plant dynamics}
\end{figure}
\section{Torsional Stiffness}
Now the compliance in torsion of the flexible joints is considered.
If we look at the compliance of the delta robot in rotation as a function of the torsional stiffness of the flexible joints (Figure \ref{fig:delta_robot_kt_compliance}), we see almost no effect: the system is not made more stiff by increasing the torsional stiffness of the joints.
\begin{figure}[htbp]
\centering
\includegraphics[scale=1]{figs/delta_robot_kt_compliance.png}
\caption{\label{fig:delta_robot_kt_compliance}Effect of the joint's torsional stiffness on the Delta Robot compliance}
\end{figure}
If we have a look at the effect of the torsional stiffness on the plant dynamics (Figure \ref{fig:delta_robot_kt_dynamics}), we see almost no effect, except when super high values are reached (\(10^6\,Nm/\text{rad}\)), which are unrealistic.
\begin{figure}[htbp]
\centering
\includegraphics[scale=1]{figs/delta_robot_kt_dynamics.png}
\caption{\label{fig:delta_robot_kt_dynamics}Effect of the joint's torsional stiffness on the Delta Robot plant dynamics}
\end{figure}
Therefore, the torsional stiffness is not a super important metric for the design of the delta robot.
\section{Shear Stiffness}
As shown in Figure \ref{fig:delta_robot_shear_stiffness_compliance}, the shear stiffness of the flexible joints has some effect on the compliance in translation and almost no effect on the compliance in rotation.
This is quite logical, and so the shear stiffness should be maximized.
A value of \(100\,N/\mu m\) seems reasonable.
\begin{figure}[htbp]
\centering
\includegraphics[scale=1]{figs/delta_robot_shear_stiffness_compliance.png}
\caption{\label{fig:delta_robot_shear_stiffness_compliance}Effect of the shear stiffness of the flexible joints on the Delta Robot compliance}
\end{figure}
\section{Effect of cube's size}
Let's choose reasonable values for the flexible joints:
\begin{itemize}
\item Bending stiffness of 50Nm/rad
\item Torsional stiffness of 500Nm/rad
\item Axial stiffness of 100N/um
\item Shear stiffness of 100N/um
\end{itemize}
And we see the effect of changing the cube's size.
\subsection{Effect on the plant dynamics}
\begin{itemize}
\item[{$\square$}] \textbf{Understand why such different dynamics between 3dof\_a joints and 6dof joints with very high shear stiffnesses}
\end{itemize}
The effect of the cube's size on the plant dynamics is shown in Figure \ref{fig:delta_robot_cube_size_plant_dynamics}:
\begin{itemize}
\item coupling decreases with the cube's size
\item one resonance frequency increases with the cube's size (resonances in rotation), which may be beneficial from a control point of view
\item coupling at the main resonance varies with the cube's size, but it may also depend on the relative position between the CoM and the cube's center
\end{itemize}
\begin{figure}[htbp]
\centering
\includegraphics[scale=1]{figs/delta_robot_cube_size_plant_dynamics.png}
\caption{\label{fig:delta_robot_cube_size_plant_dynamics}Effect of the cube's size on the plant dynamics}
\end{figure}
\subsection{Effect on the compliance}
As shown in Figure \ref{fig:delta_robot_cube_size_compliance_rotation}, the stiffness of the delta robot in rotation increases with the cube's size.
\begin{figure}[htbp]
\centering
\includegraphics[scale=1]{figs/delta_robot_cube_size_compliance_rotation.png}
\caption{\label{fig:delta_robot_cube_size_compliance_rotation}Effect of the cube's size on the rotational compliance of the top platform}
\end{figure}
With a cube size of 50mm, the resonance frequency is already above 1kHz with seems reasonable.
\section{Effect of the strut length ?}
Let's choose reasonable values for the flexible joints:
\begin{itemize}
\item Bending stiffness of 50Nm/rad
\item Torsional stiffness of 500Nm/rad
\item Axial stiffness of 100N/um
\end{itemize}
And we see the effect of changing the strut length.
\subsection{Effect on the plant dynamics}
As shown in Figure \ref{fig:delta_robot_strut_length_plant_dynamics}, having longer struts:
\begin{itemize}
\item decreases the main resonance frequency: this means that the stiffness in the X,Y and Z directions is decreased when the length of the strut is longer.
This is reasonable as the ``lever'' arm is getting larger, so the bending stiffness and compression of the flexible joints have a larger effect on the top platform compliance.
\item decreases the low frequency coupling: this effect is more difficult to physically understand
\end{itemize}
But even with relatively short struts (20mm and above), the low frequency decoupling is already around two orders of magnitude, which is enough from a control point of view.
So, the struts length can be optimized to not decrease too much the stiffness of the platform while still getting good low frequency decoupling.
\begin{figure}[htbp]
\centering
\includegraphics[scale=1]{figs/delta_robot_strut_length_plant_dynamics.png}
\caption{\label{fig:delta_robot_strut_length_plant_dynamics}Effect of the cube's size on the plant dynamics}
\end{figure}
\subsection{Effect on the compliance}
As shown in Figure \ref{fig:delta_robot_strut_length_compliance_rotation}, the strut length has an effect on the system stiffness in translation (left plot) but almost not in rotation (right plot).
\begin{figure}[htbp]
\centering
\includegraphics[scale=1]{figs/delta_robot_strut_length_compliance_rotation.png}
\caption{\label{fig:delta_robot_strut_length_compliance_rotation}Effect of the cube's size on the rotational compliance of the top platform}
\end{figure}
\section{Having the Center of Mass at the cube's center}
To make things easier, we take a top platform with no mass, mass-less struts, and we put a payload on top of the platform.
As shown in Figure \ref{fig:delta_robot_CoM_pos_effect_plant}, having the CoM of the payload at the cube's center allow to have better decoupling properties above the suspension mode of the system (i.e. above the first mode).
This could allow to have a bandwidth exceeding the frequency of the first mode.
But how sensitive this decoupling is to the exact position of the CoM still need to be studied.
\begin{figure}[htbp]
\centering
\includegraphics[scale=1]{figs/delta_robot_CoM_pos_effect_plant.png}
\caption{\label{fig:delta_robot_CoM_pos_effect_plant}Effect of the payload's Center of Mass position with respect to the cube's size on the plant dynamics}
\end{figure}
\section{Conclusion}
\chapter{Conclusion}
\printbibliography[heading=bibintoc,title={Bibliography}]
\end{document}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 241 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

View File

@@ -0,0 +1,35 @@
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;

View File

@@ -0,0 +1,85 @@
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}
% - 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.platform_F.FRa = FRa;
stewart.platform_M.MRb = MRb;

View File

@@ -0,0 +1,79 @@
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

View File

@@ -0,0 +1,237 @@
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
plot3([Fa(1,:), Fa(1,1)], ...
[Fa(2,:), Fa(2,1)], ...
[Fa(3,:), Fa(3,1)], '-', '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.
Fb = FTm*[Mb;ones(1,6)];
if args.platforms
plot3([Fb(1,:), Fb(1,1)], ...
[Fb(2,:), Fb(2,1)], ...
[Fb(3,:), Fb(3,1)], '-', 'Color', args.M_color);
end
% Plot the position and labels of the rotation joints fixed to the mobile platform.
if args.joints
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

View File

@@ -0,0 +1,34 @@
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)];

View File

@@ -0,0 +1,57 @@
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;

View File

@@ -0,0 +1,66 @@
function [stewart] = generateDeltaRobot(stewart, args)
% generateDeltaRobot - Generate a Delta Robot Configuration
%
% Syntax: [stewart] = generateDeltaRobot(args)
%
% Inputs:
% - args - Can have the following fields:
% - d [1x1] - Size of the cube [m]
% - b [1x1] - Distance between top joints bi and cube's vertices [m]
% - L [1x1] - Length of the struts (i.e. distances between ai and bi) [m]
arguments
stewart
args.d (1,1) double {mustBeNumeric, mustBePositive} = 70e-3
args.b (1,1) double {mustBeNumeric, mustBeNonnegative} = 50e-3
args.L (1,1) double {mustBeNumeric, mustBePositive} = 50e-3
args.m_top (1,1) double {mustBeNumeric, mustBePositive} = 0.3 % Mass of the top platform
end
% We define the useful vertices 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]);
% Coordinates of the cube's vertices
Cc = R'*[[args.d/2;-args.d/2;-args.d/2],[args.d/2;args.d/2;-args.d/2],[-args.d/2;args.d/2;-args.d/2],[-args.d/2;args.d/2;args.d/2],[-args.d/2;-args.d/2;args.d/2],[args.d/2;-args.d/2;args.d/2]];
% Coordinates of the cube's vertices corresponding to the six struts, expresssed with respect to the cube's center
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(:,6), Cc(:,4), Cc(:,2), Cc(:,6), Cc(:,4), Cc(:,2)]; % CCm(:,i) corresponds to the top cube's vertice corresponding to the i'th leg
% We can compute the vector of each leg si
CSi = (CCm - CCf)./vecnorm(CCm - CCf);
% We now compute the position of the joints ai and bi with respect to the cube's center
Ca = CCf - (args.b + args.L).*CSi;
Cb = CCf - args.b.*CSi;
%% Computes relative position of frames
FO_M = [0; 0; args.L*CSi(3,1)]; % Position of {M} with respect to {F} [m]
MO_B = [0; 0; (args.b+args.d/2)*CSi(3,1)]; % Position of {B} with respect to {M} [m]
FO_A = MO_B + FO_M; % Position of {A} with respect to {F} [m]
stewart.geometry.d = args.d; % Size of the cube
stewart.geometry.H = args.L*CSi(3,1); % Height between {M} and {F} frames
stewart.geometry.FO_M = FO_M;
stewart.platform_M.MO_B = MO_B;
stewart.platform_F.FO_A = FO_A;
%% Now ai and bi can be expressed with respect to the {F} and {M} frames
Fa = Ca + FO_A;
Mb = Cb + MO_B;
%%
stewart.platform_F.Ca = Ca; % Position of bottom joints ai with respect to {F}
stewart.platform_F.Fa = Fa; % Position of bottom joints ai with respect to {F}
stewart.platform_M.Mb = Mb; % Position of top joints bi with respect to {M}
stewart.platform_M.Cb = Cb; % Position of top joints bi with respect to {M}
stewart.platform_M.m = args.m_top;

View File

@@ -0,0 +1,39 @@
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;

View File

@@ -0,0 +1,60 @@
function [stewart] = initializeActuatorDynamics(stewart, args)
% initializeActuatorDynamics - Add Stiffness and Damping properties of each strut
%
% Syntax: [stewart] = initializeActuatorDynamics(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

View File

@@ -0,0 +1,17 @@
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

View File

@@ -0,0 +1,59 @@
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;

View File

@@ -0,0 +1,37 @@
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.M (1,1) double {mustBeNumeric, mustBePositive} = 0.1 % Mass [kg]
args.R (1,1) double {mustBeNumeric, mustBePositive} = 5e-3 % Radius [m]
end
stewart.struts.M = args.M;
stewart.struts.R = args.R;
stewart.struts.H = stewart.geometry.l(1);
end

View File

@@ -0,0 +1,35 @@
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;

View File

@@ -0,0 +1,61 @@
function [stewart] = initializeJointDynamics(stewart, args)
arguments
stewart
args.type_F char {mustBeMember(args.type_F,{'2dof', '3dof', '2dof_a', '3dof_a', '6dof'})} = '2dof'
args.type_M char {mustBeMember(args.type_M,{'2dof', '3dof', '2dof_a', '3dof_a', '6dof'})} = '3dof'
args.Kf (1,1) double {mustBeNumeric, mustBeNonnegative} = 0 % Bending stiffness
args.Cf (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
args.Kt (1,1) double {mustBeNumeric, mustBeNonnegative} = 0 % Torsional stiffness
args.Ct (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
args.Ka (1,1) double {mustBeNumeric, mustBeNonnegative} = 0 % Axial stiffness
args.Ca (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
args.Ks (1,1) double {mustBeNumeric, mustBeNonnegative} = 0 % Shear stiffness
args.Cs (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
end
switch args.type_F
case '2dof'
stewart.joints.type_F = 1;
case '3dof'
stewart.joints.type_F = 2;
case '2dof_a'
stewart.joints.type_F = 3;
case '3dof_a'
stewart.joints.type_F = 4;
case '6dof'
stewart.joints.type_F = 5;
otherwise
error("joints are not correctly defined")
end
switch args.type_M
case '2dof'
stewart.joints.type_M = 1;
case '3dof'
stewart.joints.type_M = 2;
case '2dof_a'
stewart.joints.type_M = 3;
case '3dof_a'
stewart.joints.type_M = 4;
case '6dof'
stewart.joints.type_M = 5;
otherwise
error("joints are not correctly defined")
end
%% Axial Stiffness
stewart.joints.Ka = args.Ka;
stewart.joints.Ca = args.Ca;
%% Bending Stiffness
stewart.joints.Kf = args.Kf;
stewart.joints.Cf = args.Cf;
%% Torsional Stiffness
stewart.joints.Kt = args.Kt;
stewart.joints.Ct = args.Ct;
%% Shear Stiffness
stewart.joints.Ks = args.Ks;
stewart.joints.Cs = args.Cs;
end

View File

@@ -0,0 +1,26 @@
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

View File

@@ -0,0 +1,27 @@
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 -
% - struts -
% - actuators -
% - geometry -
% - properties -
stewart = struct();
stewart.platform_F = struct();
stewart.platform_M = struct();
stewart.joints = struct();
stewart.struts = 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();

View File

@@ -0,0 +1,27 @@
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;

View File

@@ -0,0 +1,60 @@
function [stewart] = initializeActuatorDynamics(stewart, args)
% initializeActuatorDynamics - Add Stiffness and Damping properties of each strut
%
% Syntax: [stewart] = initializeActuatorDynamics(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

View File

@@ -0,0 +1,36 @@
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;

58
matlab/src/plotCube.m Normal file
View File

@@ -0,0 +1,58 @@
function [] = plotCube(stewart, args)
arguments
stewart
args.Hc (1,1) double {mustBeNumeric, mustBePositive} = 60e-3 % Height of the cube
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

View File

@@ -0,0 +1,15 @@
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)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

19
preamble.tex Normal file
View File

@@ -0,0 +1,19 @@
\usepackage[ %
acronym, % Separate acronyms and glossary
toc, % appear in ToC
automake, % auto-use the makeglossaries command (requires shell-escape)
nonumberlist, % don't back reference pages
nogroupskip, % don't group by letter
nopostdot % don't add a dot at the end of each element
]{glossaries}
\usepackage[stylemods=longextra]{glossaries-extra}
\setabbreviationstyle[acronym]{long-short}
\setglossarystyle{long-name-desc}
\usepackage{amssymb}
\usepackage{amsmath}
\makeindex
\makeglossaries

139
preamble_extra.tex Normal file
View File

@@ -0,0 +1,139 @@
\usepackage{float}
\usepackage{enumitem}
\usepackage{caption,tabularx,booktabs}
\usepackage{bm}
\usepackage{xpatch} % Recommanded for biblatex
\usepackage[ % use biblatex for bibliography
backend=biber, % use biber backend (bibtex replacement) or bibtex
style=numeric-comp, % bib style
hyperref=true, % activate hyperref support
backref=true, % activate backrefs
isbn=false, % don't show isbn tags
url=false, % don't show url tags
doi=false, % don't show doi tags
urldate=long, % display type for dates
autocite=inline,%
sortcites=true, %
maxnames=3, %
minnames=1, %
maxbibnames=5, %
minbibnames=3, %
maxcitenames=2, %
mincitenames=1 %
]{biblatex}
\setlength\bibitemsep{1.1\itemsep}
\usepackage{caption}
\usepackage{subcaption}
\captionsetup[figure]{labelfont=bf}
\captionsetup[subfigure]{labelfont=bf}
\captionsetup[listing]{labelfont=bf}
\captionsetup[table]{labelfont=bf}
\usepackage{xcolor}
\definecolor{my-blue}{HTML}{6b7adb}
\definecolor{my-pale-blue}{HTML}{e6e9f9}
\definecolor{my-red}{HTML}{db6b6b}
\definecolor{my-pale-red}{HTML}{f9e6e6}
\definecolor{my-green}{HTML}{6bdbb6}
\definecolor{my-pale-green}{HTML}{e6f9f3}
\definecolor{my-yellow}{HTML}{dbd26b}
\definecolor{my-pale-yellow}{HTML}{f9f7e6}
\definecolor{my-orange}{HTML}{dba76b}
\definecolor{my-pale-orange}{HTML}{f9f0e6}
\definecolor{my-grey}{HTML}{a3a3a3}
\definecolor{my-pale-grey}{HTML}{f0f0f0}
\definecolor{my-turq}{HTML}{6bc7db}
\definecolor{my-pale-turq}{HTML}{e6f6f9}
\usepackage{inconsolata}
\usepackage[newfloat=true, chapter]{minted}
\usemintedstyle{autumn}
\setminted{frame=lines,breaklines=true,tabsize=4,fontsize=\scriptsize,autogobble=true,labelposition=topline,bgcolor=my-pale-grey}
\setminted[matlab]{label=Matlab}
\setminted[latex]{label=LaTeX}
\setminted[bash]{label=Bash}
\setminted[python]{label=Python}
\setminted[text]{label=Results}
\setminted[md]{label=Org Mode}
\setmintedinline{fontsize=\normalsize,bgcolor=my-pale-grey}
\usepackage[most]{tcolorbox}
\tcbuselibrary{minted}
\newtcolorbox{seealso}{ enhanced,breakable,colback=my-pale-grey,colframe=my-grey,fonttitle=\bfseries,title=See Also}
\newtcolorbox{hint}{ enhanced,breakable,colback=my-pale-grey,colframe=my-grey,fonttitle=\bfseries,title=Hint}
\newtcolorbox{definition}{enhanced,breakable,colback=my-pale-red, colframe=my-red, fonttitle=\bfseries,title=Definition}
\newtcolorbox{important}{ enhanced,breakable,colback=my-pale-red, colframe=my-red, fonttitle=\bfseries,title=Important}
\newtcolorbox{exampl}[1][]{ enhanced,breakable,colback=my-pale-green,colframe=my-green,fonttitle=\bfseries,title=Example,#1}
\newtcolorbox{exercice}{ enhanced,breakable,colback=my-pale-yellow,colframe=my-yellow,fonttitle=\bfseries,title=Exercice}
\newtcolorbox{question}{ enhanced,breakable,colback=my-pale-yellow,colframe=my-yellow,fonttitle=\bfseries,title=Question}
\newtcolorbox{answer}{ enhanced,breakable,colback=my-pale-turq,colframe=my-turq,fonttitle=\bfseries,title=Answer}
\newtcolorbox{summary}{ enhanced,breakable,colback=my-pale-blue,colframe=my-blue,fonttitle=\bfseries,title=Summary}
\newtcolorbox{note}{ enhanced,breakable,colback=my-pale-blue,colframe=my-blue,fonttitle=\bfseries,title=Note}
\newtcolorbox{caution}{ enhanced,breakable,colback=my-pale-orange,colframe=my-orange,fonttitle=\bfseries,title=Caution}
\newtcolorbox{warning}{ enhanced,breakable,colback=my-pale-orange,colframe=my-orange,fonttitle=\bfseries,title=Warning}
\newtcolorbox{my-quote}[1]{%
colback=my-pale-grey,
grow to right by=-10mm,
grow to left by=-10mm,
boxrule=0pt,
boxsep=0pt,
breakable,
enhanced jigsaw,
borderline west={4pt}{0pt}{my-grey}}
\renewenvironment{quote}{\begin{my-quote}}{\end{my-quote}}
\newtcolorbox{my-verse}[1]{%
colback=my-pale-grey,
grow to right by=-10mm,
grow to left by=-10mm,
boxrule=0pt,
boxsep=0pt,
breakable,
enhanced jigsaw,
borderline west={4pt}{0pt}{my-grey}}
\renewenvironment{verse}{\begin{my-verse}}{\end{my-verse}}
\usepackage{environ}% http://ctan.org/pkg/environ
\NewEnviron{aside}{%
\marginpar{\BODY}
}
\renewenvironment{verbatim}{\VerbatimEnvironment\begin{minted}[]{text}}{\end{minted}}
\usepackage{soul}
\sethlcolor{my-pale-grey}
\let\OldTexttt\texttt
\renewcommand{\texttt}[1]{{\ttfamily\hl{\mbox{\,#1\,}}}}
\makeatletter
\preto\Gin@extensions{png,}
\DeclareGraphicsRule{.png}{pdf}{.pdf}{\noexpand\Gin@base.pdf}
\preto\Gin@extensions{gif,}
\DeclareGraphicsRule{.gif}{png}{.png}{\noexpand\Gin@base.png}
\makeatother
\usepackage{hyperref}
\hypersetup{
colorlinks = true,
allcolors = my-blue
}
\usepackage{hypcap}
\renewcommand{\topfraction}{.8}
\renewcommand{\floatpagefraction}{.8}