Stéphane Caronhttps://scaron.info/2019-10-31T00:00:00+01:00Humanoid robots in aircraft manufacturing2019-10-31T00:00:00+01:00Stéphane Carontag:scaron.info,2019-10-31:publications/humanoids-aircraft-manufacturing.html<p class="authors"><strong>Abderrahmane Kheddar</strong>, <strong>Stéphane Caron</strong>, <strong>Pierre Gergondet</strong>, <strong>Andrew Comport</strong>, <strong>Arnaud Tanguy</strong>, <strong>Christian Ott</strong>, <strong>Bernd Henze</strong>, <strong>George Mesesan</strong>, <strong>Johannes Englsberger</strong>, <strong>Máximo A. Roa</strong>, <strong>Pierre-Brice Wieber</strong>, <strong>François Chaumette</strong>, <strong>Fabien Spindler</strong>, <strong>Giuseppe Oriolo</strong>, <strong>Leonardo Lanari</strong>, <strong>Adrien Escande</strong>, <strong>Kevin Chappellet</strong>, <strong>Fumio Kanehiro</strong> and <strong>Patrice Rabaté</strong>. To appear in: Robotics and Automation Magazine, <a class="reference external" href="https://www.ieee-ras.org/publications/ram/special-issues/humanoid-robot-applications-in-real-world-scenarios">Special Issue on Humanoid Robot Applications in Real World Scenarios</a>, December 2019.</p>
<div class="section" id="abstract">
<h2>Abstract</h2>
<p>We report results from a collaborative project that investigated the deployment of humanoid robotic solutions in aircraft manufacturing for some assembly operations where access is not possible for wheeled or rail-ported robotic platforms. Recent developments in multi-contact planning and control, bipedal walking, embedded SLAM, whole-body multi-sensory task space optimization control, and contact detection and safety, suggest that humanoids could be a plausible solution for automation given the specific requirements in such large-scale manufacturing sites. The main challenge is to integrate these scientific and technological advances into two existing humanoid platforms: the position controlled HRP-4 and the torque controlled TORO. This integration effort was demonstrated in a bracket assembly operation inside a 1:1 scale A350 mockup of the front part of the fuselage at the Airbus Saint-Nazaire site. We present and discuss the main results that have been achieved in this project and provide recommendations for future work.</p>
</div>
<div class="section" id="content">
<h2>Content</h2>
<table border="1" class="colwidths-given files docutils">
<colgroup>
<col width="10%" />
<col width="90%" />
</colgroup>
<tbody valign="top">
<tr><td><img alt="pdf" class="icon" src="https://scaron.info/images/icons/pdf.png" /></td>
<td><a class="reference external" href="https://hal-lirmm.ccsd.cnrs.fr/lirmm-02303117/document">Pre-print</a></td>
</tr>
<tr><td><img alt="mp4" class="icon" src="https://scaron.info/images/icons/video.png" /></td>
<td><a class="reference external" href="https://ieeexplore.ieee.org/ielx7/100/4600619/8889461/mra2943395-kheddar-mm.zip?tp=&arnumber=8889461">Demonstration at the Airbus Saint-Nazaire factory</a></td>
</tr>
<tr><td><img alt="github" class="icon" src="https://scaron.info/images/icons/github.png" /></td>
<td><a class="reference external" href="https://github.com/stephane-caron/lipm_walking_controller/">Walking controller of HRP-4</a> (Section IV.A)</td>
</tr>
<tr><td><img alt="doi" class="icon" src="https://scaron.info/images/icons/doi.png" /></td>
<td><a class="reference external" href="https://doi.org/10.1109/MRA.2019.2943395">10.1109/MRA.2019.2943395</a></td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="bibtex">
<h2>BibTeX</h2>
<div class="highlight"><pre><span></span><span class="nc">@article</span><span class="p">{</span><span class="nl">kheddar:lirmm-02303117</span><span class="p">,</span>
<span class="na">title</span> <span class="p">=</span> <span class="s">{Humanoid robots in aircraft manufacturing}</span><span class="p">,</span>
<span class="na">author</span> <span class="p">=</span> <span class="s">{Kheddar, Abderrahmane and Caron, St{\'e}phane and Gergondet, Pierre and Comport, Andrew and Tanguy, Arnaud and Ott, Christian and Henze, Bernd and Mesesan, George and Englsberger, Johannes and Roa, M{\'a}ximo A and Wieber, Pierre-Brice and Chaumette, Fran{\c c}ois and Spindler, Fabien and Oriolo, Giuseppe and Lanari, Leonardo and Escande, Adrien and Chappellet, K{\'e}vin and Kanehiro, Fumio and RABATE, Patrice}</span><span class="p">,</span>
<span class="na">journal</span> <span class="p">=</span> <span class="s">{IEEE Robotics and Automation Magazine}</span><span class="p">,</span>
<span class="na">publisher</span> <span class="p">=</span> <span class="s">{IEEE}</span><span class="p">,</span>
<span class="na">volume</span> <span class="p">=</span> <span class="s">{26}</span><span class="p">,</span>
<span class="na">number</span> <span class="p">=</span> <span class="s">{4}</span><span class="p">,</span>
<span class="na">year</span> <span class="p">=</span> <span class="s">{2019}</span><span class="p">,</span>
<span class="na">month</span> <span class="p">=</span> <span class="nv">dec</span><span class="p">,</span>
<span class="na">doi</span> <span class="p">=</span> <span class="s">{10.1109/MRA.2019.2943395}</span><span class="p">,</span>
<span class="p">}</span>
</pre></div>
</div>
Divergent components of motion2019-10-29T00:00:00+01:00Stéphane Carontag:scaron.info,2019-10-29:talks/jrl-2019.html<p class="authors">Talk to be given at the <a class="reference external" href="http://jrl-umi3218.github.io/">CNRS-AIST Joint Robotics Laboratory (JRL)</a> on 29 October 2019.</p>
<div class="section" id="abstract">
<h2>Abstract</h2>
<p>Some nonlinear control systems admit an <a class="reference external" href="https://en.wikipedia.org/wiki/Exponential_dichotomy">exponential dichotomy</a> (Coppel, 1966), that is
to say, their dynamics can be decomposed into (exponentially) stable and
unstable components. Walking robots fall into this category, and we call their
unstable components <em>divergent components of motion</em> (DCM). The concept of DCM
has been fruitfully applied to the linear inverted pendulum (LIP) for both
walking pattern generation and balance feedback control. But DCMs can be found
for other models as well! In this talk, we will discuss DCMs for the
variable-height inverted pendulum (VHIP), an extension of the LIP where the
controller can add height variations. Ideally, we would like our robot to
behave as a LIP (nominal height) unless some perturbation occurs and the robot
resorts to the height-variation strategy, if it has to. Deciding when to use or
not this strategy may seem "smart" or predictive, but we will see that it can
be implemented straightforwardly as linear feedback over a 4D DCM.</p>
</div>
<div class="section" id="content">
<h2>Content</h2>
<table border="1" class="colwidths-given files docutils">
<colgroup>
<col width="10%" />
<col width="90%" />
</colgroup>
<tbody valign="top">
<tr><td><img alt="pdf" class="icon" src="https://scaron.info/images/icons/pdf.png" /></td>
<td><a class="reference external" href="/slides/jrl-2019.pdf">Slides</a></td>
</tr>
<tr><td><img alt="mp4" class="icon" src="https://scaron.info/images/icons/video.png" /></td>
<td><a class="reference external" href="https://scaron.info/videos/vhip-stabilization.mp4">Video</a></td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="references">
<h2>References</h2>
<table border="1" class="colwidths-given files docutils">
<colgroup>
<col width="10%" />
<col width="90%" />
</colgroup>
<tbody valign="top">
<tr><td><img alt="pdf" class="icon" src="https://scaron.info/images/icons/pdf.png" /></td>
<td><a class="reference external" href="https://hal.archives-ouvertes.fr/hal-02289919/document">Feedback control of a 4D DCM for the variable-height inverted pendulum</a></td>
</tr>
<tr><td><img alt="pdf" class="icon" src="https://scaron.info/images/icons/pdf.png" /></td>
<td><a class="reference external" href="https://hal.archives-ouvertes.fr/hal-01689331/document">Walking pattern generation with height variations</a></td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="discussion">
<h2>Discussion</h2>
<p>Thanks to all the people who attended the presentations and asked meaningful
questions about it. Feel free to write me directly if you have any other
question related to this talk.</p>
<p><strong>What matrices did you use to generate the figure on slide 4?</strong></p>
<blockquote>
<p>This figure corresponds to:</p>
<ul class="simple">
<li><span class="math">\(A = \begin{bmatrix} +2 & 1 \\ 0 & +1 \end{bmatrix}\)</span> for <span class="math">\(\mathrm{eig}(A) = \{2, 1\}\)</span></li>
<li><span class="math">\(A = \begin{bmatrix} -2 & 1 \\ 0 & +1 \end{bmatrix}\)</span> for <span class="math">\(\mathrm{eig}(A) = \{-2, 1\}\)</span></li>
<li><span class="math">\(A = \begin{bmatrix} -2 & 1 \\ 0 & -1 \end{bmatrix}\)</span> for <span class="math">\(\mathrm{eig}(A) = \{-2, -1\}\)</span></li>
</ul>
</blockquote>
<p><strong>Why did you seem to doubt that ω is a DCM, isn't it clearly divergent?</strong></p>
<blockquote>
Yes, the point I had doubts on is about the "of motion" part. Previously,
when the DCM was directly computed by linear combination of the CoM
position and velocity, it was clear that "it diverges" and "it is a
component of motion" imply that it is a DCM. But here, <span class="math">\(\omega\)</span>
appears as a technical choice we make in order to diagonalize the
state-transition matrix after changing variable.</blockquote>
<p><strong>How do you choose the remaining proportional gain on slide 12?</strong></p>
<blockquote>
On the real robot, it will depend on your control cycle and in particular
on the bandwidth of the force control loop (admittance control on our
robots, see slide 26). DCM and force control gains are coupled when the two
are run at roughly the same frequency, as is the case here, and we are not
modeling this coupling. For practical advice, check out this note on
<a class="reference external" href="https://github.com/stephane-caron/lipm_walking_controller/wiki/Tuning-the-stabilizer">tuning stabilizer gains</a>.</blockquote>
<p><strong>How did you select the poles in the final least-squares formulation?</strong></p>
<blockquote>
In general we could have four gains on the diagonal of the closed-loop
state-transition matrix, but in practice we often use the same gains for
different directions (for instance, the same gain for both sagittal and
lateral DCM feedback in the LIP). I followed this practice, using a single
normalized gain <span class="math">\(k > 1\)</span> and scaling it on each axis by a factor
consistent with the equations of motion.</blockquote>
<p><strong>Is there unicity of the DCMs or exponential dichotomy?</strong></p>
<blockquote>
No! For instance, in a <a class="reference external" href="/publications/icra-2018.html">previous work</a> we
had used a different DCM for the VHIP whose formula included the ZMP as
well. Multiplying a DCM by a non-zero scalar also yields a DCM, there may
be "classes" of equivalent DCMs for some equivalence relation, but I wonder
what it could be...</blockquote>
</div>
<script type='text/javascript'>if (!document.getElementById('mathjaxscript_pelican_#%@#$@#')) {
var mathjaxscript = document.createElement('script');
mathjaxscript.id = 'mathjaxscript_pelican_#%@#$@#';
mathjaxscript.type = 'text/javascript';
mathjaxscript.src = '/MathJax/MathJax.js?config=TeX-AMS-MML_HTMLorMML';
mathjaxscript[(window.opera ? "innerHTML" : "text")] =
"MathJax.Hub.Config({" +
" config: ['MMLorHTML.js']," +
" TeX: { extensions: ['AMSmath.js','AMSsymbols.js','noErrors.js','noUndefined.js'], equationNumbers: { autoNumber: 'AMS' } }," +
" jax: ['input/TeX','input/MathML','output/HTML-CSS']," +
" extensions: ['tex2jax.js','mml2jax.js','MathMenu.js','MathZoom.js']," +
" displayAlign: 'center'," +
" displayIndent: '0em'," +
" showMathMenu: true," +
" tex2jax: { " +
" inlineMath: [ ['\\\\(','\\\\)'] ], " +
" displayMath: [ ['$$','$$'] ]," +
" processEscapes: true," +
" preview: 'TeX'," +
" }, " +
" 'HTML-CSS': { " +
" styles: { '.MathJax_Display, .MathJax .mo, .MathJax .mi, .MathJax .mn': {color: '#333 ! important'} }, linebreaks: { automatic: false, width: 'container' }" +
" }, " +
" 'TeX': { " +
" Macros: { " +
" defeq: \"{\\\\stackrel{\\\\mathrm{def}}{=}}\"," +
" Ld: \"{\\\\dot{L}}\"," +
" LdG: \"{\\\\dot{L}_G}\"," +
" bfA: \"{\\\\boldsymbol{A}}\"," +
" bfB: \"{\\\\boldsymbol{B}}\"," +
" bfC: \"{\\\\boldsymbol{C}}\"," +
" bfD: \"{\\\\boldsymbol{D}}\"," +
" bfE: \"{\\\\boldsymbol{E}}\"," +
" bfF: \"{\\\\boldsymbol{F}}\"," +
" bfG: \"{\\\\boldsymbol{G}}\"," +
" bfH: \"{\\\\boldsymbol{H}}\"," +
" bfI: \"{\\\\boldsymbol{I}}\"," +
" bfJ: \"{\\\\boldsymbol{J}}\"," +
" bfK: \"{\\\\boldsymbol{K}}\"," +
" bfL: \"{\\\\boldsymbol{L}}\"," +
" bfM: \"{\\\\boldsymbol{M}}\"," +
" bfN: \"{\\\\boldsymbol{N}}\"," +
" bfO: \"{\\\\boldsymbol{O}}\"," +
" bfP: \"{\\\\boldsymbol{P}}\"," +
" bfQ: \"{\\\\boldsymbol{Q}}\"," +
" bfR: \"{\\\\boldsymbol{R}}\"," +
" bfS: \"{\\\\boldsymbol{S}}\"," +
" bfT: \"{\\\\boldsymbol{T}}\"," +
" bfU: \"{\\\\boldsymbol{U}}\"," +
" bfV: \"{\\\\boldsymbol{V}}\"," +
" bfW: \"{\\\\boldsymbol{W}}\"," +
" bfX: \"{\\\\boldsymbol{X}}\"," +
" bfY: \"{\\\\boldsymbol{Y}}\"," +
" bfZ: \"{\\\\boldsymbol{Z}}\"," +
" bfa: \"{\\\\boldsymbol{a}}\"," +
" bfb: \"{\\\\boldsymbol{b}}\"," +
" bfc: \"{\\\\boldsymbol{c}}\"," +
" bfd: \"{\\\\boldsymbol{d}}\"," +
" bfe: \"{\\\\boldsymbol{e}}\"," +
" bff: \"{\\\\boldsymbol{f}}\"," +
" bfg: \"{\\\\boldsymbol{g}}\"," +
" bfh: \"{\\\\boldsymbol{h}}\"," +
" bfi: \"{\\\\boldsymbol{i}}\"," +
" bfj: \"{\\\\boldsymbol{j}}\"," +
" bfk: \"{\\\\boldsymbol{k}}\"," +
" bfl: \"{\\\\boldsymbol{l}}\"," +
" bfm: \"{\\\\boldsymbol{m}}\"," +
" bfn: \"{\\\\boldsymbol{n}}\"," +
" bfo: \"{\\\\boldsymbol{o}}\"," +
" bfp: \"{\\\\boldsymbol{p}}\"," +
" bfq: \"{\\\\boldsymbol{q}}\"," +
" bfr: \"{\\\\boldsymbol{r}}\"," +
" bfs: \"{\\\\boldsymbol{s}}\"," +
" bft: \"{\\\\boldsymbol{t}}\"," +
" bfu: \"{\\\\boldsymbol{u}}\"," +
" bfv: \"{\\\\boldsymbol{v}}\"," +
" bfw: \"{\\\\boldsymbol{w}}\"," +
" bfx: \"{\\\\boldsymbol{x}}\"," +
" bfy: \"{\\\\boldsymbol{y}}\"," +
" bfz: \"{\\\\boldsymbol{z}}\"," +
" bfalpha: \"{\\\\boldsymbol{\\\\alpha}}\"," +
" bfxi: \"{\\\\boldsymbol{\\\\xi}}\"," +
" bfbeta: \"{\\\\boldsymbol{\\\\beta}}\"," +
" bfgamma: \"{\\\\boldsymbol{\\\\gamma}}\"," +
" bftau: \"{\\\\boldsymbol{\\\\tau}}\"," +
" bfomega: \"{\\\\boldsymbol{\\\\omega}}\"," +
" calA: \"{\\\\cal A}\"," +
" calB: \"{\\\\cal B}\"," +
" calC: \"{\\\\cal C}\"," +
" calD: \"{\\\\cal D}\"," +
" calE: \"{\\\\cal E}\"," +
" calF: \"{\\\\cal F}\"," +
" calG: \"{\\\\cal G}\"," +
" calH: \"{\\\\cal H}\"," +
" calI: \"{\\\\cal I}\"," +
" calJ: \"{\\\\cal J}\"," +
" calK: \"{\\\\cal K}\"," +
" calL: \"{\\\\cal L}\"," +
" calM: \"{\\\\cal M}\"," +
" calN: \"{\\\\cal N}\"," +
" calO: \"{\\\\cal O}\"," +
" calP: \"{\\\\cal P}\"," +
" calQ: \"{\\\\cal Q}\"," +
" calR: \"{\\\\cal R}\"," +
" calS: \"{\\\\cal S}\"," +
" calT: \"{\\\\cal T}\"," +
" calU: \"{\\\\cal U}\"," +
" calV: \"{\\\\cal V}\"," +
" calW: \"{\\\\cal W}\"," +
" calX: \"{\\\\cal X}\"," +
" calY: \"{\\\\cal Y}\"," +
" calZ: \"{\\\\cal Z}\"," +
" d: [\"{\\\\rm d}{#1}\", 1]," +
" bfcd: \"{\\\\dot{\\\\bfc}}\"," +
" bfpd: \"{\\\\dot{\\\\bfp}}\"," +
" bfpdd: \"{\\\\ddot{\\\\bfp}}\"," +
" dim: \"{\\\\rm dim}\"," +
" p: \"{\\\\boldsymbol{p}}\"," +
" q: \"{\\\\boldsymbol{q}}\"," +
" qd: \"{\\\\dot{\\\\bfq}}\"," +
" qdd: \"{\\\\ddot{\\\\bfq}}\"," +
" xd: \"{\\\\dot{x}}\"," +
" xdd: \"{\\\\ddot{x}}\"," +
" yd: \"{\\\\dot{y}}\"," +
" ydd: \"{\\\\ddot{y}}\"," +
" zd: \"{\\\\dot{z}}\"," +
" zdd: \"{\\\\ddot{z}}\"," +
" defeq: \"{\\\\stackrel{\\\\mathrm{def}}{\\\\ =\\\\ }}\"," +
" } " +
" } " +
"}); ";
(document.body || document.getElementsByTagName('head')[0]).appendChild(mathjaxscript);
}
</script>Lower body control of a semi-autonomous avatar in Virtual Reality: Balance and Locomotion of a 3D Bipedal Model2019-10-15T00:00:00+02:00Stéphane Carontag:scaron.info,2019-10-15:publications/vrst-2019.html<p class="authors"><strong>Vincent Thomasset</strong>, <strong>Stéphane Caron</strong> and <strong>Vincent Weistroffer</strong>. ACM
Symposium on Virtual Reality Software and Technology, Parramatta, Australia,
November 2019.</p>
<div class="section" id="abstract">
<h2>Abstract</h2>
<p>Animated virtual humans may rely on full-body tracking system to reproduce user
motions. In this paper, we reduce tracking to the upper-body and reconstruct
the lower body to follow autonomously its upper counterpart. Doing so reduces
the number of sensors required, making the application of virtual humans
simpler and cheaper. It also enable deployment in cluttered scenes where the
lower body is often hidden. The contribution here is the inversion of the
well-known capture problem for bipedal walking. It determines footsteps rather
than center-of-mass motions and yet can be solved with an off-the-shelf capture
problem solver. The quality of our method is assessed in real-time tracking
experiments on a wide variety of movements.</p>
</div>
<div class="section" id="content">
<h2>Content</h2>
<table border="1" class="colwidths-given files docutils">
<colgroup>
<col width="10%" />
<col width="90%" />
</colgroup>
<tbody valign="top">
<tr><td><img alt="pdf" class="icon" src="https://scaron.info/images/icons/pdf.png" /></td>
<td><a class="reference external" href="https://dl.acm.org/ft_gateway.cfm?id=3364240&ftid=2096605&dwn=1">Paper</a></td>
</tr>
<tr><td><img alt="mp4" class="icon" src="https://scaron.info/images/icons/video.png" /></td>
<td><a class="reference external" href="https://dl.acm.org/ft_gateway.cfm?id=3364240&type=avi&path=%2F3370000%2F3364240%2Fsupp%2FVRST2019%2Eavi&supp=1&dwn=1">Accompanying video</a></td>
</tr>
<tr><td><img alt="doi" class="icon" src="https://scaron.info/images/icons/doi.png" /></td>
<td><a class="reference external" href="https://doi.org/10.1145/3359996.3364240">10.1145/3359996.3364240</a></td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="bibtex">
<h2>BibTeX</h2>
<div class="highlight"><pre><span></span><span class="nc">@inproceedings</span><span class="p">{</span><span class="nl">thomasset2019vrst</span><span class="p">,</span>
<span class="na">title</span> <span class="p">=</span> <span class="s">{Lower body control of a semi-autonomous avatar in Virtual Reality: Balance and Locomotion of a 3D Bipedal Model}</span><span class="p">,</span>
<span class="na">author</span> <span class="p">=</span> <span class="s">{Thomasset, Vincent and Caron, St{\'e}phane and Weistroffer, Vincent}</span><span class="p">,</span>
<span class="na">booktitle</span> <span class="p">=</span> <span class="s">{ACM Symposium on Virtual Reality Software and Technology}</span><span class="p">,</span>
<span class="na">year</span> <span class="p">=</span> <span class="s">{2019}</span><span class="p">,</span>
<span class="na">month</span> <span class="p">=</span> <span class="nv">nov</span><span class="p">,</span>
<span class="p">}</span>
</pre></div>
</div>
Capture point2019-10-14T00:00:00+02:00Stéphane Carontag:scaron.info,2019-10-14:teaching/capture-point.html<p>The <em>capture point</em> is a characteristic point of the <a class="reference external" href="/teaching/linear-inverted-pendulum-model.html">linear inverted pendulum
model</a>. It was coined by
<a class="reference external" href="https://doi.org/10.1109/ICHR.2006.321385">Pratt et al. (2006)</a> to address a
question of push recovery: where should the robot step (instantaneously) to
eliminate linear momentum <span class="math">\(m \bfpd_G\)</span> and come (asymptotically) to a
stop?</p>
<div class="section" id="derivation">
<h2>Derivation</h2>
<p>Let us start from the equation of motion of the system:</p>
<div class="math">
\begin{equation*}
\bfpdd_G = \omega^2 (\bfp_G - \bfp_Z)
\end{equation*}
</div>
<p>We assume that the robot steps instantly at time <span class="math">\(t=0\)</span> and maintains its
<a class="reference external" href="/teaching/zero-tilting-moment-point.html">ZMP</a> at a constant location in its
new foothold, so that <span class="math">\(\bfp_Z\)</span> is stationary. Given that the natural
frequency <span class="math">\(\omega\)</span> of the pendulum is also a constant, we can solve this
second-order linear differential equation as:</p>
<div class="math">
\begin{equation*}
\bfp_G(t) = \displaystyle \bfp_Z + \frac{e^{\omega t}}{2} \left[\bfp_G(0) +
\frac{\bfpd_G(0)}{\omega} - \bfp_Z\right] + \frac{e^{-\omega t}}{2}
\left[\bfp_G(0) - \frac{\bfpd_G(0)}{\omega} - \bfp_Z\right]
\end{equation*}
</div>
<p>This function is the sum of a stationary term <span class="math">\(\bfp_Z\)</span>, a convergent term factored by <span class="math">\(e^{-\omega t}\)</span> that vanishes as <span class="math">\(t \to \infty\)</span>, and a term factored by <span class="math">\(e^{\omega t}\)</span> that diverges as <span class="math">\(t \to \infty\)</span>. Let us define the <em>capture point</em> as:</p>
<div class="math">
\begin{equation*}
\bfp_C \defeq \bfp_G + \frac{\bfpd_G}{\omega}
\end{equation*}
</div>
<p>The divergent term in <span class="math">\(\bfp_G(t)\)</span> is then <span class="math">\(e^{\omega t}/2
(\bfp_C(0) - \bfp_Z)\)</span>. In particular, the <em>only</em> way for the center of mass
trajectory to be bounded is for the stationary ZMP to be equal to the
instantaneous capture point:</p>
<div class="math">
\begin{equation*}
\bfp_Z = \bfp_C(0) \ \Longrightarrow \ \bfp_G(t) \underset{t \to
\infty}{\longrightarrow} \bfp_C(0)
\end{equation*}
</div>
<p>We can thus interpret the capture point as a point where the robot should step
(shift its ZMP) in order to come (asymptotically) to a stop.</p>
</div>
<div class="section" id="discussion">
<h2>Discussion</h2>
<p>The capture point is a <a class="reference external" href="/teaching/divergent-component-of-motion.html">divergent component of motion</a> of the linear inverted
pendulum. Shifting the ZMP to the capture point prevents divergence from the
unstable dynamics of the model, but does not control the other (stable)
component. In effect, the system comes to a stop following its <em>natural</em>
dynamics:</p>
<div class="math">
\begin{equation*}
\bfpd_G = \omega (\bfp_C - \bfp_G)
\end{equation*}
</div>
<p>This phenomenon is noticable in <a class="reference external" href="/teaching/how-do-biped-robots-walk.html#walking-stabilization">balance controllers</a> based on
capture point feedback such as <a class="reference external" href="https://doi.org/10.1109/IROS.2011.6094435">Englsberger et al. (2011)</a> and <a class="reference external" href="https://doi.org/10.1109/HUMANOIDS.2012.6651601">Morisawa et al. (2012)</a>. Take the robot standing,
push it in a given direction and sustain your push, then suddenly release it:
the robot will come back to its reference standing position following its
natural dynamics (which only depend on <span class="math">\(\omega\)</span>, <em>i.e.</em> gravity and the
height of the center of mass), regardless of the values of the various feedback
gains used in the balance controller. You can for instance test this behavior
in dynamic simulations with the <a class="reference external" href="https://github.com/stephane-caron/lipm_walking_controller/">lipm_walking_controller</a>.</p>
<p>This behavior highlights how balance controllers based on capture-point
feedback are not trying to come to a stop as fast as possible. Rather, they
focus on preventing divergence, and leverage passive dynamics to absorb
undesired linear momentum. When using linear feedback, <a class="reference external" href="https://doi.org/10.1109/ROBOT.2009.5152284">Sugihara (2009)</a> showed that this approach
maximizes the basin of attraction of the resulting controller.</p>
</div>
<div class="section" id="boundedness-condition">
<h2>Boundedness condition</h2>
<p>The derivation above can be generalized to the case where <span class="math">\(\bfp_Z(t)\)</span> is
time-varying rather than time-invariant. Consider the equation of motion split
as follows into divergent and convergent components:</p>
<div class="math">
\begin{equation*}
\begin{array}{rcl}
\bfpd_C & = & \omega (\bfp_C - \bfp_Z) \\
\bfpd_G & = & \omega (\bfp_C - \bfp_G)
\end{array}
\end{equation*}
</div>
<p>The capture point diverges away from the ZMP while the center of mass is
attracted to the capture point:</p>
<img alt="Decoupled dynamics between the ZMP, capture point and center of mass" class="center max-height-200px max-width-90pct" src="https://scaron.info/figures/zmp-cp-com.png" />
<p>As the center-of-mass dynamics are convergent, the system diverges <em>if and only
if</em> its capture point diverges. We can therefore focus on the
capture point dynamics alone.</p>
<p>The solution to a first-order linear time-varying differential equation is:</p>
<div class="math">
\begin{equation*}
\dot{\bfy}(t) - a(t) \bfy(t) = \bfb(t)
\ \Longrightarrow \
\bfy(t) = e^{A(t)} \left(\bfy(0) + \int_{\tau=0}^t \bfb(\tau) e^{-A(\tau)}
{\rm d} \tau \right)
\end{equation*}
</div>
<p>where <span class="math">\(A\)</span> is the antiderivative of <span class="math">\(a\)</span> such that <span class="math">\(A(0)=0\)</span>.
Applied to capture point dynamics, this formula becomes:</p>
<div class="math">
\begin{equation*}
\bfp_C(t) = e^{\omega t} \left(\bfp_C(0) - \omega \int_{\tau=0}^t \bfp_Z(t)
e^{-\omega \tau} {\rm d}\tau\right)
\end{equation*}
</div>
<p>We can check how, in the previous case where <span class="math">\(\bfp_Z\)</span> is stationary, this
formula becomes:</p>
<div class="math">
\begin{equation*}
\bfp_C(t) = \bfp_Z + e^{\omega t} (\bfp_C(0) - \bfp_Z)
\end{equation*}
</div>
<p>The capture point trajectory is then bounded if and only if <span class="math">\(\bfp_Z =
\bfp_C(0)\)</span>, which is indeed the result we obtained above. In the general case,
the capture point stays bounded if and only if:</p>
<div class="math">
\begin{equation*}
\bfp_C(0) = \omega \int_{\tau=0}^t \bfp_Z(t) e^{-\omega \tau} {\rm d}\tau
\end{equation*}
</div>
<p>This condition was coined <em>boundedness condition</em> by <a class="reference external" href="https://doi.org/10.1109/HUMANOIDS.2014.7041478">Lanari et al. (2014)</a>. It relates <em>future</em> system
inputs to the present state, and characterizes the subset of these inputs that
will actually stabilize the system in the long run. The boundedness condition
is, for instance, a core component of the walking pattern generator from
<a class="reference external" href="https://arxiv.org/pdf/1901.08505.pdf">Scianca et al. (2019)</a>. It can also be
applied to more general reduced models such as the <a class="reference external" href="/publications/tro-2019.html">variable-height inverted
pendulum</a>.</p>
</div>
<div class="section" id="to-go-further">
<h2>To go further</h2>
<p>The notion of <a class="reference external" href="/teaching/divergent-component-of-motion.html">divergent component of motion</a> behind the capture point
reaches beyond the linear inverted pendulum model. Check it out for extensions
to more advanced balance control.</p>
</div>
<script type='text/javascript'>if (!document.getElementById('mathjaxscript_pelican_#%@#$@#')) {
var mathjaxscript = document.createElement('script');
mathjaxscript.id = 'mathjaxscript_pelican_#%@#$@#';
mathjaxscript.type = 'text/javascript';
mathjaxscript.src = '/MathJax/MathJax.js?config=TeX-AMS-MML_HTMLorMML';
mathjaxscript[(window.opera ? "innerHTML" : "text")] =
"MathJax.Hub.Config({" +
" config: ['MMLorHTML.js']," +
" TeX: { extensions: ['AMSmath.js','AMSsymbols.js','noErrors.js','noUndefined.js'], equationNumbers: { autoNumber: 'AMS' } }," +
" jax: ['input/TeX','input/MathML','output/HTML-CSS']," +
" extensions: ['tex2jax.js','mml2jax.js','MathMenu.js','MathZoom.js']," +
" displayAlign: 'center'," +
" displayIndent: '0em'," +
" showMathMenu: true," +
" tex2jax: { " +
" inlineMath: [ ['\\\\(','\\\\)'] ], " +
" displayMath: [ ['$$','$$'] ]," +
" processEscapes: true," +
" preview: 'TeX'," +
" }, " +
" 'HTML-CSS': { " +
" styles: { '.MathJax_Display, .MathJax .mo, .MathJax .mi, .MathJax .mn': {color: '#333 ! important'} }, linebreaks: { automatic: false, width: 'container' }" +
" }, " +
" 'TeX': { " +
" Macros: { " +
" defeq: \"{\\\\stackrel{\\\\mathrm{def}}{=}}\"," +
" Ld: \"{\\\\dot{L}}\"," +
" LdG: \"{\\\\dot{L}_G}\"," +
" bfA: \"{\\\\boldsymbol{A}}\"," +
" bfB: \"{\\\\boldsymbol{B}}\"," +
" bfC: \"{\\\\boldsymbol{C}}\"," +
" bfD: \"{\\\\boldsymbol{D}}\"," +
" bfE: \"{\\\\boldsymbol{E}}\"," +
" bfF: \"{\\\\boldsymbol{F}}\"," +
" bfG: \"{\\\\boldsymbol{G}}\"," +
" bfH: \"{\\\\boldsymbol{H}}\"," +
" bfI: \"{\\\\boldsymbol{I}}\"," +
" bfJ: \"{\\\\boldsymbol{J}}\"," +
" bfK: \"{\\\\boldsymbol{K}}\"," +
" bfL: \"{\\\\boldsymbol{L}}\"," +
" bfM: \"{\\\\boldsymbol{M}}\"," +
" bfN: \"{\\\\boldsymbol{N}}\"," +
" bfO: \"{\\\\boldsymbol{O}}\"," +
" bfP: \"{\\\\boldsymbol{P}}\"," +
" bfQ: \"{\\\\boldsymbol{Q}}\"," +
" bfR: \"{\\\\boldsymbol{R}}\"," +
" bfS: \"{\\\\boldsymbol{S}}\"," +
" bfT: \"{\\\\boldsymbol{T}}\"," +
" bfU: \"{\\\\boldsymbol{U}}\"," +
" bfV: \"{\\\\boldsymbol{V}}\"," +
" bfW: \"{\\\\boldsymbol{W}}\"," +
" bfX: \"{\\\\boldsymbol{X}}\"," +
" bfY: \"{\\\\boldsymbol{Y}}\"," +
" bfZ: \"{\\\\boldsymbol{Z}}\"," +
" bfa: \"{\\\\boldsymbol{a}}\"," +
" bfb: \"{\\\\boldsymbol{b}}\"," +
" bfc: \"{\\\\boldsymbol{c}}\"," +
" bfd: \"{\\\\boldsymbol{d}}\"," +
" bfe: \"{\\\\boldsymbol{e}}\"," +
" bff: \"{\\\\boldsymbol{f}}\"," +
" bfg: \"{\\\\boldsymbol{g}}\"," +
" bfh: \"{\\\\boldsymbol{h}}\"," +
" bfi: \"{\\\\boldsymbol{i}}\"," +
" bfj: \"{\\\\boldsymbol{j}}\"," +
" bfk: \"{\\\\boldsymbol{k}}\"," +
" bfl: \"{\\\\boldsymbol{l}}\"," +
" bfm: \"{\\\\boldsymbol{m}}\"," +
" bfn: \"{\\\\boldsymbol{n}}\"," +
" bfo: \"{\\\\boldsymbol{o}}\"," +
" bfp: \"{\\\\boldsymbol{p}}\"," +
" bfq: \"{\\\\boldsymbol{q}}\"," +
" bfr: \"{\\\\boldsymbol{r}}\"," +
" bfs: \"{\\\\boldsymbol{s}}\"," +
" bft: \"{\\\\boldsymbol{t}}\"," +
" bfu: \"{\\\\boldsymbol{u}}\"," +
" bfv: \"{\\\\boldsymbol{v}}\"," +
" bfw: \"{\\\\boldsymbol{w}}\"," +
" bfx: \"{\\\\boldsymbol{x}}\"," +
" bfy: \"{\\\\boldsymbol{y}}\"," +
" bfz: \"{\\\\boldsymbol{z}}\"," +
" bfalpha: \"{\\\\boldsymbol{\\\\alpha}}\"," +
" bfxi: \"{\\\\boldsymbol{\\\\xi}}\"," +
" bfbeta: \"{\\\\boldsymbol{\\\\beta}}\"," +
" bfgamma: \"{\\\\boldsymbol{\\\\gamma}}\"," +
" bftau: \"{\\\\boldsymbol{\\\\tau}}\"," +
" bfomega: \"{\\\\boldsymbol{\\\\omega}}\"," +
" calA: \"{\\\\cal A}\"," +
" calB: \"{\\\\cal B}\"," +
" calC: \"{\\\\cal C}\"," +
" calD: \"{\\\\cal D}\"," +
" calE: \"{\\\\cal E}\"," +
" calF: \"{\\\\cal F}\"," +
" calG: \"{\\\\cal G}\"," +
" calH: \"{\\\\cal H}\"," +
" calI: \"{\\\\cal I}\"," +
" calJ: \"{\\\\cal J}\"," +
" calK: \"{\\\\cal K}\"," +
" calL: \"{\\\\cal L}\"," +
" calM: \"{\\\\cal M}\"," +
" calN: \"{\\\\cal N}\"," +
" calO: \"{\\\\cal O}\"," +
" calP: \"{\\\\cal P}\"," +
" calQ: \"{\\\\cal Q}\"," +
" calR: \"{\\\\cal R}\"," +
" calS: \"{\\\\cal S}\"," +
" calT: \"{\\\\cal T}\"," +
" calU: \"{\\\\cal U}\"," +
" calV: \"{\\\\cal V}\"," +
" calW: \"{\\\\cal W}\"," +
" calX: \"{\\\\cal X}\"," +
" calY: \"{\\\\cal Y}\"," +
" calZ: \"{\\\\cal Z}\"," +
" d: [\"{\\\\rm d}{#1}\", 1]," +
" bfcd: \"{\\\\dot{\\\\bfc}}\"," +
" bfpd: \"{\\\\dot{\\\\bfp}}\"," +
" bfpdd: \"{\\\\ddot{\\\\bfp}}\"," +
" dim: \"{\\\\rm dim}\"," +
" p: \"{\\\\boldsymbol{p}}\"," +
" q: \"{\\\\boldsymbol{q}}\"," +
" qd: \"{\\\\dot{\\\\bfq}}\"," +
" qdd: \"{\\\\ddot{\\\\bfq}}\"," +
" xd: \"{\\\\dot{x}}\"," +
" xdd: \"{\\\\ddot{x}}\"," +
" yd: \"{\\\\dot{y}}\"," +
" ydd: \"{\\\\ddot{y}}\"," +
" zd: \"{\\\\dot{z}}\"," +
" zdd: \"{\\\\ddot{z}}\"," +
" defeq: \"{\\\\stackrel{\\\\mathrm{def}}{\\\\ =\\\\ }}\"," +
" } " +
" } " +
"}); ";
(document.body || document.getElementsByTagName('head')[0]).appendChild(mathjaxscript);
}
</script>Divergent component of motion2019-10-14T00:00:00+02:00Stéphane Carontag:scaron.info,2019-10-14:teaching/divergent-component-of-motion.html<p>The equations of motion of legged robots can be decomposed into <em>convergent</em>
and <em>divergent</em> components of motion.</p>
<p>The DCM is a major concept that has been applied to <a class="reference external" href="https://doi.org/10.1109/IROS.2011.6094435">walking</a> and <a class="reference external" href="https://doi.org/10.1109/IROS.2009.5354654">running</a> pattern generation.</p>
<div class="section" id="this-article-is-a-stub">
<h2>This article is a stub</h2>
<p>... content is coming...</p>
</div>
<div class="section" id="to-go-further">
<h2>To go further</h2>
<p>...</p>
</div>
Linear inverted pendulum model2019-10-14T00:00:00+02:00Stéphane Carontag:scaron.info,2019-10-14:teaching/linear-inverted-pendulum-model.html<p>The linear inverted pendulum model focuses on the translational components of a
legged robot's dynamics.</p>
<div class="section" id="derivation">
<h2>Derivation</h2>
<p>Both fixed and mobile robots are usually modeled as rigid bodies connected by
actuated joints. The <a class="reference external" href="/teaching/equations-of-motion.html">equation of motion</a>
for such a system are:</p>
<div class="math">
\begin{equation*}
\bfM(\bfq) \qdd + \qd^\top \bfC(\bfq) \qd + \bfg(\bfq) = \bfS^\top \bftau +
\sum_{i=1}^N \bfJ_{C_i}^\top \bff_i,
\end{equation*}
</div>
<p>where <span class="math">\(\bfq\)</span> is the vector of actuated and unactuated coordinates.
Actuated coordinates correspond to joint angles directly controlled by motors.
Unactuated coordinates correspond to the six degrees of freedom for the
position and orientation of the <em>floating base</em> (a frame attached to any of the
robot's bodies) with respect to the inertial fame. The vector <span class="math">\(\bfq\)</span> is
typically high-dimensional.</p>
<div class="section" id="centroidal-dynamics">
<h3>Centroidal dynamics</h3>
<p>The first working assumption to simplify this model is (Assumption 1) that
the robot has enough joint torques to realize the actuated part of the
equation, and focus on the <a class="reference external" href="/teaching/newton-euler-equations.html">Newton-Euler equations</a> that correspond to the six unactuated
coordinates:</p>
<div class="math">
\begin{equation*}
\begin{bmatrix} m \bfpdd_G \\ \dot{\bfL}_G \end{bmatrix}
=
\begin{bmatrix} \bff \\ \bftau_G \end{bmatrix}
+
\begin{bmatrix} m \bfg \\ \boldsymbol{0} \end{bmatrix}
\end{equation*}
</div>
<p>where on the left-hand side <span class="math">\(\bfp_G\)</span> is the position of the center
of mass (CoM) and <span class="math">\(\bfL_G\)</span> is the net angular momentum around the CoM,
while on the right-hand side <span class="math">\(\bff\)</span> is the resultant of contact forces,
<span class="math">\(\bftau_G\)</span> is the moment of contact forces around the CoM, <span class="math">\(m\)</span> is
the robot mass and <span class="math">\(\bfg\)</span> is the gravity vector. This model is called
<em>centroidal dynamics</em>.</p>
</div>
<div class="section" id="linearized-dynamics">
<h3>Linearized dynamics</h3>
<p>Angular momentum or height variations make centroidal dynamics nonlinear. This
means for instance that, to generate a trajectory for this system, one needs to
solve a nonlinear optimization. An alternative to linearize this system is to
make two assumptions:</p>
<ul class="simple">
<li><em>Assumption 2:</em> there is no angular momentum around the center of mass
<span class="math">\((\dot{\bfL}_G=\boldsymbol{0})\)</span>. This is why the Honda P2 <a class="reference external" href="https://youtu.be/d2BUO4HEhvM?t=172">walks with
locked arms</a>.</li>
<li><em>Assumption 3:</em> the center of mass keeps a constant height. This is why the
Honda P2 <a class="reference external" href="https://youtu.be/d2BUO4HEhvM?t=26">walks with bent knees</a>.</li>
</ul>
<p>These two assumptions are used to derive linearized dynamics as follows. First,
let us consider the <a class="reference external" href="/teaching/zero-tilting-moment-point.html">zero-tilting moment point (ZMP)</a> of the contact wrench. It is a
point <span class="math">\(Z\)</span> where the moment of contact forces is vertical:</p>
<div class="math">
\begin{equation*}
\bfe_Z \times \bftau_Z = \boldsymbol{0}
\end{equation*}
</div>
<p>with <span class="math">\(\bfe_Z\)</span> the unit upward vertical vector of the inertial frame. This
quantity defines an axis in general: to make <span class="math">\(Z\)</span> a unique point, let us
take it on the ground with <span class="math">\(z_Z = z_G - h\)</span>, where <span class="math">\(h\)</span> is the
constant height of the CoM. The moment <span class="math">\(\bftau_Z\)</span> of the contact wrench
at this ZMP is related to the moment at the CoM by:</p>
<div class="math">
\begin{equation*}
\bftau_Z = \bftau_G + (\bfp_G - \bfp_Z) \times \bff
\end{equation*}
</div>
<p>Since <span class="math">\(\bftau_G = \boldsymbol{0}\)</span> (Assumption 2), we have:</p>
<div class="math">
\begin{equation*}
\bfe_Z \times ((\bfp_G - \bfp_Z) \times \bff) = \boldsymbol{0}
\end{equation*}
</div>
<p>Applying the <a class="reference external" href="https://en.wikipedia.org/wiki/Triple_product#Vector_triple_product">vector triple product</a> formula,
we get:</p>
<div class="math">
\begin{equation*}
f_z (\bfp_G - \bfp_Z) - h \bff = \boldsymbol{0}
\end{equation*}
</div>
<p>From Newton's equation, <span class="math">\(\bff = m (\bfpdd_G - \bfg)\)</span> and we can rewrite
the equation above as:</p>
<div class="math">
\begin{equation*}
h (\bfpdd_G - \bfg) = (\zdd_G + g) (\bfp_G - \bfp_Z)
\end{equation*}
</div>
<p>Since <span class="math">\(\zdd_G = 0\)</span> (Assumption 3), this equation is a trivial identity in
the vertical direction while its horizontal coordinates are:</p>
<div class="math">
\begin{equation*}
\bfpdd_G = \omega^2 (\bfp_G - \bfp_Z)
\end{equation*}
</div>
<p>where <span class="math">\(\omega^2 = g / h\)</span>, <span class="math">\(g\)</span> is the gravity constant and <span class="math">\(h
= z_G - z_Z\)</span> is the constant height of the center of mass. The constant
<span class="math">\(\omega\)</span> is called <em>natural frequency</em> of the linear inverted pendulum.</p>
<img alt="Humanoid robot walking in the linear inverted pendulum mode" class="center max-height-450px" src="https://scaron.info/figures/lipm.png" />
<p>In this model, the robot can be seen as a point-mass concentrated at <span class="math">\(G\)</span>
resting on a mass-less leg in contact with the ground at <span class="math">\(Z\)</span>.
Intuitively, the ZMP is the point where the robot applies its weight. As a
consequence, this point needs to lie inside the contact surface <span class="math">\(\cal S\)</span>.</p>
</div>
</div>
<div class="section" id="to-go-further">
<h2>To go further</h2>
<p>The linear inverted pendulum <em>mode</em> (not model) was introduced in <a class="reference external" href="https://doi.org/10.1109/IROS.2001.973365">Kajita et
al. (2001)</a> for walking pattern
generation. The rationale for calling it a <em>mode</em> of motion is that it relies
solely on planar linear momentum, which is one among many ways to affect the
acceleration of the center of mass and thus locomote (others include <a class="reference external" href="/publications/tro-2019.html">height
variations</a> and angular momentum variations that
separate the <a class="reference external" href="/teaching/zero-tilting-moment-point.html">ZMP</a> and <a class="reference external" href="http://ijr.sagepub.com/cgi/doi/10.1177/0278364905058363">centroidal
moment pivot</a>).</p>
</div>
<script type='text/javascript'>if (!document.getElementById('mathjaxscript_pelican_#%@#$@#')) {
var mathjaxscript = document.createElement('script');
mathjaxscript.id = 'mathjaxscript_pelican_#%@#$@#';
mathjaxscript.type = 'text/javascript';
mathjaxscript.src = '/MathJax/MathJax.js?config=TeX-AMS-MML_HTMLorMML';
mathjaxscript[(window.opera ? "innerHTML" : "text")] =
"MathJax.Hub.Config({" +
" config: ['MMLorHTML.js']," +
" TeX: { extensions: ['AMSmath.js','AMSsymbols.js','noErrors.js','noUndefined.js'], equationNumbers: { autoNumber: 'AMS' } }," +
" jax: ['input/TeX','input/MathML','output/HTML-CSS']," +
" extensions: ['tex2jax.js','mml2jax.js','MathMenu.js','MathZoom.js']," +
" displayAlign: 'center'," +
" displayIndent: '0em'," +
" showMathMenu: true," +
" tex2jax: { " +
" inlineMath: [ ['\\\\(','\\\\)'] ], " +
" displayMath: [ ['$$','$$'] ]," +
" processEscapes: true," +
" preview: 'TeX'," +
" }, " +
" 'HTML-CSS': { " +
" styles: { '.MathJax_Display, .MathJax .mo, .MathJax .mi, .MathJax .mn': {color: '#333 ! important'} }, linebreaks: { automatic: false, width: 'container' }" +
" }, " +
" 'TeX': { " +
" Macros: { " +
" defeq: \"{\\\\stackrel{\\\\mathrm{def}}{=}}\"," +
" Ld: \"{\\\\dot{L}}\"," +
" LdG: \"{\\\\dot{L}_G}\"," +
" bfA: \"{\\\\boldsymbol{A}}\"," +
" bfB: \"{\\\\boldsymbol{B}}\"," +
" bfC: \"{\\\\boldsymbol{C}}\"," +
" bfD: \"{\\\\boldsymbol{D}}\"," +
" bfE: \"{\\\\boldsymbol{E}}\"," +
" bfF: \"{\\\\boldsymbol{F}}\"," +
" bfG: \"{\\\\boldsymbol{G}}\"," +
" bfH: \"{\\\\boldsymbol{H}}\"," +
" bfI: \"{\\\\boldsymbol{I}}\"," +
" bfJ: \"{\\\\boldsymbol{J}}\"," +
" bfK: \"{\\\\boldsymbol{K}}\"," +
" bfL: \"{\\\\boldsymbol{L}}\"," +
" bfM: \"{\\\\boldsymbol{M}}\"," +
" bfN: \"{\\\\boldsymbol{N}}\"," +
" bfO: \"{\\\\boldsymbol{O}}\"," +
" bfP: \"{\\\\boldsymbol{P}}\"," +
" bfQ: \"{\\\\boldsymbol{Q}}\"," +
" bfR: \"{\\\\boldsymbol{R}}\"," +
" bfS: \"{\\\\boldsymbol{S}}\"," +
" bfT: \"{\\\\boldsymbol{T}}\"," +
" bfU: \"{\\\\boldsymbol{U}}\"," +
" bfV: \"{\\\\boldsymbol{V}}\"," +
" bfW: \"{\\\\boldsymbol{W}}\"," +
" bfX: \"{\\\\boldsymbol{X}}\"," +
" bfY: \"{\\\\boldsymbol{Y}}\"," +
" bfZ: \"{\\\\boldsymbol{Z}}\"," +
" bfa: \"{\\\\boldsymbol{a}}\"," +
" bfb: \"{\\\\boldsymbol{b}}\"," +
" bfc: \"{\\\\boldsymbol{c}}\"," +
" bfd: \"{\\\\boldsymbol{d}}\"," +
" bfe: \"{\\\\boldsymbol{e}}\"," +
" bff: \"{\\\\boldsymbol{f}}\"," +
" bfg: \"{\\\\boldsymbol{g}}\"," +
" bfh: \"{\\\\boldsymbol{h}}\"," +
" bfi: \"{\\\\boldsymbol{i}}\"," +
" bfj: \"{\\\\boldsymbol{j}}\"," +
" bfk: \"{\\\\boldsymbol{k}}\"," +
" bfl: \"{\\\\boldsymbol{l}}\"," +
" bfm: \"{\\\\boldsymbol{m}}\"," +
" bfn: \"{\\\\boldsymbol{n}}\"," +
" bfo: \"{\\\\boldsymbol{o}}\"," +
" bfp: \"{\\\\boldsymbol{p}}\"," +
" bfq: \"{\\\\boldsymbol{q}}\"," +
" bfr: \"{\\\\boldsymbol{r}}\"," +
" bfs: \"{\\\\boldsymbol{s}}\"," +
" bft: \"{\\\\boldsymbol{t}}\"," +
" bfu: \"{\\\\boldsymbol{u}}\"," +
" bfv: \"{\\\\boldsymbol{v}}\"," +
" bfw: \"{\\\\boldsymbol{w}}\"," +
" bfx: \"{\\\\boldsymbol{x}}\"," +
" bfy: \"{\\\\boldsymbol{y}}\"," +
" bfz: \"{\\\\boldsymbol{z}}\"," +
" bfalpha: \"{\\\\boldsymbol{\\\\alpha}}\"," +
" bfxi: \"{\\\\boldsymbol{\\\\xi}}\"," +
" bfbeta: \"{\\\\boldsymbol{\\\\beta}}\"," +
" bfgamma: \"{\\\\boldsymbol{\\\\gamma}}\"," +
" bftau: \"{\\\\boldsymbol{\\\\tau}}\"," +
" bfomega: \"{\\\\boldsymbol{\\\\omega}}\"," +
" calA: \"{\\\\cal A}\"," +
" calB: \"{\\\\cal B}\"," +
" calC: \"{\\\\cal C}\"," +
" calD: \"{\\\\cal D}\"," +
" calE: \"{\\\\cal E}\"," +
" calF: \"{\\\\cal F}\"," +
" calG: \"{\\\\cal G}\"," +
" calH: \"{\\\\cal H}\"," +
" calI: \"{\\\\cal I}\"," +
" calJ: \"{\\\\cal J}\"," +
" calK: \"{\\\\cal K}\"," +
" calL: \"{\\\\cal L}\"," +
" calM: \"{\\\\cal M}\"," +
" calN: \"{\\\\cal N}\"," +
" calO: \"{\\\\cal O}\"," +
" calP: \"{\\\\cal P}\"," +
" calQ: \"{\\\\cal Q}\"," +
" calR: \"{\\\\cal R}\"," +
" calS: \"{\\\\cal S}\"," +
" calT: \"{\\\\cal T}\"," +
" calU: \"{\\\\cal U}\"," +
" calV: \"{\\\\cal V}\"," +
" calW: \"{\\\\cal W}\"," +
" calX: \"{\\\\cal X}\"," +
" calY: \"{\\\\cal Y}\"," +
" calZ: \"{\\\\cal Z}\"," +
" d: [\"{\\\\rm d}{#1}\", 1]," +
" bfcd: \"{\\\\dot{\\\\bfc}}\"," +
" bfpd: \"{\\\\dot{\\\\bfp}}\"," +
" bfpdd: \"{\\\\ddot{\\\\bfp}}\"," +
" dim: \"{\\\\rm dim}\"," +
" p: \"{\\\\boldsymbol{p}}\"," +
" q: \"{\\\\boldsymbol{q}}\"," +
" qd: \"{\\\\dot{\\\\bfq}}\"," +
" qdd: \"{\\\\ddot{\\\\bfq}}\"," +
" xd: \"{\\\\dot{x}}\"," +
" xdd: \"{\\\\ddot{x}}\"," +
" yd: \"{\\\\dot{y}}\"," +
" ydd: \"{\\\\ddot{y}}\"," +
" zd: \"{\\\\dot{z}}\"," +
" zdd: \"{\\\\ddot{z}}\"," +
" defeq: \"{\\\\stackrel{\\\\mathrm{def}}{\\\\ =\\\\ }}\"," +
" } " +
" } " +
"}); ";
(document.body || document.getElementsByTagName('head')[0]).appendChild(mathjaxscript);
}
</script>Biped Stabilization by Linear Feedback of the Variable-Height Inverted Pendulum Model2019-09-17T00:00:00+02:00Stéphane Carontag:scaron.info,2019-09-17:publications/vhip-stabilization.html<p class="authors"><strong>Stéphane Caron</strong>. Submitted September 2019.</p>
<div class="section" id="abstract">
<h2>Abstract</h2>
<p>The variable-height inverted pendulum (VHIP) model enables a new balancing
strategy, based on vertical motions of the center of mass, in addition to the
well-known ankle strategy. We propose a biped stabilizer based on linear
feedback of the VHIP that is simple to implement, coincides with the
state-of-the-art for small perturbations and is able to recover from larger
perturbations thanks to this new strategy. This solution is based on
"best-effort" pole placement of the 4D divergent component of motion of the
VHIP under input feasibility and state viability constraints. We complement it
with a suitable whole-body admittance control law and test the stabilizer on
the HRP-4 humanoid robot.</p>
</div>
<div class="section" id="video">
<h2>Video</h2>
<p>
<video width="95%" controls>
<source src="https://scaron.info/videos/vhip-stabilization.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
</p></div>
<div class="section" id="content">
<h2>Content</h2>
<table border="1" class="colwidths-given files docutils">
<colgroup>
<col width="10%" />
<col width="90%" />
</colgroup>
<tbody valign="top">
<tr><td><img alt="pdf" class="icon" src="https://scaron.info/images/icons/pdf.png" /></td>
<td><a class="reference external" href="https://hal.archives-ouvertes.fr/hal-02289919/document">Paper</a></td>
</tr>
<tr><td><img alt="pdf" class="icon" src="https://scaron.info/images/icons/pdf.png" /></td>
<td><a class="reference external" href="/slides/jrl-2019.pdf">Presentation given at JRL</a> on 29 October 2019</td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="bibtex">
<h2>BibTeX</h2>
<div class="highlight"><pre><span></span><span class="nc">@unpublished</span><span class="p">{</span><span class="nl">caron2019vhip</span><span class="p">,</span>
<span class="na">title</span> <span class="p">=</span> <span class="s">{Biped Stabilization by Linear Feedback of the Variable-Height Inverted Pendulum Model}</span><span class="p">,</span>
<span class="na">author</span> <span class="p">=</span> <span class="s">{Caron, St{\'e}phane}</span><span class="p">,</span>
<span class="na">note</span> <span class="p">=</span> <span class="s">{submitted}</span><span class="p">,</span>
<span class="na">url</span> <span class="p">=</span> <span class="s">{https://hal.archives-ouvertes.fr/hal-02289919}</span><span class="p">,</span>
<span class="na">year</span> <span class="p">=</span> <span class="s">{2019}</span><span class="p">,</span>
<span class="na">month</span> <span class="p">=</span> <span class="nv">sep</span><span class="p">,</span>
<span class="p">}</span>
</pre></div>
</div>
<div class="section" id="discussion">
<h2>Discussion</h2>
<p>See the discussion we had following a <a class="reference external" href="/talks/jrl-2019.html">presentation of this work at JRL</a>.</p>
</div>
Balance of Humanoid robot in Multi-contact and Sliding Scenarios2019-09-16T00:00:00+02:00Stéphane Carontag:scaron.info,2019-09-16:publications/sliding.html<p class="authors"><strong>Saeid Samadi</strong>, <strong>Stéphane Caron</strong>, <strong>Arnaud Tanguy</strong> and <strong>Abderrahmane
Kheddar</strong>. Submitted September 2019.</p>
<div class="section" id="abstract">
<h2>Abstract</h2>
<p>This study deals with the balance of humanoid or multi-legged robots in a
multi-contact setting where a chosen subset of contacts is undergoing desired
sliding-task motions. One method to keep balance is to hold the center-of-mass
(CoM) within an admissible convex area. This area should be calculated based on
the contact positions and forces. We introduce a methodology to compute this
CoM support area (CSA) for multiple fixed and sliding contacts. To select the
most appropriate CoM position inside CSA, we account for (i) constraints of
multiple fixed and sliding contacts, (ii) desired wrench distribution for
contacts, and (iii) desired position of CoM (eventually dictated by other
tasks). These are formulated as a quadratic programming optimization problem.
We illustrate our approach with pushing against a wall and wiping and conducted
experiments using the HRP-4 humanoid robot.</p>
</div>
<div class="section" id="content">
<h2>Content</h2>
<table border="1" class="colwidths-given files docutils">
<colgroup>
<col width="10%" />
<col width="90%" />
</colgroup>
<tbody valign="top">
<tr><td><img alt="pdf" class="icon" src="https://scaron.info/images/icons/pdf.png" /></td>
<td><a class="reference external" href="https://hal.archives-ouvertes.fr/hal-02297879/document">Paper</a></td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="bibtex">
<h2>BibTeX</h2>
<div class="highlight"><pre><span></span><span class="nc">@unpublished</span><span class="p">{</span><span class="nl">samadi2019sliding</span><span class="p">,</span>
<span class="na">title</span> <span class="p">=</span> <span class="s">{Balance of Humanoid robot in Multi-contact and Sliding Scenarios}</span><span class="p">,</span>
<span class="na">author</span> <span class="p">=</span> <span class="s">{Samadi, Saeid and Caron, St{\'e}phane and Tanguy, Arnaud and Kheddar, Abderrahmane}</span><span class="p">,</span>
<span class="na">note</span> <span class="p">=</span> <span class="s">{submitted}</span><span class="p">,</span>
<span class="na">url</span> <span class="p">=</span> <span class="s">{https://hal.archives-ouvertes.fr/hal-02297879}</span><span class="p">,</span>
<span class="na">year</span> <span class="p">=</span> <span class="s">{2019}</span><span class="p">,</span>
<span class="na">month</span> <span class="p">=</span> <span class="nv">sep</span><span class="p">,</span>
<span class="p">}</span>
</pre></div>
</div>
Walking and stair climbing controller for locomotion in an aircraft factory2019-06-05T00:00:00+02:00Stéphane Carontag:scaron.info,2019-06-05:talks/jpl-2019.html<p class="authors">Talk given at the NASA-Caltech <a class="reference external" href="https://www.jpl.nasa.gov/">Jet Propulsion Laboratory</a> on 5 June 2019.</p>
<div class="section" id="abstract">
<h2>Abstract</h2>
<p>The task was initially phrased for humans: go upstairs, walk into the aircraft,
pick up the object and place it on the fuselage. Yet, repetition and the
disposition of target locations turned out to cause chronic back pain, and the
question of automation was raised: can a robot do that? In this talk, we will
see how the HRP-4 humanoid can do that, and discuss the components we developed
for the final demonstrator of the <a class="reference external" href="http://comanoid.cnrs.fr/">COMANOID project</a> that ran at the Airbus Saint-Nazaire factory on 21
February 2019: self localization, locomotion, object localization and
manipulation. We will focus on walking and stair climbing control. The audience
is encouraged to bring (empty) plastic bottles.</p>
</div>
<div class="section" id="content">
<h2>Content</h2>
<table border="1" class="colwidths-given files docutils">
<colgroup>
<col width="10%" />
<col width="90%" />
</colgroup>
<tbody valign="top">
<tr><td><img alt="pdf" class="icon" src="https://scaron.info/images/icons/pdf.png" /></td>
<td><a class="reference external" href="/slides/jpl-2019.pdf">Slides</a></td>
</tr>
<tr><td><img alt="youtube" class="icon" src="https://scaron.info/images/icons/youtube.png" /></td>
<td><a class="reference external" href="https://www.youtube.com/watch?v=vFCFKAunsYM&t=22">Stair climbing experiment</a></td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="references">
<h2>References</h2>
<table border="1" class="colwidths-given files docutils">
<colgroup>
<col width="10%" />
<col width="90%" />
</colgroup>
<tbody valign="top">
<tr><td><img alt="pdf" class="icon" src="https://scaron.info/images/icons/pdf.png" /></td>
<td><a class="reference external" href="https://hal.archives-ouvertes.fr/hal-01875387/document">Stair climbing stabilization of the HRP-4 humanoid robot using whole-body admittance control</a></td>
</tr>
</tbody>
</table>
</div>
Stair Climbing Stabilization of the HRP-4 Humanoid Robot using Whole-body Admittance Control2019-05-20T00:00:00+02:00Stéphane Carontag:scaron.info,2019-05-20:publications/icra-2019.html<p class="authors"><strong>Stéphane Caron</strong>, <strong>Abderrahmane Kheddar</strong> and <strong>Olivier Tempier</strong>. ICRA
2019, Montreal, Canada, May 2019.</p>
<div class="section" id="abstract">
<h2>Abstract</h2>
<p>We consider dynamic stair climbing with the HRP-4 humanoid robot as part of an
Airbus manufacturing use-case demonstrator. We share experimental knowledge
gathered so as to achieve this task, which HRP-4 had never been challenged to
before. In particular, we extend walking stabilization based on <a class="reference external" href="https://doi.org/10.1109/IROS.2010.5651082">linear
inverted pendulum tracking</a> by
quadratic programming-based wrench distribution and a whole-body admittance
controller that applies both end-effector and CoM strategies. While existing
stabilizers tend to use either one or the other, our experience suggests that
the combination of these two approaches improves tracking performance. We
demonstrate this solution in an on-site experiment where HRP-4 climbs an
industrial staircase with 18.5 cm high steps, and release <a class="reference external" href="https://github.com/stephane-caron/lipm_walking_controller/">our walking
controller</a> as
open source software.</p>
</div>
<div class="section" id="videos">
<h2>Videos</h2>
<div class="section" id="climbing-stairs">
<h3>Climbing stairs</h3>
<div class="youtube youtube-16x9"><iframe src="https://www.youtube.com/embed/vFCFKAunsYM?start=22" allowfullscreen seamless frameBorder="0"></iframe></div></div>
<div class="section" id="standing-on-mobile-ground">
<h3>Standing on mobile ground</h3>
<div class="youtube youtube-16x9"><iframe src="https://www.youtube.com/embed/MxSJtEKkZE0?start=7" allowfullscreen seamless frameBorder="0"></iframe></div></div>
</div>
<div class="section" id="content">
<h2>Content</h2>
<p>The paper on HAL is a <em>post-print</em> I have kept updating after the conference to
keep up with the later additions and fixes implemented in the <a class="reference external" href="https://github.com/stephane-caron/lipm_walking_controller/">walking
controller</a>. See
the release notes on GitHub for an overview of the major changes since the
conference version (v1.1).</p>
<table border="1" class="colwidths-given files docutils">
<colgroup>
<col width="10%" />
<col width="90%" />
</colgroup>
<tbody valign="top">
<tr><td><img alt="pdf" class="icon" src="https://scaron.info/images/icons/pdf.png" /></td>
<td><a class="reference external" href="https://hal.archives-ouvertes.fr/hal-01875387/document">Paper</a> post-print</td>
</tr>
<tr><td><img alt="pdf" class="icon" src="https://scaron.info/images/icons/pdf.png" /></td>
<td><a class="reference external" href="https://scaron.info/files/icra-2019/poster.pdf">Poster</a> presented at ICRA 2019</td>
</tr>
<tr><td><img alt="pdf" class="icon" src="https://scaron.info/images/icons/pdf.png" /></td>
<td><a class="reference external" href="/slides/jpl-2019.pdf">Presentation given at NASA-Caltech JPL</a> on 5 June 2019</td>
</tr>
<tr><td><img alt="mp4" class="icon" src="https://scaron.info/images/icons/video.png" /></td>
<td><a class="reference external" href="https://ieeexplore.ieee.org/document/8794348/media">Stair climbing at the Airbus Saint-Nazaire factory</a></td>
</tr>
<tr><td><img alt="github" class="icon" src="https://scaron.info/images/icons/github.png" /></td>
<td><a class="reference external" href="https://github.com/stephane-caron/lipm_walking_controller/">Walking controller (C++)</a></td>
</tr>
<tr><td><img alt="doi" class="icon" src="https://scaron.info/images/icons/doi.png" /></td>
<td><a class="reference external" href="https://doi.org/10.1109/ICRA.2019.8794348">10.1109/ICRA.2019.8794348</a></td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="supplementary-material">
<h2>Supplementary material</h2>
<table border="1" class="colwidths-given files docutils">
<colgroup>
<col width="10%" />
<col width="90%" />
</colgroup>
<tbody valign="top">
<tr><td><img alt="html" class="icon" src="https://scaron.info/images/icons/html5.png" /></td>
<td><a class="reference external" href="/doc/lipm_walking_controller/">Controller documentation</a></td>
</tr>
<tr><td><img alt="html" class="icon" src="https://scaron.info/images/icons/html5.png" /></td>
<td><a class="reference external" href="/teaching/floating-base-estimation.html">Floating base observer</a> used in this controller</td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="bibtex">
<h2>BibTeX</h2>
<div class="highlight"><pre><span></span><span class="nc">@inproceedings</span><span class="p">{</span><span class="nl">caron2019icra</span><span class="p">,</span>
<span class="na">title</span> <span class="p">=</span> <span class="s">{Stair Climbing Stabilization of the {HRP}-4 Humanoid Robot using Whole-body Admittance Control}</span><span class="p">,</span>
<span class="na">author</span> <span class="p">=</span> <span class="s">{Caron, St{\'e}phane and Kheddar, Abderrahmane and Tempier, Olivier}</span><span class="p">,</span>
<span class="na">booktitle</span> <span class="p">=</span> <span class="s">{IEEE International Conference on Robotics and Automation}</span><span class="p">,</span>
<span class="na">url</span> <span class="p">=</span> <span class="s">{https://hal.archives-ouvertes.fr/hal-01875387}</span><span class="p">,</span>
<span class="na">year</span> <span class="p">=</span> <span class="s">{2019}</span><span class="p">,</span>
<span class="na">month</span> <span class="p">=</span> <span class="nv">may</span><span class="p">,</span>
<span class="p">}</span>
</pre></div>
</div>
<div class="section" id="discussion">
<h2>Discussion</h2>
<p><strong>What is the formula for the matrix</strong> <span class="math">\(\bfU\)</span> <strong>in Equation (10)?</strong></p>
<blockquote>
<p>This matrix is given by:</p>
<blockquote>
<div class="math">
\begin{equation*}
\bfU = \begin{bmatrix}
-1 & 0 & -\mu & 0 & 0 & 0 \\
+1 & 0 & -\mu & 0 & 0 & 0 \\
0 & -1 & -\mu & 0 & 0 & 0 \\
0 & +1 & -\mu & 0 & 0 & 0 \\
0 & 0 & -Y & -1 & 0 & 0 \\
0 & 0 & -Y & +1 & 0 & 0 \\
0 & 0 & -X & 0 & -1 & 0 \\
0 & 0 & -X & 0 & +1 & 0 \\
-Y & -X & -(X + Y) \mu & +\mu & +\mu & -1 \\
-Y & +X & -(X + Y) \mu & +\mu & -\mu & -1 \\
+Y & -X & -(X + Y) \mu & -\mu & +\mu & -1 \\
+Y & +X & -(X + Y) \mu & -\mu & -\mu & -1 \\
+Y & +X & -(X + Y) \mu & +\mu & +\mu & +1 \\
+Y & -X & -(X + Y) \mu & +\mu & -\mu & +1 \\
-Y & +X & -(X + Y) \mu & -\mu & +\mu & +1 \\
-Y & -X & -(X + Y) \mu & -\mu & -\mu & +1
\end{bmatrix}
\end{equation*}
</div>
</blockquote>
<p>with <span class="math">\(\mu\)</span> the friction coefficient, <span class="math">\(X\)</span> the half-length and
<span class="math">\(Y\)</span> the half-width of the rectangular contact area. Check out <a class="reference external" href="https://hal.archives-ouvertes.fr/hal-02108449/document">this
paper</a> for the
derivation of this formula, which corresponds to its equations (15) to
(20). In code, it is implemented in the functions:</p>
<ul class="simple">
<li><a class="reference external" href="https://scaron.info/doc/pymanoid/contact-stability.html#pymanoid.contact.Contact.wrench_inequalities">Contact.wrench_inequalities()</a> of <a class="reference external" href="https://github.com/stephane-caron/pymanoid/">pymanoid</a> (Python)</li>
<li><a class="reference external" href="https://github.com/stephane-caron/lipm_walking_controller/blob/1faa0b7adec71acf8e2af9de934695ab16296fc3/include/lipm_walking/Stabilizer.h#L215">Stabilizer::wrenchFaceMatrix()</a> of the <a class="reference external" href="https://github.com/stephane-caron/lipm_walking_controller/">lipm_walking_controller</a> (C++)</li>
</ul>
</blockquote>
</div>
<script type='text/javascript'>if (!document.getElementById('mathjaxscript_pelican_#%@#$@#')) {
var mathjaxscript = document.createElement('script');
mathjaxscript.id = 'mathjaxscript_pelican_#%@#$@#';
mathjaxscript.type = 'text/javascript';
mathjaxscript.src = '/MathJax/MathJax.js?config=TeX-AMS-MML_HTMLorMML';
mathjaxscript[(window.opera ? "innerHTML" : "text")] =
"MathJax.Hub.Config({" +
" config: ['MMLorHTML.js']," +
" TeX: { extensions: ['AMSmath.js','AMSsymbols.js','noErrors.js','noUndefined.js'], equationNumbers: { autoNumber: 'AMS' } }," +
" jax: ['input/TeX','input/MathML','output/HTML-CSS']," +
" extensions: ['tex2jax.js','mml2jax.js','MathMenu.js','MathZoom.js']," +
" displayAlign: 'center'," +
" displayIndent: '0em'," +
" showMathMenu: true," +
" tex2jax: { " +
" inlineMath: [ ['\\\\(','\\\\)'] ], " +
" displayMath: [ ['$$','$$'] ]," +
" processEscapes: true," +
" preview: 'TeX'," +
" }, " +
" 'HTML-CSS': { " +
" styles: { '.MathJax_Display, .MathJax .mo, .MathJax .mi, .MathJax .mn': {color: '#333 ! important'} }, linebreaks: { automatic: false, width: 'container' }" +
" }, " +
" 'TeX': { " +
" Macros: { " +
" defeq: \"{\\\\stackrel{\\\\mathrm{def}}{=}}\"," +
" Ld: \"{\\\\dot{L}}\"," +
" LdG: \"{\\\\dot{L}_G}\"," +
" bfA: \"{\\\\boldsymbol{A}}\"," +
" bfB: \"{\\\\boldsymbol{B}}\"," +
" bfC: \"{\\\\boldsymbol{C}}\"," +
" bfD: \"{\\\\boldsymbol{D}}\"," +
" bfE: \"{\\\\boldsymbol{E}}\"," +
" bfF: \"{\\\\boldsymbol{F}}\"," +
" bfG: \"{\\\\boldsymbol{G}}\"," +
" bfH: \"{\\\\boldsymbol{H}}\"," +
" bfI: \"{\\\\boldsymbol{I}}\"," +
" bfJ: \"{\\\\boldsymbol{J}}\"," +
" bfK: \"{\\\\boldsymbol{K}}\"," +
" bfL: \"{\\\\boldsymbol{L}}\"," +
" bfM: \"{\\\\boldsymbol{M}}\"," +
" bfN: \"{\\\\boldsymbol{N}}\"," +
" bfO: \"{\\\\boldsymbol{O}}\"," +
" bfP: \"{\\\\boldsymbol{P}}\"," +
" bfQ: \"{\\\\boldsymbol{Q}}\"," +
" bfR: \"{\\\\boldsymbol{R}}\"," +
" bfS: \"{\\\\boldsymbol{S}}\"," +
" bfT: \"{\\\\boldsymbol{T}}\"," +
" bfU: \"{\\\\boldsymbol{U}}\"," +
" bfV: \"{\\\\boldsymbol{V}}\"," +
" bfW: \"{\\\\boldsymbol{W}}\"," +
" bfX: \"{\\\\boldsymbol{X}}\"," +
" bfY: \"{\\\\boldsymbol{Y}}\"," +
" bfZ: \"{\\\\boldsymbol{Z}}\"," +
" bfa: \"{\\\\boldsymbol{a}}\"," +
" bfb: \"{\\\\boldsymbol{b}}\"," +
" bfc: \"{\\\\boldsymbol{c}}\"," +
" bfd: \"{\\\\boldsymbol{d}}\"," +
" bfe: \"{\\\\boldsymbol{e}}\"," +
" bff: \"{\\\\boldsymbol{f}}\"," +
" bfg: \"{\\\\boldsymbol{g}}\"," +
" bfh: \"{\\\\boldsymbol{h}}\"," +
" bfi: \"{\\\\boldsymbol{i}}\"," +
" bfj: \"{\\\\boldsymbol{j}}\"," +
" bfk: \"{\\\\boldsymbol{k}}\"," +
" bfl: \"{\\\\boldsymbol{l}}\"," +
" bfm: \"{\\\\boldsymbol{m}}\"," +
" bfn: \"{\\\\boldsymbol{n}}\"," +
" bfo: \"{\\\\boldsymbol{o}}\"," +
" bfp: \"{\\\\boldsymbol{p}}\"," +
" bfq: \"{\\\\boldsymbol{q}}\"," +
" bfr: \"{\\\\boldsymbol{r}}\"," +
" bfs: \"{\\\\boldsymbol{s}}\"," +
" bft: \"{\\\\boldsymbol{t}}\"," +
" bfu: \"{\\\\boldsymbol{u}}\"," +
" bfv: \"{\\\\boldsymbol{v}}\"," +
" bfw: \"{\\\\boldsymbol{w}}\"," +
" bfx: \"{\\\\boldsymbol{x}}\"," +
" bfy: \"{\\\\boldsymbol{y}}\"," +
" bfz: \"{\\\\boldsymbol{z}}\"," +
" bfalpha: \"{\\\\boldsymbol{\\\\alpha}}\"," +
" bfxi: \"{\\\\boldsymbol{\\\\xi}}\"," +
" bfbeta: \"{\\\\boldsymbol{\\\\beta}}\"," +
" bfgamma: \"{\\\\boldsymbol{\\\\gamma}}\"," +
" bftau: \"{\\\\boldsymbol{\\\\tau}}\"," +
" bfomega: \"{\\\\boldsymbol{\\\\omega}}\"," +
" calA: \"{\\\\cal A}\"," +
" calB: \"{\\\\cal B}\"," +
" calC: \"{\\\\cal C}\"," +
" calD: \"{\\\\cal D}\"," +
" calE: \"{\\\\cal E}\"," +
" calF: \"{\\\\cal F}\"," +
" calG: \"{\\\\cal G}\"," +
" calH: \"{\\\\cal H}\"," +
" calI: \"{\\\\cal I}\"," +
" calJ: \"{\\\\cal J}\"," +
" calK: \"{\\\\cal K}\"," +
" calL: \"{\\\\cal L}\"," +
" calM: \"{\\\\cal M}\"," +
" calN: \"{\\\\cal N}\"," +
" calO: \"{\\\\cal O}\"," +
" calP: \"{\\\\cal P}\"," +
" calQ: \"{\\\\cal Q}\"," +
" calR: \"{\\\\cal R}\"," +
" calS: \"{\\\\cal S}\"," +
" calT: \"{\\\\cal T}\"," +
" calU: \"{\\\\cal U}\"," +
" calV: \"{\\\\cal V}\"," +
" calW: \"{\\\\cal W}\"," +
" calX: \"{\\\\cal X}\"," +
" calY: \"{\\\\cal Y}\"," +
" calZ: \"{\\\\cal Z}\"," +
" d: [\"{\\\\rm d}{#1}\", 1]," +
" bfcd: \"{\\\\dot{\\\\bfc}}\"," +
" bfpd: \"{\\\\dot{\\\\bfp}}\"," +
" bfpdd: \"{\\\\ddot{\\\\bfp}}\"," +
" dim: \"{\\\\rm dim}\"," +
" p: \"{\\\\boldsymbol{p}}\"," +
" q: \"{\\\\boldsymbol{q}}\"," +
" qd: \"{\\\\dot{\\\\bfq}}\"," +
" qdd: \"{\\\\ddot{\\\\bfq}}\"," +
" xd: \"{\\\\dot{x}}\"," +
" xdd: \"{\\\\ddot{x}}\"," +
" yd: \"{\\\\dot{y}}\"," +
" ydd: \"{\\\\ddot{y}}\"," +
" zd: \"{\\\\dot{z}}\"," +
" zdd: \"{\\\\ddot{z}}\"," +
" defeq: \"{\\\\stackrel{\\\\mathrm{def}}{\\\\ =\\\\ }}\"," +
" } " +
" } " +
"}); ";
(document.body || document.getElementsByTagName('head')[0]).appendChild(mathjaxscript);
}
</script>