2019-03-22 12:03:59 +01:00
<?xml version="1.0" encoding="utf-8"?>
2020-01-28 17:38:19 +01:00
<?xml version="1.0" encoding="utf-8"?>
2019-03-22 12:03:59 +01:00
< !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 >
2020-02-13 15:48:42 +01:00
<!-- 2020 - 02 - 12 mer. 10:22 -->
2019-03-22 12:03:59 +01:00
< meta http-equiv = "Content-Type" content = "text/html;charset=utf-8" / >
< meta name = "viewport" content = "width=device-width, initial-scale=1" / >
< title > Kinematic Study of the Stewart Platform< / title >
< meta name = "generator" content = "Org mode" / >
2020-01-28 17:38:19 +01:00
< meta name = "author" content = "Dehaeze Thomas" / >
2019-03-22 12:03:59 +01:00
< style type = "text/css" >
<!-- /* --> <![CDATA[/*> <!-- */
.title { text-align: center;
margin-bottom: .2em; }
.subtitle { text-align: center;
font-size: medium;
font-weight: bold;
margin-top:0; }
.todo { font-family: monospace; color: red; }
.done { font-family: monospace; color: green; }
.priority { font-family: monospace; color: orange; }
.tag { background-color: #eee; font-family: monospace;
padding: 2px; font-size: 80%; font-weight: normal; }
.timestamp { color: #bebebe; }
.timestamp-kwd { color: #5f9ea0; }
.org-right { margin-left: auto; margin-right: 0px; text-align: right; }
.org-left { margin-left: 0px; margin-right: auto; text-align: left; }
.org-center { margin-left: auto; margin-right: auto; text-align: center; }
.underline { text-decoration: underline; }
#postamble p, #preamble p { font-size: 90%; margin: .2em; }
p.verse { margin-left: 3%; }
pre {
border: 1px solid #ccc;
box-shadow: 3px 3px 3px #eee;
padding: 8pt;
font-family: monospace;
overflow: auto;
margin: 1.2em;
}
pre.src {
position: relative;
overflow: visible;
padding-top: 1.2em;
}
pre.src:before {
display: none;
position: absolute;
background-color: white;
top: -10px;
right: 10px;
padding: 3px;
border: 1px solid black;
}
pre.src:hover:before { display: inline;}
/* Languages per Org manual */
pre.src-asymptote:before { content: 'Asymptote'; }
pre.src-awk:before { content: 'Awk'; }
pre.src-C:before { content: 'C'; }
/* pre.src-C++ doesn't work in CSS */
pre.src-clojure:before { content: 'Clojure'; }
pre.src-css:before { content: 'CSS'; }
pre.src-D:before { content: 'D'; }
pre.src-ditaa:before { content: 'ditaa'; }
pre.src-dot:before { content: 'Graphviz'; }
pre.src-calc:before { content: 'Emacs Calc'; }
pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
pre.src-fortran:before { content: 'Fortran'; }
pre.src-gnuplot:before { content: 'gnuplot'; }
pre.src-haskell:before { content: 'Haskell'; }
pre.src-hledger:before { content: 'hledger'; }
pre.src-java:before { content: 'Java'; }
pre.src-js:before { content: 'Javascript'; }
pre.src-latex:before { content: 'LaTeX'; }
pre.src-ledger:before { content: 'Ledger'; }
pre.src-lisp:before { content: 'Lisp'; }
pre.src-lilypond:before { content: 'Lilypond'; }
pre.src-lua:before { content: 'Lua'; }
pre.src-matlab:before { content: 'MATLAB'; }
pre.src-mscgen:before { content: 'Mscgen'; }
pre.src-ocaml:before { content: 'Objective Caml'; }
pre.src-octave:before { content: 'Octave'; }
pre.src-org:before { content: 'Org mode'; }
pre.src-oz:before { content: 'OZ'; }
pre.src-plantuml:before { content: 'Plantuml'; }
pre.src-processing:before { content: 'Processing.js'; }
pre.src-python:before { content: 'Python'; }
pre.src-R:before { content: 'R'; }
pre.src-ruby:before { content: 'Ruby'; }
pre.src-sass:before { content: 'Sass'; }
pre.src-scheme:before { content: 'Scheme'; }
pre.src-screen:before { content: 'Gnu Screen'; }
pre.src-sed:before { content: 'Sed'; }
pre.src-sh:before { content: 'shell'; }
pre.src-sql:before { content: 'SQL'; }
pre.src-sqlite:before { content: 'SQLite'; }
/* additional languages in org.el's org-babel-load-languages alist */
pre.src-forth:before { content: 'Forth'; }
pre.src-io:before { content: 'IO'; }
pre.src-J:before { content: 'J'; }
pre.src-makefile:before { content: 'Makefile'; }
pre.src-maxima:before { content: 'Maxima'; }
pre.src-perl:before { content: 'Perl'; }
pre.src-picolisp:before { content: 'Pico Lisp'; }
pre.src-scala:before { content: 'Scala'; }
pre.src-shell:before { content: 'Shell Script'; }
pre.src-ebnf2ps:before { content: 'ebfn2ps'; }
/* additional language identifiers per "defun org-babel-execute"
in ob-*.el */
pre.src-cpp:before { content: 'C++'; }
pre.src-abc:before { content: 'ABC'; }
pre.src-coq:before { content: 'Coq'; }
pre.src-groovy:before { content: 'Groovy'; }
/* additional language identifiers from org-babel-shell-names in
ob-shell.el: ob-shell is the only babel language using a lambda to put
the execution function name together. */
pre.src-bash:before { content: 'bash'; }
pre.src-csh:before { content: 'csh'; }
pre.src-ash:before { content: 'ash'; }
pre.src-dash:before { content: 'dash'; }
pre.src-ksh:before { content: 'ksh'; }
pre.src-mksh:before { content: 'mksh'; }
pre.src-posh:before { content: 'posh'; }
/* Additional Emacs modes also supported by the LaTeX listings package */
pre.src-ada:before { content: 'Ada'; }
pre.src-asm:before { content: 'Assembler'; }
pre.src-caml:before { content: 'Caml'; }
pre.src-delphi:before { content: 'Delphi'; }
pre.src-html:before { content: 'HTML'; }
pre.src-idl:before { content: 'IDL'; }
pre.src-mercury:before { content: 'Mercury'; }
pre.src-metapost:before { content: 'MetaPost'; }
pre.src-modula-2:before { content: 'Modula-2'; }
pre.src-pascal:before { content: 'Pascal'; }
pre.src-ps:before { content: 'PostScript'; }
pre.src-prolog:before { content: 'Prolog'; }
pre.src-simula:before { content: 'Simula'; }
pre.src-tcl:before { content: 'tcl'; }
pre.src-tex:before { content: 'TeX'; }
pre.src-plain-tex:before { content: 'Plain TeX'; }
pre.src-verilog:before { content: 'Verilog'; }
pre.src-vhdl:before { content: 'VHDL'; }
pre.src-xml:before { content: 'XML'; }
pre.src-nxml:before { content: 'XML'; }
/* add a generic configuration mode; LaTeX export needs an additional
(add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */
pre.src-conf:before { content: 'Configuration File'; }
table { border-collapse:collapse; }
caption.t-above { caption-side: top; }
caption.t-bottom { caption-side: bottom; }
td, th { vertical-align:top; }
th.org-right { text-align: center; }
th.org-left { text-align: center; }
th.org-center { text-align: center; }
td.org-right { text-align: right; }
td.org-left { text-align: left; }
td.org-center { text-align: center; }
dt { font-weight: bold; }
.footpara { display: inline; }
.footdef { margin-bottom: 1em; }
.figure { padding: 1em; }
.figure p { text-align: center; }
.equation-container {
display: table;
text-align: center;
width: 100%;
}
.equation {
vertical-align: middle;
}
.equation-label {
display: table-cell;
text-align: right;
vertical-align: middle;
}
.inlinetask {
padding: 10px;
border: 2px solid gray;
margin: 10px;
background: #ffffcc;
}
#org-div-home-and-up
{ text-align: right; font-size: 70%; white-space: nowrap; }
textarea { overflow-x: auto; }
.linenr { font-size: smaller }
.code-highlighted { background-color: #ffff00; }
.org-info-js_info-navigation { border-style: none; }
#org-info-js_console-label
{ font-size: 10px; font-weight: bold; white-space: nowrap; }
.org-info-js_search-highlight
{ background-color: #ffff00; color: #000000; font-weight: bold; }
.org-svg { width: 90%; }
/*]]>*/-->
< / style >
2019-08-26 11:58:44 +02:00
< link rel = "stylesheet" type = "text/css" href = "./css/htmlize.css" / >
< link rel = "stylesheet" type = "text/css" href = "./css/readtheorg.css" / >
< script src = "./js/jquery.min.js" > < / script >
< script src = "./js/bootstrap.min.js" > < / script >
< script src = "./js/jquery.stickytableheaders.min.js" > < / script >
< script src = "./js/readtheorg.js" > < / script >
2019-03-22 12:03:59 +01:00
< script type = "text/javascript" >
/*
@licstart The following is the entire license notice for the
JavaScript code in this tag.
2020-01-28 17:38:19 +01:00
Copyright (C) 2012-2020 Free Software Foundation, Inc.
2019-03-22 12:03:59 +01:00
The JavaScript code in this tag is free software: you can
redistribute it and/or modify it under the terms of the GNU
General Public License (GNU GPL) as published by the Free Software
Foundation, either version 3 of the License, or (at your option)
any later version. The code is distributed WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
As additional permission under GNU GPL version 3 section 7, you
may distribute non-source (e.g., minimized or compacted) forms of
that code without the copy of the GNU GPL normally required by
section 4, provided you include this license notice and a URL
through which recipients can access the Corresponding Source.
@licend The above is the entire license notice
for the JavaScript code in this tag.
*/
<!-- /* --> <![CDATA[/*> <!-- */
function CodeHighlightOn(elem, id)
{
var target = document.getElementById(id);
if(null != target) {
elem.cacheClassElem = elem.className;
elem.cacheClassTarget = target.className;
target.className = "code-highlighted";
elem.className = "code-highlighted";
}
}
function CodeHighlightOff(elem, id)
{
var target = document.getElementById(id);
if(elem.cacheClassElem)
elem.className = elem.cacheClassElem;
if(elem.cacheClassTarget)
target.className = elem.cacheClassTarget;
}
/*]]>*///-->
< / script >
2020-01-29 17:49:25 +01:00
< script >
2020-02-11 15:16:07 +01:00
MathJax = {
tex: { macros: {
bm: ["\\boldsymbol{#1}",1],
}
2020-01-29 17:49:25 +01:00
}
2020-02-11 15:16:07 +01:00
};
< / script >
< script type = "text/javascript"
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js">< / script >
2019-03-22 12:03:59 +01:00
< / head >
< body >
2019-08-26 11:58:44 +02:00
< 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" >
2019-03-22 12:03:59 +01:00
< h1 class = "title" > Kinematic Study of the Stewart Platform< / h1 >
< div id = "table-of-contents" >
< h2 > Table of Contents< / h2 >
< div id = "text-table-of-contents" >
< ul >
2020-02-11 15:50:52 +01:00
< li > < a href = "#org6858f1f" > 1. Jacobian Analysis< / a >
2020-01-28 17:38:19 +01:00
< ul >
2020-02-11 15:50:52 +01:00
< li > < a href = "#org8210cee" > 1.1. Jacobian Computation< / a > < / li >
< li > < a href = "#org4d71022" > 1.2. Jacobian - Velocity loop closure< / a > < / li >
< li > < a href = "#org2847e30" > 1.3. Jacobian - Static Force Transformation< / a > < / li >
2020-01-28 17:38:19 +01:00
< / ul >
< / li >
2020-02-11 15:50:52 +01:00
< li > < a href = "#org87bfd11" > 2. Stiffness Analysis< / a >
2020-01-28 17:38:19 +01:00
< ul >
2020-02-11 15:50:52 +01:00
< li > < a href = "#orgb1956e6" > 2.1. Computation of the Stiffness and Compliance Matrix< / a > < / li >
2020-01-29 13:29:29 +01:00
< / ul >
< / li >
2020-02-11 15:50:52 +01:00
< li > < a href = "#org5718735" > 3. Forward and Inverse Kinematics< / a >
2020-01-29 17:49:25 +01:00
< ul >
2020-02-11 15:50:52 +01:00
< li > < a href = "#orgebda1d9" > 3.1. Inverse Kinematics< / a > < / li >
< li > < a href = "#org1795522" > 3.2. Forward Kinematics< / a > < / li >
< li > < a href = "#org5a3ce80" > 3.3. Approximate solution of the Forward and Inverse Kinematic problem for small displacement using the Jacobian matrix< / a > < / li >
< li > < a href = "#org86b4b35" > 3.4. Estimation of the range validity of the approximate inverse kinematics< / a >
2020-01-28 17:38:19 +01:00
< ul >
2020-02-13 15:48:42 +01:00
< li > < a href = "#orgc3c7024" > 3.4.1. Stewart architecture definition< / a > < / li >
2020-02-11 15:50:52 +01:00
< li > < a href = "#orgd83ccf3" > 3.4.2. Comparison for “ pure” translations< / a > < / li >
< li > < a href = "#org4871c83" > 3.4.3. Conclusion< / a > < / li >
2020-01-28 17:38:19 +01:00
< / ul >
< / li >
2020-01-29 17:49:25 +01:00
< / ul >
< / li >
2020-02-11 15:50:52 +01:00
< li > < a href = "#org63255f9" > 4. Estimated required actuator stroke from specified platform mobility< / a >
2019-03-22 12:03:59 +01:00
< ul >
2020-02-13 15:48:42 +01:00
< li > < a href = "#orgea4978b" > 4.1. Stewart architecture definition< / a > < / li >
2020-02-11 15:50:52 +01:00
< li > < a href = "#orgde50dd3" > 4.2. Wanted translations and rotations< / a > < / li >
< li > < a href = "#org24e45ca" > 4.3. Needed stroke for “ pure” rotations or translations< / a > < / li >
< li > < a href = "#orgf6ba90c" > 4.4. Needed stroke for “ combined” rotations or translations< / a > < / li >
2019-03-26 09:25:04 +01:00
< / ul >
< / li >
2020-02-11 15:50:52 +01:00
< li > < a href = "#orgbbbf7b3" > 5. Estimated platform mobility from specified actuator stroke< / a >
2020-01-29 17:49:25 +01:00
< ul >
2020-02-13 15:48:42 +01:00
< li > < a href = "#orgbecdc67" > 5.1. Stewart architecture definition< / a > < / li >
2020-02-11 15:50:52 +01:00
< li > < a href = "#org2c6819e" > 5.2. Pure translations< / a > < / li >
2020-01-29 13:29:29 +01:00
< / ul >
< / li >
2020-02-11 15:50:52 +01:00
< li > < a href = "#orgc4916dc" > 6. Functions< / a >
2020-01-29 13:29:29 +01:00
< ul >
2020-02-11 15:50:52 +01:00
< li > < a href = "#org26e8b28" > 6.1. < code > computeJacobian< / code > : Compute the Jacobian Matrix< / a >
2019-03-26 09:25:04 +01:00
< ul >
2020-02-13 15:48:42 +01:00
< li > < a href = "#org1a620fe" > Function description< / a > < / li >
< li > < a href = "#org9c3aa33" > Check the < code > stewart< / code > structure elements< / a > < / li >
2020-02-11 15:27:39 +01:00
< li > < a href = "#org0cd57b5" > Compute Jacobian Matrix< / a > < / li >
< li > < a href = "#orge21dcfc" > Compute Stiffness Matrix< / a > < / li >
< li > < a href = "#orgae76071" > Compute Compliance Matrix< / a > < / li >
< li > < a href = "#org78f18d7" > Populate the < code > stewart< / code > structure< / a > < / li >
2020-01-29 13:29:29 +01:00
< / ul >
< / li >
2020-02-11 15:50:52 +01:00
< li > < a href = "#orgb82066f" > 6.2. < code > inverseKinematics< / code > : Compute Inverse Kinematics< / a >
2020-01-29 13:29:29 +01:00
< ul >
2020-02-11 15:27:39 +01:00
< li > < a href = "#org89930b7" > Theory< / a > < / li >
2020-02-13 15:48:42 +01:00
< li > < a href = "#orgd97252a" > Function description< / a > < / li >
< li > < a href = "#org7be1dc4" > Optional Parameters< / a > < / li >
< li > < a href = "#orga7b29d7" > Check the < code > stewart< / code > structure elements< / a > < / li >
2020-02-11 15:27:39 +01:00
< li > < a href = "#org0d64c23" > Compute< / a > < / li >
2020-01-29 13:29:29 +01:00
< / ul >
< / li >
2020-02-11 15:50:52 +01:00
< li > < a href = "#orgf5d8f0b" > 6.3. < code > forwardKinematicsApprox< / code > : Compute the Approximate Forward Kinematics< / a >
2020-01-29 13:29:29 +01:00
< ul >
2020-02-13 15:48:42 +01:00
< li > < a href = "#org1a280b0" > Function description< / a > < / li >
< li > < a href = "#orge4b0020" > Optional Parameters< / a > < / li >
< li > < a href = "#org08a6ec5" > Check the < code > stewart< / code > structure elements< / a > < / li >
2020-02-11 15:27:39 +01:00
< li > < a href = "#orge5ade24" > Computation< / a > < / li >
2020-01-28 17:38:19 +01:00
< / ul >
< / li >
2019-03-22 12:03:59 +01:00
< / ul >
< / li >
< / ul >
< / div >
< / div >
2020-01-29 17:49:25 +01:00
< p >
The kinematic analysis of a parallel manipulator is well described in < a class = 'org-ref-reference' href = "#taghirad13_paral" > taghirad13_paral< / a > :
< / p >
< blockquote >
< p >
Kinematic analysis refers to the study of the geometry of motion of a robot, without considering the forces an torques that cause the motion.
In this analysis, the relation between the geometrical parameters of the manipulator with the final motion of the moving platform is derived and analyzed.
< / p >
< / blockquote >
< p >
The current document is divided in the following sections:
< / p >
< ul class = "org-ul" >
2020-02-11 15:50:52 +01:00
< li > Section < a href = "#orgc45d118" > 1< / a > : The Jacobian matrix is derived from the geometry of the Stewart platform. Then it is shown that the Jacobian can link velocities and forces present in the system, and thus this matrix can be very useful for both analysis and control of the Stewart platform.< / li >
< li > Section < a href = "#orgf9e4f1a" > 2< / a > : The stiffness and compliance matrices are derived from the Jacobian matrix and the stiffness of each strut.< / li >
< li > Section < a href = "#orgca82bb8" > 3< / a > : The Forward and Inverse kinematic problems are presented.< / li >
< li > Section < a href = "#orge72d811" > 4< / a > : The Inverse kinematic solution is used to estimate required actuator stroke from the wanted mobility of the Stewart platform.< / li >
2020-01-29 17:49:25 +01:00
< / ul >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-org6858f1f" class = "outline-2" >
2020-02-11 15:50:52 +01:00
< h2 id = "org6858f1f" > < span class = "section-number-2" > 1< / span > Jacobian Analysis< / h2 >
< div class = "outline-text-2" id = "text-1" >
2020-01-29 17:49:25 +01:00
< p >
2020-02-11 15:27:39 +01:00
< a id = "orgc45d118" > < / a >
2020-01-29 17:49:25 +01:00
< / p >
< p >
From < a class = 'org-ref-reference' href = "#taghirad13_paral" > taghirad13_paral< / a > :
< / p >
< blockquote >
< p >
The Jacobian matrix not only reveals the < b > relation between the joint variable velocities of a parallel manipulator to the moving platform linear and angular velocities< / b > , it also constructs the transformation needed to find the < b > actuator forces from the forces and moments acting on the moving platform< / b > .
< / p >
< / blockquote >
2020-01-29 13:29:29 +01:00
< / div >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-org8210cee" class = "outline-3" >
2020-02-11 15:50:52 +01:00
< h3 id = "org8210cee" > < span class = "section-number-3" > 1.1< / span > Jacobian Computation< / h3 >
< div class = "outline-text-3" id = "text-1-1" >
2020-01-29 17:49:25 +01:00
< p >
If we note:
< / p >
< ul class = "org-ul" >
< li > \({}^A\hat{\bm{s}}_i\) the unit vector representing the direction of the i’ th strut and expressed in frame \(\{A\}\)< / li >
< li > \({}^A\bm{b}_i\) the position vector of the i’ th joint fixed to the mobile platform and expressed in frame \(\{A\}\)< / li >
< / ul >
< p >
Then, we can compute the Jacobian with the following equation (the superscript \(A\) is ignored):
< / p >
\begin{equation*}
\bm{J} = \begin{bmatrix}
{\hat{\bm{s}}_1}^T & (\bm{b}_1 \times \hat{\bm{s}}_1)^T \\
{\hat{\bm{s}}_2}^T & (\bm{b}_2 \times \hat{\bm{s}}_2)^T \\
{\hat{\bm{s}}_3}^T & (\bm{b}_3 \times \hat{\bm{s}}_3)^T \\
{\hat{\bm{s}}_4}^T & (\bm{b}_4 \times \hat{\bm{s}}_4)^T \\
{\hat{\bm{s}}_5}^T & (\bm{b}_5 \times \hat{\bm{s}}_5)^T \\
{\hat{\bm{s}}_6}^T & (\bm{b}_6 \times \hat{\bm{s}}_6)^T
\end{bmatrix}
\end{equation*}
2020-01-29 13:29:29 +01:00
2020-01-29 17:49:25 +01:00
< p >
2020-02-11 15:27:39 +01:00
The Jacobian matrix \(\bm{J}\) can be computed using the < code > computeJacobian< / code > function (accessible < a href = "#org2387f19" > here< / a > ).
2020-01-29 17:49:25 +01:00
For instance:
< / p >
< div class = "org-src-container" >
< pre class = "src src-matlab" > stewart = computeJacobian(stewart);
< / pre >
< / div >
< p >
This will add three new matrix to the < code > stewart< / code > structure:
< / p >
< ul class = "org-ul" >
< li > < code > J< / code > the Jacobian matrix< / li >
< li > < code > K< / code > the stiffness matrix< / li >
< li > < code > C< / code > the compliance matrix< / li >
< / ul >
2020-01-29 13:29:29 +01:00
< / div >
2020-01-29 17:49:25 +01:00
< / div >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-org4d71022" class = "outline-3" >
2020-02-11 15:50:52 +01:00
< h3 id = "org4d71022" > < span class = "section-number-3" > 1.2< / span > Jacobian - Velocity loop closure< / h3 >
< div class = "outline-text-3" id = "text-1-2" >
2020-01-29 17:49:25 +01:00
< p >
The Jacobian matrix links the input joint rate \(\dot{\bm{\mathcal{L}}} = [ \dot{l}_1, \dot{l}_2, \dot{l}_3, \dot{l}_4, \dot{l}_5, \dot{l}_6 ]^T\) of each strut to the output twist vector of the mobile platform is denoted by \(\dot{\bm{X}} = [^A\bm{v}_p, {}^A\bm{\omega}]^T\):
< / p >
\begin{equation*}
\dot{\bm{\mathcal{L}}} = \bm{J} \dot{\bm{\mathcal{X}}}
\end{equation*}
< p >
The input joint rate \(\dot{\bm{\mathcal{L}}}\) can be measured by taking the derivative of the relative motion sensor in each strut.
The output twist vector can be measured with a “ Transform Sensor” block measuring the relative velocity and relative angular velocity of frame \(\{B\}\) with respect to frame \(\{A\}\).
< / p >
< p >
If the Jacobian matrix is inversible, we can also compute \(\dot{\bm{\mathcal{X}}}\) from \(\dot{\bm{\mathcal{L}}}\).
< / p >
\begin{equation*}
\dot{\bm{\mathcal{X}}} = \bm{J}^{-1} \dot{\bm{\mathcal{L}}}
\end{equation*}
2020-01-29 13:29:29 +01:00
2020-01-29 17:49:25 +01:00
< p >
The Jacobian matrix can also be used to approximate forward and inverse kinematics for small displacements.
2020-02-11 15:50:52 +01:00
This is explained in section < a href = "#org02628f3" > 3.3< / a > .
2020-01-29 17:49:25 +01:00
< / p >
< / div >
2020-01-29 13:29:29 +01:00
< / div >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-org2847e30" class = "outline-3" >
2020-02-11 15:50:52 +01:00
< h3 id = "org2847e30" > < span class = "section-number-3" > 1.3< / span > Jacobian - Static Force Transformation< / h3 >
< div class = "outline-text-3" id = "text-1-3" >
2020-01-29 17:49:25 +01:00
< p >
If we note:
< / p >
< ul class = "org-ul" >
< li > \(\bm{\tau} = [\tau_1, \tau_2, \cdots, \tau_6]^T\): vector of actuator forces applied in each strut< / li >
< li > \(\bm{\mathcal{F}} = [\bm{f}, \bm{n}]^T\): external force/torque action on the mobile platform at \(\bm{O}_B\)< / li >
< / ul >
< p >
We find that the transpose of the Jacobian matrix links the two by the following equation:
< / p >
\begin{equation*}
\bm{\mathcal{F}} = \bm{J}^T \bm{\tau}
\end{equation*}
< p >
If the Jacobian matrix is inversible, we also have the following relation:
< / p >
\begin{equation*}
\bm{\tau} = \bm{J}^{-T} \bm{\mathcal{F}}
\end{equation*}
< / div >
2020-01-29 13:29:29 +01:00
< / div >
< / div >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-org87bfd11" class = "outline-2" >
2020-02-11 15:50:52 +01:00
< h2 id = "org87bfd11" > < span class = "section-number-2" > 2< / span > Stiffness Analysis< / h2 >
< div class = "outline-text-2" id = "text-2" >
2020-01-29 17:49:25 +01:00
< p >
2020-02-11 15:27:39 +01:00
< a id = "orgf9e4f1a" > < / a >
2020-01-29 17:49:25 +01:00
< / p >
< p >
Here, we focus on the deflections of the manipulator moving platform that are the result of the external applied wrench to the mobile platform.
The amount of these deflections are a function of the applied wrench as well as the manipulator < b > structural stiffness< / b > .
< / p >
< / div >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-orgb1956e6" class = "outline-3" >
2020-02-11 15:50:52 +01:00
< h3 id = "orgb1956e6" > < span class = "section-number-3" > 2.1< / span > Computation of the Stiffness and Compliance Matrix< / h3 >
< div class = "outline-text-3" id = "text-2-1" >
2020-01-29 17:49:25 +01:00
< p >
As explain in < a href = "stewart-architecture.html" > this< / a > document, each Actuator is modeled by 3 elements in parallel:
< / p >
< ul class = "org-ul" >
< li > A spring with a stiffness \(k_{i}\)< / li >
< li > A dashpot with a damping \(c_{i}\)< / li >
< / ul >
< p >
The stiffness of the actuator \(k_i\) links the applied actuator force \(\delta \tau_i\) and the corresponding small deflection \(\delta l_i\):
< / p >
\begin{equation*}
\tau_i = k_i \delta l_i, \quad i = 1,\ \dots,\ 6
\end{equation*}
< p >
If we combine these 6 relations:
< / p >
\begin{equation*}
\bm{\tau} = \mathcal{K} \delta \bm{\mathcal{L}} \quad \mathcal{K} = \text{diag}\left[ k_1,\ \dots,\ k_6 \right]
\end{equation*}
< p >
Substituting \(\bm{\tau} = \bm{J}^{-T} \bm{\mathcal{F}}\) and \(\delta \bm{\mathcal{L}} = \bm{J} \cdot \delta \bm{\mathcal{X}}\) gives
< / p >
\begin{equation*}
\bm{\mathcal{F}} = \bm{J}^T \mathcal{K} \bm{J} \cdot \delta \bm{\mathcal{X}}
\end{equation*}
< p >
And then we identify the stiffness matrix \(\bm{K}\):
< / p >
\begin{equation*}
\bm{K} = \bm{J}^T \mathcal{K} \bm{J}
\end{equation*}
< p >
If the stiffness matrix \(\bm{K}\) is inversible, the < b > compliance matrix< / b > of the manipulator is defined as
< / p >
\begin{equation*}
\bm{C} = \bm{K}^{-1} = (\bm{J}^T \mathcal{K} \bm{J})^{-1}
\end{equation*}
< p >
The compliance matrix of a manipulator shows the mapping of the moving platform wrench applied at \(\bm{O}_B\) to its small deflection by
< / p >
\begin{equation*}
\delta \bm{\mathcal{X}} = \bm{C} \cdot \bm{\mathcal{F}}
\end{equation*}
< p >
2020-02-11 15:27:39 +01:00
The stiffness and compliance matrices are computed using the < code > computeJacobian< / code > function (accessible < a href = "#org2387f19" > here< / a > ).
2020-01-29 17:49:25 +01:00
< / p >
< / div >
2020-01-29 13:29:29 +01:00
< / div >
< / div >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-org5718735" class = "outline-2" >
2020-02-11 15:50:52 +01:00
< h2 id = "org5718735" > < span class = "section-number-2" > 3< / span > Forward and Inverse Kinematics< / h2 >
< div class = "outline-text-2" id = "text-3" >
2020-01-29 17:49:25 +01:00
< p >
2020-02-11 15:27:39 +01:00
< a id = "orgca82bb8" > < / a >
2020-01-29 17:49:25 +01:00
< / p >
< / div >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-orgebda1d9" class = "outline-3" >
2020-02-11 15:50:52 +01:00
< h3 id = "orgebda1d9" > < span class = "section-number-3" > 3.1< / span > Inverse Kinematics< / h3 >
< div class = "outline-text-3" id = "text-3-1" >
2020-01-29 17:49:25 +01:00
< p >
2020-02-11 15:27:39 +01:00
< a id = "org2f224fc" > < / a >
2020-01-29 17:49:25 +01:00
< / p >
2020-01-29 13:29:29 +01:00
2020-01-29 17:49:25 +01:00
< blockquote >
< p >
For < b > inverse kinematic analysis< / b > , it is assumed that the position \({}^A\bm{P}\) and orientation of the moving platform \({}^A\bm{R}_B\) are given and the problem is to obtain the joint variables \(\bm{\mathcal{L}} = \left[ l_1, l_2, l_3, l_4, l_5, l_6 \right]^T\).
< / p >
< / blockquote >
< p >
This problem can be easily solved using the loop closures.
< / p >
< p >
The obtain joint variables are:
< / p >
\begin{equation*}
\begin{aligned}
l_i = & \Big[ {}^A\bm{P}^T {}^A\bm{P} + {}^B\bm{b}_i^T {}^B\bm{b}_i + {}^A\bm{a}_i^T {}^A\bm{a}_i - 2 {}^A\bm{P}^T {}^A\bm{a}_i + \dots\\
& 2 {}^A\bm{P}^T \left[{}^A\bm{R}_B {}^B\bm{b}_i\right] - 2 \left[{}^A\bm{R}_B {}^B\bm{b}_i\right]^T {}^A\bm{a}_i \Big]^{1/2}
\end{aligned}
\end{equation*}
< p >
If the position and orientation of the platform lie in the feasible workspace, the solution is unique.
Otherwise, the solution gives complex numbers.
< / p >
< p >
2020-02-11 15:27:39 +01:00
This inverse kinematic solution can be obtained using the function < code > inverseKinematics< / code > (described < a href = "#orgb8859d7" > here< / a > ).
2020-01-29 17:49:25 +01:00
< / p >
< / div >
2020-01-29 13:29:29 +01:00
< / div >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-org1795522" class = "outline-3" >
2020-02-11 15:50:52 +01:00
< h3 id = "org1795522" > < span class = "section-number-3" > 3.2< / span > Forward Kinematics< / h3 >
< div class = "outline-text-3" id = "text-3-2" >
2020-01-29 17:49:25 +01:00
< p >
2020-02-11 15:27:39 +01:00
< a id = "orgf1db8ea" > < / a >
2020-01-29 17:49:25 +01:00
< / p >
< blockquote >
< p >
In < b > forward kinematic analysis< / b > , it is assumed that the vector of limb lengths \(\bm{L}\) is given and the problem is to find the position \({}^A\bm{P}\) and the orientation \({}^A\bm{R}_B\).
< / p >
< / blockquote >
< p >
This is a difficult problem that requires to solve nonlinear equations.
< / p >
2020-01-29 13:29:29 +01:00
2020-01-29 17:49:25 +01:00
< p >
In a next section, an approximate solution of the forward kinematics problem is proposed for small displacements.
< / p >
2020-01-29 13:29:29 +01:00
< / div >
< / div >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-org5a3ce80" class = "outline-3" >
2020-02-11 15:50:52 +01:00
< h3 id = "org5a3ce80" > < span class = "section-number-3" > 3.3< / span > Approximate solution of the Forward and Inverse Kinematic problem for small displacement using the Jacobian matrix< / h3 >
< div class = "outline-text-3" id = "text-3-3" >
2020-01-29 17:49:25 +01:00
< p >
2020-02-11 15:27:39 +01:00
< a id = "org02628f3" > < / a >
2020-01-29 17:49:25 +01:00
< / p >
2020-01-29 13:29:29 +01:00
2020-01-29 17:49:25 +01:00
< p >
2020-01-29 20:23:01 +01:00
For small displacements mobile platform displacement \(\delta \bm{\mathcal{X}} = [\delta x, \delta y, \delta z, \delta \theta_x, \delta \theta_y, \delta \theta_z ]^T\) around \(\bm{\mathcal{X}}_0\), the associated joint displacement can be computed using the Jacobian (approximate solution of the inverse kinematic problem):
2020-01-29 17:49:25 +01:00
< / p >
\begin{equation*}
\delta\bm{\mathcal{L}} = \bm{J} \delta\bm{\mathcal{X}}
\end{equation*}
< p >
2020-01-29 20:23:01 +01:00
Similarly, for small joint displacements \(\delta\bm{\mathcal{L}} = [ \delta l_1,\ \dots,\ \delta l_6 ]^T\) around \(\bm{\mathcal{L}}_0\), it is possible to find the induced small displacement of the mobile platform (approximate solution of the forward kinematic problem):
2020-01-29 17:49:25 +01:00
< / p >
\begin{equation*}
\delta\bm{\mathcal{X}} = \bm{J}^{-1} \delta\bm{\mathcal{L}}
\end{equation*}
< p >
These two relations solve the forward and inverse kinematic problems for small displacement in a < b > approximate< / b > way.
As the inverse kinematic can be easily solved exactly this is not much useful, however, as the forward kinematic problem is difficult to solve, this approximation can be very useful for small displacements.
< / p >
< p >
2020-02-11 15:27:39 +01:00
The function < code > forwardKinematicsApprox< / code > (described < a href = "#orgdb31434" > here< / a > ) can be used to solve the forward kinematic problem using the Jacobian matrix.
2020-01-29 17:49:25 +01:00
< / p >
2020-01-29 13:29:29 +01:00
< / div >
< / div >
2020-01-29 17:49:25 +01:00
2020-02-11 15:27:39 +01:00
< div id = "outline-container-org86b4b35" class = "outline-3" >
2020-02-11 15:50:52 +01:00
< h3 id = "org86b4b35" > < span class = "section-number-3" > 3.4< / span > Estimation of the range validity of the approximate inverse kinematics< / h3 >
< div class = "outline-text-3" id = "text-3-4" >
2020-01-29 17:49:25 +01:00
< p >
2020-02-11 15:27:39 +01:00
< a id = "org2bfd694" > < / a >
2020-02-11 15:16:07 +01:00
< / p >
< p >
2020-01-29 17:49:25 +01:00
As we know how to exactly solve the Inverse kinematic problem, we can compare the exact solution with the approximate solution using the Jacobian matrix.
For small displacements, the approximate solution is expected to work well.
We would like here to determine up to what displacement this approximation can be considered as correct.
< / p >
< p >
Then, we can determine the range for which the approximate inverse kinematic is valid.
This will also gives us the range for which the approximate forward kinematic is valid.
< / p >
2020-01-29 13:29:29 +01:00
< / div >
2020-02-13 15:48:42 +01:00
< div id = "outline-container-orgc3c7024" class = "outline-4" >
< h4 id = "orgc3c7024" > < span class = "section-number-4" > 3.4.1< / span > Stewart architecture definition< / h4 >
2020-02-11 15:50:52 +01:00
< div class = "outline-text-4" id = "text-3-4-1" >
2020-01-29 17:49:25 +01:00
< p >
We first define some general Stewart architecture.
< / p >
< div class = "org-src-container" >
2020-02-11 15:27:39 +01:00
< pre class = "src src-matlab" > stewart = initializeStewartPlatform();
stewart = initializeFramesPositions(stewart, < span class = "org-string" > 'H'< / span > , 90e< span class = "org-type" > -< / span > 3, < span class = "org-string" > 'MO_B'< / span > , 45e< span class = "org-type" > -< / span > 3);
2020-01-29 17:49:25 +01:00
stewart = generateGeneralConfiguration(stewart);
stewart = computeJointsPose(stewart);
stewart = initializeStewartPose(stewart);
stewart = initializeCylindricalPlatforms(stewart);
stewart = initializeCylindricalStruts(stewart);
stewart = initializeStrutDynamics(stewart);
stewart = initializeJointDynamics(stewart);
stewart = computeJacobian(stewart);
< / pre >
2020-01-29 13:29:29 +01:00
< / div >
2020-01-29 17:49:25 +01:00
< / div >
< / div >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-orgd83ccf3" class = "outline-4" >
2020-02-11 15:50:52 +01:00
< h4 id = "orgd83ccf3" > < span class = "section-number-4" > 3.4.2< / span > Comparison for “ pure” translations< / h4 >
< div class = "outline-text-4" id = "text-3-4-2" >
2020-01-29 17:49:25 +01:00
< p >
Let’ s first compare the perfect and approximate solution of the inverse for pure \(x\) translations.
< / p >
2019-03-26 09:25:04 +01:00
< p >
2020-01-29 17:49:25 +01:00
We compute the approximate and exact required strut stroke to have the wanted mobile platform \(x\) displacement.
2020-02-11 15:27:39 +01:00
The estimate required strut stroke for both the approximate and exact solutions are shown in Figure < a href = "#org5996f21" > 1< / a > .
The relative strut length displacement is shown in Figure < a href = "#org02d8e34" > 2< / a > .
2020-01-29 17:49:25 +01:00
< / p >
< div class = "org-src-container" >
< pre class = "src src-matlab" > Xrs = logspace(< span class = "org-type" > -< / span > 6, < span class = "org-type" > -< / span > 1, 100); < span class = "org-comment" > % Wanted X translation of the mobile platform [m]< / span >
Ls_approx = zeros(6, length(Xrs));
Ls_exact = zeros(6, length(Xrs));
< span class = "org-keyword" > for< / span > < span class = "org-variable-name" > < span class = "org-constant" > i< / span > < / span > = < span class = "org-constant" > 1:length(Xrs)< / span >
Xr = Xrs(< span class = "org-constant" > i< / span > );
2020-02-13 15:48:42 +01:00
L_approx(< span class = "org-type" > :< / span > , < span class = "org-constant" > i< / span > ) = stewart.kinematics.J< span class = "org-type" > *< / span > [Xr; 0; 0; 0; 0; 0;];
2020-01-29 17:49:25 +01:00
[< span class = "org-type" > ~< / span > , L_exact(< span class = "org-type" > :< / span > , < span class = "org-constant" > i< / span > )] = inverseKinematics(stewart, < span class = "org-string" > 'AP'< / span > , [Xr; 0; 0]);
< span class = "org-keyword" > end< / span >
< / pre >
< / div >
2020-02-11 15:27:39 +01:00
< div id = "org5996f21" class = "figure" >
2020-01-29 17:49:25 +01:00
< p > < img src = "figs/inverse_kinematics_approx_validity_x_translation.png" alt = "inverse_kinematics_approx_validity_x_translation.png" / >
2019-03-26 09:25:04 +01:00
< / p >
2020-01-29 17:49:25 +01:00
< p > < span class = "figure-number" > Figure 1: < / span > Comparison of the Approximate solution and True solution for the Inverse kinematic problem (< a href = "./figs/inverse_kinematics_approx_validity_x_translation.png" > png< / a > , < a href = "./figs/inverse_kinematics_approx_validity_x_translation.pdf" > pdf< / a > )< / p >
2019-03-22 12:03:59 +01:00
< / div >
2019-03-26 09:25:04 +01:00
2020-01-29 17:49:25 +01:00
2020-02-11 15:27:39 +01:00
< div id = "org02d8e34" class = "figure" >
2020-01-29 17:49:25 +01:00
< p > < img src = "figs/inverse_kinematics_approx_validity_x_translation_relative.png" alt = "inverse_kinematics_approx_validity_x_translation_relative.png" / >
< / p >
< p > < span class = "figure-number" > Figure 2: < / span > Relative length error by using the Approximate solution of the Inverse kinematic problem (< a href = "./figs/inverse_kinematics_approx_validity_x_translation_relative.png" > png< / a > , < a href = "./figs/inverse_kinematics_approx_validity_x_translation_relative.pdf" > pdf< / a > )< / p >
< / div >
< / div >
< / div >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-org4871c83" class = "outline-4" >
2020-02-11 15:50:52 +01:00
< h4 id = "org4871c83" > < span class = "section-number-4" > 3.4.3< / span > Conclusion< / h4 >
< div class = "outline-text-4" id = "text-3-4-3" >
2020-02-13 15:48:42 +01:00
< div class = "important" >
2019-03-26 09:25:04 +01:00
< p >
2020-01-29 17:49:25 +01:00
For small wanted displacements (up to \(\approx 1\%\) of the size of the Hexapod), the approximate inverse kinematic solution using the Jacobian matrix is quite correct.
2019-03-26 09:25:04 +01:00
< / p >
2020-02-13 15:48:42 +01:00
< / div >
2020-01-29 17:49:25 +01:00
< / div >
< / div >
< / div >
< / div >
2019-03-26 09:25:04 +01:00
2020-02-11 15:27:39 +01:00
< div id = "outline-container-org63255f9" class = "outline-2" >
2020-02-11 15:50:52 +01:00
< h2 id = "org63255f9" > < span class = "section-number-2" > 4< / span > Estimated required actuator stroke from specified platform mobility< / h2 >
< div class = "outline-text-2" id = "text-4" >
2020-01-29 17:49:25 +01:00
< p >
2020-02-11 15:27:39 +01:00
< a id = "orge72d811" > < / a >
2020-01-29 17:49:25 +01:00
< / p >
< p >
Let’ s say one want to design a Stewart platform with some specified mobility (position and orientation).
One may want to determine the required actuator stroke required to obtain the specified mobility.
This is what is analyzed in this section.
< / p >
< / div >
2020-02-13 15:48:42 +01:00
< div id = "outline-container-orgea4978b" class = "outline-3" >
< h3 id = "orgea4978b" > < span class = "section-number-3" > 4.1< / span > Stewart architecture definition< / h3 >
2020-02-11 15:50:52 +01:00
< div class = "outline-text-3" id = "text-4-1" >
2020-01-29 17:49:25 +01:00
< p >
Let’ s first define the Stewart platform architecture that we want to study.
< / p >
2019-03-26 09:25:04 +01:00
< div class = "org-src-container" >
2020-02-11 15:27:39 +01:00
< pre class = "src src-matlab" > stewart = initializeStewartPlatform();
stewart = initializeFramesPositions(stewart, < span class = "org-string" > 'H'< / span > , 90e< span class = "org-type" > -< / span > 3, < span class = "org-string" > 'MO_B'< / span > , 45e< span class = "org-type" > -< / span > 3);
2020-01-29 17:49:25 +01:00
stewart = generateGeneralConfiguration(stewart);
stewart = computeJointsPose(stewart);
stewart = initializeStewartPose(stewart);
stewart = initializeCylindricalPlatforms(stewart);
stewart = initializeCylindricalStruts(stewart);
2020-02-13 15:48:42 +01:00
stewart = initializeStrutDynamics(stewart);
2020-01-29 17:49:25 +01:00
stewart = initializeJointDynamics(stewart);
stewart = computeJacobian(stewart);
2019-03-26 09:25:04 +01:00
< / pre >
< / div >
< / div >
< / div >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-orgde50dd3" class = "outline-3" >
2020-02-11 15:50:52 +01:00
< h3 id = "orgde50dd3" > < span class = "section-number-3" > 4.2< / span > Wanted translations and rotations< / h3 >
< div class = "outline-text-3" id = "text-4-2" >
2019-03-26 09:25:04 +01:00
< p >
2020-01-29 17:49:25 +01:00
Let’ s now define the wanted extreme translations and rotations.
2019-03-26 09:25:04 +01:00
< / p >
< div class = "org-src-container" >
2020-01-29 17:49:25 +01:00
< pre class = "src src-matlab" > Tx_max = 50e< span class = "org-type" > -< / span > 6; < span class = "org-comment" > % Translation [m]< / span >
Ty_max = 50e< span class = "org-type" > -< / span > 6; < span class = "org-comment" > % Translation [m]< / span >
Tz_max = 50e< span class = "org-type" > -< / span > 6; < span class = "org-comment" > % Translation [m]< / span >
2020-01-28 17:38:19 +01:00
Rx_max = 30e< span class = "org-type" > -< / span > 6; < span class = "org-comment" > % Rotation [rad]< / span >
Ry_max = 30e< span class = "org-type" > -< / span > 6; < span class = "org-comment" > % Rotation [rad]< / span >
2020-01-29 17:49:25 +01:00
Rz_max = 0; < span class = "org-comment" > % Rotation [rad]< / span >
2019-03-26 09:25:04 +01:00
< / pre >
< / div >
< / div >
< / div >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-org24e45ca" class = "outline-3" >
2020-02-11 15:50:52 +01:00
< h3 id = "org24e45ca" > < span class = "section-number-3" > 4.3< / span > Needed stroke for “ pure” rotations or translations< / h3 >
< div class = "outline-text-3" id = "text-4-3" >
2020-01-29 17:49:25 +01:00
< p >
As a first estimation, we estimate the needed actuator stroke for “ pure” rotations and translation.
We do that using either the Inverse Kinematic solution or the Jacobian matrix as an approximation.
< / p >
< div class = "org-src-container" >
2020-02-13 15:48:42 +01:00
< pre class = "src src-matlab" > LTx = stewart.kinematics.J< span class = "org-type" > *< / span > [Tx_max 0 0 0 0 0]< span class = "org-type" > '< / span > ;
LTy = stewart.kinematics.J< span class = "org-type" > *< / span > [0 Ty_max 0 0 0 0]< span class = "org-type" > '< / span > ;
LTz = stewart.kinematics.J< span class = "org-type" > *< / span > [0 0 Tz_max 0 0 0]< span class = "org-type" > '< / span > ;
LRx = stewart.kinematics.J< span class = "org-type" > *< / span > [0 0 0 Rx_max 0 0]< span class = "org-type" > '< / span > ;
LRy = stewart.kinematics.J< span class = "org-type" > *< / span > [0 0 0 0 Ry_max 0]< span class = "org-type" > '< / span > ;
LRz = stewart.kinematics.J< span class = "org-type" > *< / span > [0 0 0 0 0 Rz_max]< span class = "org-type" > '< / span > ;
2020-01-29 17:49:25 +01:00
< / pre >
< / div >
< p >
The obtain required stroke is:
< / p >
< pre class = "example" >
From -3.8e-05[m] to 3.8e-05[m]: Total stroke = 76.1[um]
< / pre >
< p >
This is surely a low estimation of the required stroke.
< / p >
< / div >
< / div >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-orgf6ba90c" class = "outline-3" >
2020-02-11 15:50:52 +01:00
< h3 id = "orgf6ba90c" > < span class = "section-number-3" > 4.4< / span > Needed stroke for “ combined” rotations or translations< / h3 >
< div class = "outline-text-3" id = "text-4-4" >
2020-01-29 17:49:25 +01:00
< p >
We know would like to have a more precise estimation.
< / p >
< p >
To do so, we may estimate the required actuator stroke for all possible combination of translation and rotation.
< / p >
< p >
Let’ s first generate all the possible combination of maximum translation and rotations.
< / p >
< div class = "org-src-container" >
< pre class = "src src-matlab" > Ps = [2< span class = "org-type" > *< / span > (dec2bin(0< span class = "org-type" > :< / span > 5< span class = "org-type" > ^< / span > 2< span class = "org-type" > -< / span > 1,5)< span class = "org-type" > -< / span > < span class = "org-string" > '0'< / span > )< span class = "org-type" > -< / span > 1, zeros(5< span class = "org-type" > ^< / span > 2, 1)]< span class = "org-type" > .*< / span > [Tx_max Ty_max Tz_max Rx_max Ry_max Rz_max];
< / pre >
< / div >
< 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 >
< thead >
< tr >
< th scope = "col" class = "org-right" > < b > Tx [m]< / b > < / th >
< th scope = "col" class = "org-right" > < b > Ty [m]< / b > < / th >
< th scope = "col" class = "org-right" > < b > Tz [m]< / b > < / th >
< th scope = "col" class = "org-right" > < b > Rx [rad]< / b > < / th >
< th scope = "col" class = "org-right" > < b > Ry [rad]< / b > < / th >
< th scope = "col" class = "org-right" > < b > Rz [rad]< / b > < / th >
< / tr >
< / thead >
< tbody >
< tr >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > 3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< tr >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > 5.0e-05< / td >
< td class = "org-right" > -5.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > -3.0e-05< / td >
< td class = "org-right" > 0.0e+00< / td >
< / tr >
< / tbody >
< / table >
2019-03-26 09:25:04 +01:00
< p >
2020-01-29 17:49:25 +01:00
For all possible combination, we compute the required actuator stroke using the inverse kinematic solution.
2019-03-26 09:25:04 +01:00
< / p >
< div class = "org-src-container" >
2020-01-29 17:49:25 +01:00
< pre class = "src src-matlab" > L_min = 0;
L_max = 0;
< span class = "org-keyword" > for< / span > < span class = "org-variable-name" > < span class = "org-constant" > i< / span > < / span > = < span class = "org-constant" > 1:size(Ps,1)< / span >
Rx = [1 0 0;
0 cos(Ps(< span class = "org-constant" > i< / span > , 4)) < span class = "org-type" > -< / span > sin(Ps(< span class = "org-constant" > i< / span > , 4));
0 sin(Ps(< span class = "org-constant" > i< / span > , 4)) cos(Ps(< span class = "org-constant" > i< / span > , 4))];
Ry = [ cos(Ps(< span class = "org-constant" > i< / span > , 5)) 0 sin(Ps(< span class = "org-constant" > i< / span > , 5));
0 1 0;
< span class = "org-type" > -< / span > sin(Ps(< span class = "org-constant" > i< / span > , 5)) 0 cos(Ps(< span class = "org-constant" > i< / span > , 5))];
Rz = [cos(Ps(< span class = "org-constant" > i< / span > , 6)) < span class = "org-type" > -< / span > sin(Ps(< span class = "org-constant" > i< / span > , 6)) 0;
sin(Ps(< span class = "org-constant" > i< / span > , 6)) cos(Ps(< span class = "org-constant" > i< / span > , 6)) 0;
0 0 1];
ARB = Rz< span class = "org-type" > *< / span > Ry< span class = "org-type" > *< / span > Rx;
[< span class = "org-type" > ~< / span > , Ls] = inverseKinematics(stewart, < span class = "org-string" > 'AP'< / span > , Ps(< span class = "org-constant" > i< / span > , 1< span class = "org-type" > :< / span > 3)< span class = "org-type" > '< / span > , < span class = "org-string" > 'ARB'< / span > , ARB);
< span class = "org-keyword" > if< / span > min(Ls) < span class = "org-type" > < < / span > L_min
L_min = min(Ls)
< span class = "org-keyword" > end< / span >
< span class = "org-keyword" > if< / span > max(Ls) < span class = "org-type" > > < / span > L_max
L_max = max(Ls)
< span class = "org-keyword" > end< / span >
< span class = "org-keyword" > end< / span >
2019-03-26 09:25:04 +01:00
< / pre >
< / div >
2020-01-29 17:49:25 +01:00
< p >
We obtain the required actuator stroke:
< / p >
2019-03-26 09:25:04 +01:00
< pre class = "example" >
2020-01-29 17:49:25 +01:00
From -8.9e-05[m] to 8.9e-05[m]: Total stroke = 177.2[um]
2019-03-26 09:25:04 +01:00
< / pre >
2020-01-29 17:49:25 +01:00
< p >
This is probably a much realistic estimation of the required actuator stroke.
< / p >
2019-03-26 09:25:04 +01:00
< / div >
< / div >
< / div >
2020-01-29 17:49:25 +01:00
2020-02-11 15:27:39 +01:00
< div id = "outline-container-orgbbbf7b3" class = "outline-2" >
2020-02-11 15:50:52 +01:00
< h2 id = "orgbbbf7b3" > < span class = "section-number-2" > 5< / span > Estimated platform mobility from specified actuator stroke< / h2 >
< div class = "outline-text-2" id = "text-5" >
2020-01-29 17:49:25 +01:00
< p >
2020-02-11 15:27:39 +01:00
< a id = "orgeca09fb" > < / a >
2020-01-29 17:49:25 +01:00
< / p >
< p >
Here, from some value of the actuator stroke, we would like to estimate the mobility of the Stewart platform.
< / p >
< p >
2020-02-11 15:50:52 +01:00
As explained in section < a href = "#orgca82bb8" > 3< / a > , the forward kinematic problem of the Stewart platform is quite difficult to solve.
2020-01-29 17:49:25 +01:00
However, for small displacements, we can use the Jacobian as an approximate solution.
< / p >
< / div >
2020-02-13 15:48:42 +01:00
< div id = "outline-container-orgbecdc67" class = "outline-3" >
< h3 id = "orgbecdc67" > < span class = "section-number-3" > 5.1< / span > Stewart architecture definition< / h3 >
2020-02-11 15:50:52 +01:00
< div class = "outline-text-3" id = "text-5-1" >
2020-01-29 17:49:25 +01:00
< p >
Let’ s first define the Stewart platform architecture that we want to study.
< / p >
< div class = "org-src-container" >
2020-02-11 15:27:39 +01:00
< pre class = "src src-matlab" > stewart = initializeStewartPlatform();
stewart = initializeFramesPositions(stewart, < span class = "org-string" > 'H'< / span > , 90e< span class = "org-type" > -< / span > 3, < span class = "org-string" > 'MO_B'< / span > , 45e< span class = "org-type" > -< / span > 3);
2020-01-29 17:49:25 +01:00
stewart = generateGeneralConfiguration(stewart);
stewart = computeJointsPose(stewart);
stewart = initializeStewartPose(stewart);
stewart = initializeCylindricalPlatforms(stewart);
stewart = initializeCylindricalStruts(stewart);
2020-02-13 15:48:42 +01:00
stewart = initializeStrutDynamics(stewart);
2020-01-29 17:49:25 +01:00
stewart = initializeJointDynamics(stewart);
stewart = computeJacobian(stewart);
< / pre >
< / div >
< p >
Let’ s now define the actuator stroke.
< / p >
< div class = "org-src-container" >
< pre class = "src src-matlab" > L_min = < span class = "org-type" > -< / span > 50e< span class = "org-type" > -< / span > 6; < span class = "org-comment" > % [m]< / span >
L_max = 50e< span class = "org-type" > -< / span > 6; < span class = "org-comment" > % [m]< / span >
< / pre >
< / div >
< / div >
2019-03-26 09:25:04 +01:00
< / div >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-org2c6819e" class = "outline-3" >
2020-02-11 15:50:52 +01:00
< h3 id = "org2c6819e" > < span class = "section-number-3" > 5.2< / span > Pure translations< / h3 >
< div class = "outline-text-3" id = "text-5-2" >
2020-01-29 20:23:01 +01:00
< p >
Let’ s first estimate the mobility in translation when the orientation of the Stewart platform stays the same.
< / p >
< p >
As shown previously, for such small stroke, we can use the approximate Forward Dynamics solution using the Jacobian matrix:
< / p >
\begin{equation*}
\delta\bm{\mathcal{L}} = \bm{J} \delta\bm{\mathcal{X}}
\end{equation*}
< p >
To obtain the mobility “ volume” attainable by the Stewart platform when it’ s orientation is set to zero, we use the spherical coordinate \((r, \theta, \phi)\).
< / p >
< p >
For each possible value of \((\theta, \phi)\), we compute the maximum radius \(r\) attainable with the constraint that the stroke of each actuator should be between < code > L_min< / code > and < code > L_max< / code > .
< / p >
< div class = "org-src-container" >
< pre class = "src src-matlab" > thetas = linspace(0, < span class = "org-constant" > pi< / span > , 50);
phis = linspace(0, 2< span class = "org-type" > *< / span > < span class = "org-constant" > pi< / span > , 50);
rs = zeros(length(thetas), length(phis));
< span class = "org-keyword" > for< / span > < span class = "org-variable-name" > < span class = "org-constant" > i< / span > < / span > = < span class = "org-constant" > 1:length(thetas)< / span >
< span class = "org-keyword" > for< / span > < span class = "org-variable-name" > < span class = "org-constant" > j< / span > < / span > = < span class = "org-constant" > 1:length(phis)< / span >
Tx = sin(thetas(< span class = "org-constant" > i< / span > ))< span class = "org-type" > *< / span > cos(phis(< span class = "org-constant" > j< / span > ));
Ty = sin(thetas(< span class = "org-constant" > i< / span > ))< span class = "org-type" > *< / span > sin(phis(< span class = "org-constant" > j< / span > ));
Tz = cos(thetas(< span class = "org-constant" > i< / span > ));
2020-02-13 15:48:42 +01:00
dL = stewart.kinematics.J< span class = "org-type" > *< / span > [Tx; Ty; Tz; 0; 0; 0;]; < span class = "org-comment" > % dL required for 1m displacement in theta/phi direction< / span >
2020-01-29 20:23:01 +01:00
rs(< span class = "org-constant" > i< / span > , < span class = "org-constant" > j< / span > ) = max([dL(dL< span class = "org-type" > < < / span > 0)< span class = "org-type" > *< / span > L_min; dL(dL< span class = "org-type" > > < / span > 0)< span class = "org-type" > *< / span > L_max]);
< span class = "org-keyword" > end< / span >
< span class = "org-keyword" > end< / span >
< / pre >
< / div >
< p >
Now that we have found the corresponding radius \(r\), we plot the obtained mobility.
We can also approximate the mobility by a sphere with a radius equal to the minimum obtained value of \(r\), this is however a pessimistic estimation of the mobility.
< / 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" / >
< / colgroup >
< thead >
< tr >
< th scope = "col" class = "org-right" > < code > L_min< / code > [\(\mu m\)]< / th >
< th scope = "col" class = "org-right" > < code > L_max< / code > [\(\mu m\)]< / th >
< th scope = "col" class = "org-right" > < code > R< / code > [\(\mu m\)]< / th >
< / tr >
< / thead >
< tbody >
< tr >
< td class = "org-right" > -50.0< / td >
< td class = "org-right" > 50.0< / td >
< td class = "org-right" > 31.5< / td >
< / tr >
< / tbody >
< / table >
2020-02-11 15:27:39 +01:00
< div id = "orgc67ab85" class = "figure" >
2020-01-29 20:23:01 +01:00
< p > < img src = "figs/mobility_translations_null_rotation.png" alt = "mobility_translations_null_rotation.png" / >
< / p >
< p > < span class = "figure-number" > Figure 3: < / span > Obtain mobility of the Stewart platform for zero rotations (< a href = "./figs/mobility_translations_null_rotation.png" > png< / a > , < a href = "./figs/mobility_translations_null_rotation.pdf" > pdf< / a > )< / p >
< / div >
< / div >
2020-01-28 17:38:19 +01:00
< / div >
2020-01-29 17:49:25 +01:00
< / div >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-orgc4916dc" class = "outline-2" >
2020-02-11 15:50:52 +01:00
< h2 id = "orgc4916dc" > < span class = "section-number-2" > 6< / span > Functions< / h2 >
< div class = "outline-text-2" id = "text-6" >
2020-01-29 17:49:25 +01:00
< p >
2020-02-11 15:27:39 +01:00
< a id = "orgf9a6042" > < / a >
2020-01-29 17:49:25 +01:00
< / p >
2020-01-28 17:38:19 +01:00
< / div >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-org26e8b28" class = "outline-3" >
2020-02-11 15:50:52 +01:00
< h3 id = "org26e8b28" > < span class = "section-number-3" > 6.1< / span > < code > computeJacobian< / code > : Compute the Jacobian Matrix< / h3 >
< div class = "outline-text-3" id = "text-6-1" >
2020-01-28 17:38:19 +01:00
< p >
2020-02-11 15:27:39 +01:00
< a id = "org2387f19" > < / a >
2020-01-28 17:38:19 +01:00
< / p >
< p >
2020-02-11 18:04:45 +01:00
This Matlab function is accessible < a href = "../src/computeJacobian.m" > here< / a > .
2020-01-28 17:38:19 +01:00
< / p >
< / div >
2020-02-13 15:48:42 +01:00
< div id = "outline-container-org1a620fe" class = "outline-4" >
< h4 id = "org1a620fe" > Function description< / h4 >
< div class = "outline-text-4" id = "text-org1a620fe" >
2020-01-28 17:38:19 +01:00
< div class = "org-src-container" >
< pre class = "src src-matlab" > < span class = "org-keyword" > function< / span > < span class = "org-variable-name" > [stewart]< / span > = < span class = "org-function-name" > computeJacobian< / span > (< span class = "org-variable-name" > stewart< / span > )
< span class = "org-comment" > % computeJacobian -< / span >
< span class = "org-comment" > %< / span >
< span class = "org-comment" > % Syntax: [stewart] = computeJacobian(stewart)< / span >
< span class = "org-comment" > %< / span >
< span class = "org-comment" > % Inputs:< / span >
< span class = "org-comment" > % - stewart - With at least the following fields:< / span >
2020-02-11 15:16:07 +01:00
< span class = "org-comment" > % - geometry.As [3x6] - The 6 unit vectors for each strut expressed in {A}< / span >
< span class = "org-comment" > % - geometry.Ab [3x6] - The 6 position of the joints bi expressed in {A}< / span >
< span class = "org-comment" > % - actuators.K [6x1] - Total stiffness of the actuators< / span >
2020-01-28 17:38:19 +01:00
< span class = "org-comment" > %< / span >
< span class = "org-comment" > % Outputs:< / span >
< span class = "org-comment" > % - stewart - With the 3 added field:< / span >
2020-02-11 15:16:07 +01:00
< span class = "org-comment" > % - kinematics.J [6x6] - The Jacobian Matrix< / span >
< span class = "org-comment" > % - kinematics.K [6x6] - The Stiffness Matrix< / span >
< span class = "org-comment" > % - kinematics.C [6x6] - The Compliance Matrix< / span >
2020-01-28 17:38:19 +01:00
< / pre >
< / div >
< / div >
< / div >
2020-02-13 15:48:42 +01:00
< div id = "outline-container-org9c3aa33" class = "outline-4" >
< h4 id = "org9c3aa33" > Check the < code > stewart< / code > structure elements< / h4 >
< div class = "outline-text-4" id = "text-org9c3aa33" >
2020-01-28 17:38:19 +01:00
< div class = "org-src-container" >
2020-02-11 15:16:07 +01:00
< pre class = "src src-matlab" > assert(isfield(stewart.geometry, < span class = "org-string" > 'As'< / span > ), < span class = "org-string" > 'stewart.geometry should have attribute As'< / span > )
As = stewart.geometry.As;
assert(isfield(stewart.geometry, < span class = "org-string" > 'Ab'< / span > ), < span class = "org-string" > 'stewart.geometry should have attribute Ab'< / span > )
Ab = stewart.geometry.Ab;
assert(isfield(stewart.actuators, < span class = "org-string" > 'K'< / span > ), < span class = "org-string" > 'stewart.actuators should have attribute K'< / span > )
Ki = stewart.actuators.K;
2020-01-28 17:38:19 +01:00
< / pre >
< / div >
< / div >
< / div >
2020-02-11 15:16:07 +01:00
2020-02-11 15:27:39 +01:00
< div id = "outline-container-org0cd57b5" class = "outline-4" >
< h4 id = "org0cd57b5" > Compute Jacobian Matrix< / h4 >
< div class = "outline-text-4" id = "text-org0cd57b5" >
2020-01-28 17:38:19 +01:00
< div class = "org-src-container" >
2020-02-11 15:16:07 +01:00
< pre class = "src src-matlab" > J = [As< span class = "org-type" > '< / span > , cross(Ab, As)< span class = "org-type" > '< / span > ];
2020-01-28 17:38:19 +01:00
< / pre >
< / div >
< / div >
< / div >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-orge21dcfc" class = "outline-4" >
< h4 id = "orge21dcfc" > Compute Stiffness Matrix< / h4 >
< div class = "outline-text-4" id = "text-orge21dcfc" >
2020-01-28 17:38:19 +01:00
< div class = "org-src-container" >
2020-02-11 15:16:07 +01:00
< pre class = "src src-matlab" > K = J< span class = "org-type" > '*< / span > diag(Ki)< span class = "org-type" > *< / span > J;
2020-01-28 17:38:19 +01:00
< / pre >
< / div >
< / div >
< / div >
2020-02-11 15:16:07 +01:00
2020-02-11 15:27:39 +01:00
< div id = "outline-container-orgae76071" class = "outline-4" >
< h4 id = "orgae76071" > Compute Compliance Matrix< / h4 >
< div class = "outline-text-4" id = "text-orgae76071" >
2020-02-11 15:16:07 +01:00
< div class = "org-src-container" >
< pre class = "src src-matlab" > C = inv(K);
< / pre >
< / div >
< / div >
2020-01-28 17:38:19 +01:00
< / div >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-org78f18d7" class = "outline-4" >
< h4 id = "org78f18d7" > Populate the < code > stewart< / code > structure< / h4 >
< div class = "outline-text-4" id = "text-org78f18d7" >
2020-02-11 15:16:07 +01:00
< div class = "org-src-container" >
< pre class = "src src-matlab" > stewart.kinematics.J = J;
stewart.kinematics.K = K;
stewart.kinematics.C = C;
< / pre >
< / div >
< / div >
< / div >
< / div >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-orgb82066f" class = "outline-3" >
2020-02-11 15:50:52 +01:00
< h3 id = "orgb82066f" > < span class = "section-number-3" > 6.2< / span > < code > inverseKinematics< / code > : Compute Inverse Kinematics< / h3 >
< div class = "outline-text-3" id = "text-6-2" >
2020-01-28 17:38:19 +01:00
< p >
2020-02-11 15:27:39 +01:00
< a id = "orgb8859d7" > < / a >
2020-01-28 17:38:19 +01:00
< / p >
< p >
2020-02-11 18:04:45 +01:00
This Matlab function is accessible < a href = "../src/inverseKinematics.m" > here< / a > .
2020-01-28 17:38:19 +01:00
< / p >
< / div >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-org89930b7" class = "outline-4" >
< h4 id = "org89930b7" > Theory< / h4 >
< div class = "outline-text-4" id = "text-org89930b7" >
2020-02-11 15:16:07 +01:00
< p >
For inverse kinematic analysis, it is assumed that the position \({}^A\bm{P}\) and orientation of the moving platform \({}^A\bm{R}_B\) are given and the problem is to obtain the joint variables, namely, \(\bm{L} = [l_1, l_2, \dots, l_6]^T\).
< / p >
< p >
From the geometry of the manipulator, the loop closure for each limb, \(i = 1, 2, \dots, 6\) can be written as
< / p >
\begin{align*}
l_i {}^A\hat{\bm{s}}_i & = {}^A\bm{A} + {}^A\bm{b}_i - {}^A\bm{a}_i \\
& = {}^A\bm{A} + {}^A\bm{R}_b {}^B\bm{b}_i - {}^A\bm{a}_i
\end{align*}
< p >
To obtain the length of each actuator and eliminate \(\hat{\bm{s}}_i\), it is sufficient to dot multiply each side by itself:
< / p >
\begin{equation}
l_i^2 \left[ {}^A\hat{\bm{s}}_i^T {}^A\hat{\bm{s}}_i \right] = \left[ {}^A\bm{P} + {}^A\bm{R}_B {}^B\bm{b}_i - {}^A\bm{a}_i \right]^T \left[ {}^A\bm{P} + {}^A\bm{R}_B {}^B\bm{b}_i - {}^A\bm{a}_i \right]
\end{equation}
< p >
Hence, for \(i = 1, 2, \dots, 6\), each limb length can be uniquely determined by:
< / p >
\begin{equation}
l_i = \sqrt{{}^A\bm{P}^T {}^A\bm{P} + {}^B\bm{b}_i^T {}^B\bm{b}_i + {}^A\bm{a}_i^T {}^A\bm{a}_i - 2 {}^A\bm{P}^T {}^A\bm{a}_i + 2 {}^A\bm{P}^T \left[{}^A\bm{R}_B {}^B\bm{b}_i\right] - 2 \left[{}^A\bm{R}_B {}^B\bm{b}_i\right]^T {}^A\bm{a}_i}
\end{equation}
< p >
If the position and orientation of the moving platform lie in the feasible workspace of the manipulator, one unique solution to the limb length is determined by the above equation.
Otherwise, when the limbs’ lengths derived yield complex numbers, then the position or orientation of the moving platform is not reachable.
< / p >
< / div >
< / div >
2020-02-13 15:48:42 +01:00
< div id = "outline-container-orgd97252a" class = "outline-4" >
< h4 id = "orgd97252a" > Function description< / h4 >
< div class = "outline-text-4" id = "text-orgd97252a" >
2020-01-28 17:38:19 +01:00
< div class = "org-src-container" >
< pre class = "src src-matlab" > < span class = "org-keyword" > function< / span > < span class = "org-variable-name" > [Li, dLi]< / span > = < span class = "org-function-name" > inverseKinematics< / span > (< span class = "org-variable-name" > stewart< / span > , < span class = "org-variable-name" > args< / span > )
< span class = "org-comment" > % inverseKinematics - Compute the needed length of each strut to have the wanted position and orientation of {B} with respect to {A}< / span >
< span class = "org-comment" > %< / span >
< span class = "org-comment" > % Syntax: [stewart] = inverseKinematics(stewart)< / span >
< span class = "org-comment" > %< / span >
< span class = "org-comment" > % Inputs:< / span >
< span class = "org-comment" > % - stewart - A structure with the following fields< / span >
2020-02-11 15:16:07 +01:00
< span class = "org-comment" > % - geometry.Aa [3x6] - The positions ai expressed in {A}< / span >
< span class = "org-comment" > % - geometry.Bb [3x6] - The positions bi expressed in {B}< / span >
< span class = "org-comment" > % - geometry.l [6x1] - Length of each strut< / span >
2020-01-28 17:38:19 +01:00
< span class = "org-comment" > % - args - Can have the following fields:< / span >
< span class = "org-comment" > % - AP [3x1] - The wanted position of {B} with respect to {A}< / span >
< span class = "org-comment" > % - ARB [3x3] - The rotation matrix that gives the wanted orientation of {B} with respect to {A}< / span >
< span class = "org-comment" > %< / span >
< span class = "org-comment" > % Outputs:< / span >
< span class = "org-comment" > % - Li [6x1] - The 6 needed length of the struts in [m] to have the wanted pose of {B} w.r.t. {A}< / span >
< span class = "org-comment" > % - 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}< / span >
< / pre >
< / div >
< / div >
< / div >
2020-02-13 15:48:42 +01:00
< div id = "outline-container-org7be1dc4" class = "outline-4" >
< h4 id = "org7be1dc4" > Optional Parameters< / h4 >
< div class = "outline-text-4" id = "text-org7be1dc4" >
2020-01-28 17:38:19 +01:00
< div class = "org-src-container" >
< pre class = "src src-matlab" > arguments
stewart
args.AP (3,1) double {mustBeNumeric} = zeros(3,1)
args.ARB (3,3) double {mustBeNumeric} = eye(3)
< span class = "org-keyword" > end< / span >
< / pre >
< / div >
< / div >
< / div >
2020-02-13 15:48:42 +01:00
< div id = "outline-container-orga7b29d7" class = "outline-4" >
< h4 id = "orga7b29d7" > Check the < code > stewart< / code > structure elements< / h4 >
< div class = "outline-text-4" id = "text-orga7b29d7" >
2020-02-11 15:16:07 +01:00
< div class = "org-src-container" >
< pre class = "src src-matlab" > assert(isfield(stewart.geometry, < span class = "org-string" > 'Aa'< / span > ), < span class = "org-string" > 'stewart.geometry should have attribute Aa'< / span > )
Aa = stewart.geometry.Aa;
2020-01-28 17:38:19 +01:00
2020-02-11 15:16:07 +01:00
assert(isfield(stewart.geometry, < span class = "org-string" > 'Bb'< / span > ), < span class = "org-string" > 'stewart.geometry should have attribute Bb'< / span > )
Bb = stewart.geometry.Bb;
2020-01-28 17:38:19 +01:00
2020-02-11 15:16:07 +01:00
assert(isfield(stewart.geometry, < span class = "org-string" > 'l'< / span > ), < span class = "org-string" > 'stewart.geometry should have attribute l'< / span > )
l = stewart.geometry.l;
< / pre >
< / div >
2020-01-28 17:38:19 +01:00
< / div >
< / div >
2020-02-11 15:16:07 +01:00
2020-02-11 15:27:39 +01:00
< div id = "outline-container-org0d64c23" class = "outline-4" >
< h4 id = "org0d64c23" > Compute< / h4 >
< div class = "outline-text-4" id = "text-org0d64c23" >
2020-01-28 17:38:19 +01:00
< div class = "org-src-container" >
2020-02-11 15:16:07 +01:00
< pre class = "src src-matlab" > Li = sqrt(args.AP< span class = "org-type" > '*< / span > args.AP < span class = "org-type" > +< / span > diag(Bb< span class = "org-type" > '*< / span > Bb) < span class = "org-type" > +< / span > diag(Aa< span class = "org-type" > '*< / span > Aa) < span class = "org-type" > -< / span > (2< span class = "org-type" > *< / span > args.AP< span class = "org-type" > '*< / span > Aa)< span class = "org-type" > '< / span > < span class = "org-type" > +< / span > (2< span class = "org-type" > *< / span > args.AP< span class = "org-type" > '*< / span > (args.ARB< span class = "org-type" > *< / span > Bb))< span class = "org-type" > '< / span > < span class = "org-type" > -< / span > diag(2< span class = "org-type" > *< / span > (args.ARB< span class = "org-type" > *< / span > Bb)< span class = "org-type" > '*< / span > Aa));
2020-01-28 17:38:19 +01:00
< / pre >
< / div >
< div class = "org-src-container" >
2020-02-11 15:16:07 +01:00
< pre class = "src src-matlab" > dLi = Li< span class = "org-type" > -< / span > l;
2020-01-28 17:38:19 +01:00
< / pre >
< / div >
< / div >
< / div >
< / div >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-orgf5d8f0b" class = "outline-3" >
2020-02-11 15:50:52 +01:00
< h3 id = "orgf5d8f0b" > < span class = "section-number-3" > 6.3< / span > < code > forwardKinematicsApprox< / code > : Compute the Approximate Forward Kinematics< / h3 >
< div class = "outline-text-3" id = "text-6-3" >
2020-01-28 17:38:19 +01:00
< p >
2020-02-11 15:27:39 +01:00
< a id = "orgdb31434" > < / a >
2020-01-28 17:38:19 +01:00
< / p >
< p >
2020-02-11 18:04:45 +01:00
This Matlab function is accessible < a href = "../src/forwardKinematicsApprox.m" > here< / a > .
2020-01-28 17:38:19 +01:00
< / p >
< / div >
2020-02-13 15:48:42 +01:00
< div id = "outline-container-org1a280b0" class = "outline-4" >
< h4 id = "org1a280b0" > Function description< / h4 >
< div class = "outline-text-4" id = "text-org1a280b0" >
2020-01-28 17:38:19 +01:00
< div class = "org-src-container" >
< pre class = "src src-matlab" > < span class = "org-keyword" > function< / span > < span class = "org-variable-name" > [P, R]< / span > = < span class = "org-function-name" > forwardKinematicsApprox< / span > (< span class = "org-variable-name" > stewart< / span > , < span class = "org-variable-name" > args< / span > )
< span class = "org-comment" > % forwardKinematicsApprox - Computed the approximate pose of {B} with respect to {A} from the length of each strut and using< / span >
< span class = "org-comment" > % the Jacobian Matrix< / span >
< span class = "org-comment" > %< / span >
< span class = "org-comment" > % Syntax: [P, R] = forwardKinematicsApprox(stewart, args)< / span >
< span class = "org-comment" > %< / span >
< span class = "org-comment" > % Inputs:< / span >
< span class = "org-comment" > % - stewart - A structure with the following fields< / span >
2020-02-11 15:16:07 +01:00
< span class = "org-comment" > % - kinematics.J [6x6] - The Jacobian Matrix< / span >
2020-01-28 17:38:19 +01:00
< span class = "org-comment" > % - args - Can have the following fields:< / span >
< span class = "org-comment" > % - dL [6x1] - Displacement of each strut [m]< / span >
< span class = "org-comment" > %< / span >
< span class = "org-comment" > % Outputs:< / span >
< span class = "org-comment" > % - P [3x1] - The estimated position of {B} with respect to {A}< / span >
< span class = "org-comment" > % - R [3x3] - The estimated rotation matrix that gives the orientation of {B} with respect to {A}< / span >
< / pre >
< / div >
< / div >
< / div >
2020-02-13 15:48:42 +01:00
< div id = "outline-container-orge4b0020" class = "outline-4" >
< h4 id = "orge4b0020" > Optional Parameters< / h4 >
< div class = "outline-text-4" id = "text-orge4b0020" >
2020-01-28 17:38:19 +01:00
< div class = "org-src-container" >
< pre class = "src src-matlab" > arguments
stewart
args.dL (6,1) double {mustBeNumeric} = zeros(6,1)
2019-08-26 11:58:44 +02:00
< span class = "org-keyword" > end< / span >
2019-03-22 12:03:59 +01:00
< / pre >
< / div >
< / div >
< / div >
2020-01-28 17:38:19 +01:00
2020-02-13 15:48:42 +01:00
< div id = "outline-container-org08a6ec5" class = "outline-4" >
< h4 id = "org08a6ec5" > Check the < code > stewart< / code > structure elements< / h4 >
< div class = "outline-text-4" id = "text-org08a6ec5" >
2020-02-11 15:16:07 +01:00
< div class = "org-src-container" >
< pre class = "src src-matlab" > assert(isfield(stewart.kinematics, < span class = "org-string" > 'J'< / span > ), < span class = "org-string" > 'stewart.kinematics should have attribute J'< / span > )
J = stewart.kinematics.J;
< / pre >
< / div >
< / div >
< / div >
2020-02-11 15:27:39 +01:00
< div id = "outline-container-orge5ade24" class = "outline-4" >
< h4 id = "orge5ade24" > Computation< / h4 >
< div class = "outline-text-4" id = "text-orge5ade24" >
2020-01-28 17:38:19 +01:00
< p >
From a small displacement of each strut \(d\bm{\mathcal{L}}\), we can compute the
position and orientation of {B} with respect to {A} using the following formula:
\[ d \bm{\mathcal{X}} = \bm{J}^{-1} d\bm{\mathcal{L}} \]
< / p >
< div class = "org-src-container" >
2020-02-11 15:16:07 +01:00
< pre class = "src src-matlab" > X = J< span class = "org-type" > \< / span > args.dL;
2020-01-28 17:38:19 +01:00
< / pre >
< / div >
< p >
The position vector corresponds to the first 3 elements.
< / p >
< div class = "org-src-container" >
< pre class = "src src-matlab" > P = X(1< span class = "org-type" > :< / span > 3);
< / pre >
< / div >
< p >
The next 3 elements are the orientation of {B} with respect to {A} expressed
using the screw axis.
< / p >
< div class = "org-src-container" >
< pre class = "src src-matlab" > theta = norm(X(4< span class = "org-type" > :< / span > 6));
s = X(4< span class = "org-type" > :< / span > 6)< span class = "org-type" > /< / span > theta;
< / pre >
< / div >
< p >
We then compute the corresponding rotation matrix.
< / p >
< div class = "org-src-container" >
< pre class = "src src-matlab" > R = [s(1)< span class = "org-type" > ^< / span > 2< span class = "org-type" > *< / span > (1< span class = "org-type" > -< / span > cos(theta)) < span class = "org-type" > +< / span > cos(theta) , s(1)< span class = "org-type" > *< / span > s(2)< span class = "org-type" > *< / span > (1< span class = "org-type" > -< / span > cos(theta)) < span class = "org-type" > -< / span > s(3)< span class = "org-type" > *< / span > sin(theta), s(1)< span class = "org-type" > *< / span > s(3)< span class = "org-type" > *< / span > (1< span class = "org-type" > -< / span > cos(theta)) < span class = "org-type" > +< / span > s(2)< span class = "org-type" > *< / span > sin(theta);
s< span class = "org-type" > (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);< / span >
s< span class = "org-type" > (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)];< / span >
< / pre >
< / div >
< / div >
< / div >
< / div >
2019-03-22 12:03:59 +01:00
< / div >
2020-02-11 15:16:07 +01:00
2020-01-29 17:49:25 +01:00
< p >
< h1 class = 'org-ref-bib-h1' > Bibliography< / h1 >
< ul class = 'org-ref-bib' > < li > < a id = "taghirad13_paral" > [taghirad13_paral]< / a > < a name = "taghirad13_paral" > < / a > Taghirad, Parallel robots : mechanics and control, CRC Press (2013).< / li >
< / ul >
< / p >
2019-03-22 12:03:59 +01:00
< / div >
< div id = "postamble" class = "status" >
2020-01-28 17:38:19 +01:00
< p class = "author" > Author: Dehaeze Thomas< / p >
2020-02-13 15:48:42 +01:00
< p class = "date" > Created: 2020-02-12 mer. 10:22< / p >
2019-03-22 12:03:59 +01:00
< / div >
< / body >
< / html >