-
Notifications
You must be signed in to change notification settings - Fork 6
/
python_bindings.html
582 lines (459 loc) · 40.7 KB
/
python_bindings.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta name="msapplication-config" content="/browserconfig.xml"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta charset="utf-8"/>
<link rel="apple-touch-icon" type="image/png" href="/apple-touch-icon.png"/>
<link rel="manifest" type="application/manifest+json" href="/site.webmanifest"/>
<link rel="mask-icon" type="image/svg+xml" href="/mask-icon.svg" color="#990000"/>
<link rel="shortcut icon" type="image/png" href="/favicon.png"/>
<title>Drake: Using Drake from Python</title>
<meta
name="description"
content="Drake ("dragon" in Middle English) is a C++ toolbox started by the Robot
Locomotion Group at the MIT Computer Science and Artificial Intelligence
Lab (CSAIL). The development team has now grown significantly, with core
development led by the Toyota Research Institute. It is a collection of
tools for analyzing the dynamics of our robots and building control
systems for them, with a heavy emphasis on optimization-based design/
analysis.
"/>
<!--
The "Work Sans" font is licensed under the SIL Open Font License (OFL). For
more information, see:
- https://fonts.google.com/specimen/Work+Sans?preview.text_type=custom#about
- https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL
-->
<link href="https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=Work+Sans:wght@300;400;600;700;800&display=swap" rel="stylesheet"/>
<link rel="stylesheet" href="/third_party/github-styling/github-markdown.css"/>
<link rel="stylesheet" href="/third_party/dracula/syntax.css"/>
<link rel="stylesheet" href="/third_party/pylons/pylons.css"/>
<link rel="stylesheet" href="/assets/css/main.css"/>
</head>
<body>
<header class="site-header">
<div class="site-header-inner contain">
<a href="/" class="drake-logo">
<img src="/images/drake-logo-white.svg">
</a>
<div class="menu-mobile-toggle">
<span></span>
</div>
<nav class="site-menu">
<ul>
<li class="site-menu-item site-menu-item-main">
<a href="/" class="site-menu-item">Home</a>
</li>
<li class="site-menu-item site-menu-item-main">
<a href="/installation.html" class="site-menu-item">Installation</a>
</li>
<li class="site-menu-item site-menu-item-main">
<a href="/gallery.html" class="site-menu-item">Gallery</a>
</li>
<li class="site-menu-item site-menu-item-main">
API Documentation
<div class="sub">
<a href="/doxygen_cxx/index.html" class="site-menu-item">C++</a>
<a href="/pydrake/index.html" class="site-menu-item">Python</a>
</div>
</li>
<li class="site-menu-item site-menu-item-main">
Resources
<div class="sub">
<a href="/getting_help.html" class="site-menu-item">Getting Help</a>
<a href="https://deepnote.com/workspace/Drake-0b3b2c53-a7ad-441b-80f8-bf8350752305/project/Tutorials-2b4fc509-aef2-417d-a40d-6071dfed9199/%2Findex.ipynb" class="site-menu-item">Tutorials</a>
<a href="/python_bindings.html" class="site-menu-item">Python Bindings</a>
<a href="/developers.html" class="site-menu-item">For Developers</a>
<a href="/credits.html" class="site-menu-item">Credits</a>
</div>
</li>
<li class="search">
<div class="search-icon">
<!-- This is an inline SVG image of a magnifying glass. -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 374.9 374.84">
<path d="M235 270a148.74 148.74 0 1 1 35-35l97.74 97.74a24.37 24.37 0 0 1 0 34.58l-.4.4a24.47 24.47 0 0 1-34.58 0L235 270Zm-86.22-7.47A113.75 113.75 0 1 0 35 148.75 113.75 113.75 0 0 0 148.75 262.5Z"/>
</svg>
</div>
<div class="search-bar">
<form id="search_form" action="https://google.com/search" method="get">
<input type="text" name="q" placeholder="Search all of Drake…" />
<input type="hidden" name="q" value="site:drake.mit.edu OR site:underactuated.csail.mit.edu OR site:manipulation.csail.mit.edu" />
</form>
<div class="search-close">
<!-- This is an inline SVG image of an "X". -->
<svg height="20" width="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 373.61 373.57">
<path d="M219.71 186.77 366.71 40a23.43 23.43 0 1 0-33.13-33.13l-146.77 147-146.77-147A23.43 23.43 0 0 0 6.9 40l147 146.77-147 146.77a23.43 23.43 0 1 0 33.14 33.13l146.77-147 146.77 147a23.43 23.43 0 1 0 33.13-33.13Z"/>
</svg>
</div>
</div>
<ul id="results-container"></ul>
</li>
<li class="github-link">
<a href="https://github.com/RobotLocomotion/drake" class="site-menu-item">GitHub <img src="/third_party/images/GitHub-Mark-Light-64px.png" /></a>
</li>
</ul>
</nav>
</div>
</header>
<div class="page">
<div class="content">
<div class="drake-page">
<header class="drake-page-header">
<div class="contain">
<h1>Using Drake from Python</h1>
</div>
</header>
<section class="padding">
<div class="contain grid grid-1-2col-nav-and-body">
<!--
N.B. The page is responsible for including the front + end matter.
See "Caveats" in drake/doc/README.txt.
-->
<!--
See "Caveats" in drake/doc/README.txt.
-->
<div class="sub-nav">
<div class="sticky">
<h5>Table of Contents</h5>
<ul id="markdown-toc">
<li><a href="#background" id="markdown-toc-background">Background</a></li>
<li><a href="#installation" id="markdown-toc-installation">Installation</a></li>
<li><a href="#using-the-python-bindings" id="markdown-toc-using-the-python-bindings">Using the Python Bindings</a> <ul>
<li><a href="#check-installation" id="markdown-toc-check-installation">Check Installation</a></li>
<li><a href="#whats-available-from-python" id="markdown-toc-whats-available-from-python">What’s Available from Python</a></li>
<li><a href="#differences-with-c-api" id="markdown-toc-differences-with-c-api">Differences with C++ API</a></li>
<li><a href="#scalar-types" id="markdown-toc-scalar-types">Scalar Types</a></li>
<li><a href="#c-function-and-method-template-instantiations-in-python" id="markdown-toc-c-function-and-method-template-instantiations-in-python">C++ Function and Method Template Instantiations in Python</a></li>
<li><a href="#debugging-with-the-python-bindings" id="markdown-toc-debugging-with-the-python-bindings">Debugging with the Python Bindings</a></li>
<li><a href="#for-developers" id="markdown-toc-for-developers">For Developers</a></li>
</ul>
</li>
</ul>
</div>
</div>
<article class="markdown-body">
<h1 id="background">Background</h1>
<p>A substantial subset of the Drake C++ functionality is available from Python.
The Drake Python bindings are generated using <a href="https://github.com/pybind/pybind11">pybind11</a>,
which means that every function or
class which is exposed to C++ has been explicitly enumerated in one of the
source files inside the <code class="language-plaintext highlighter-rouge">bindings/pydrake</code> folder. These bindings are
installed as a single package called <code class="language-plaintext highlighter-rouge">pydrake</code>.</p>
<div class="note">
<p>Drake is not tested regularly with Anaconda, so if you are using Anaconda you
may experience compatibility hiccups; when asking for help, be sure to mention
that Conda is involved.</p>
</div>
<h1 id="installation">Installation</h1>
<p>Refer to <a href="/pip.html#stable-releases">Installation via Pip</a> for how to install
Drake’s releases using pip, or the general <a href="/installation.html">Installation</a>
instructions for alternative options.</p>
<h1 id="using-the-python-bindings">Using the Python Bindings</h1>
<h2 id="check-installation">Check Installation</h2>
<p>After following the above install steps, check to ensure you can import
<code class="language-plaintext highlighter-rouge">pydrake</code>.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python3 <span class="nt">-c</span> <span class="s1">'import pydrake.all; print(pydrake.__file__)'</span>
</code></pre></div> </div>
<div class="note">
<p>If you are using Gurobi, you must either have it installed in the suggested location under <code class="language-plaintext highlighter-rouge">/opt/...</code> mentioned in Gurobi 10.0, or you must ensure that you define the <code class="language-plaintext highlighter-rouge">${GUROBI_HOME}</code> environment variable, or specify <code class="language-plaintext highlighter-rouge">${GUROBI_INCLUDE_DIR}</code> via CMake.</p>
</div>
<h2 id="whats-available-from-python">What’s Available from Python</h2>
<p>You should first browse the <a href="/pydrake/index.html">Python API</a> to see what
modules are available. The most up-to-date high-level demonstrations of what
can be done using <code class="language-plaintext highlighter-rouge">pydrake</code> are in Drake’s <a href="/index.html#tutorials">Tutorials</a> and
the <a href="https://underactuated.mit.edu/">Underactuated Robotics Textbook</a> and
the <a href="https://manipulation.mit.edu/">Robotic Manipulation Textbook</a>.</p>
<p>You can also see lower-level usages of the API in the <code class="language-plaintext highlighter-rouge">pydrake</code> unit tests
themselves, which you can find inside of the
<code class="language-plaintext highlighter-rouge">drake/bindings/python/pydrake/**/test</code> folders in the Drake source code.</p>
<p>Here’s an example snippet of code from <code class="language-plaintext highlighter-rouge">pydrake</code>:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pydrake.common</span> <span class="kn">import</span> <span class="n">FindResourceOrThrow</span>
<span class="kn">from</span> <span class="nn">pydrake.multibody.parsing</span> <span class="kn">import</span> <span class="n">Parser</span>
<span class="kn">from</span> <span class="nn">pydrake.multibody.plant</span> <span class="kn">import</span> <span class="n">AddMultibodyPlantSceneGraph</span>
<span class="kn">from</span> <span class="nn">pydrake.systems.analysis</span> <span class="kn">import</span> <span class="n">Simulator</span>
<span class="kn">from</span> <span class="nn">pydrake.systems.framework</span> <span class="kn">import</span> <span class="n">DiagramBuilder</span>
<span class="n">builder</span> <span class="o">=</span> <span class="n">DiagramBuilder</span><span class="p">()</span>
<span class="n">plant</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="n">AddMultibodyPlantSceneGraph</span><span class="p">(</span><span class="n">builder</span><span class="p">,</span> <span class="mf">0.0</span><span class="p">)</span>
<span class="n">Parser</span><span class="p">(</span><span class="n">plant</span><span class="p">).</span><span class="n">AddModels</span><span class="p">(</span>
<span class="n">FindResourceOrThrow</span><span class="p">(</span><span class="s">"drake/examples/pendulum/Pendulum.urdf"</span><span class="p">))</span>
<span class="n">plant</span><span class="p">.</span><span class="n">Finalize</span><span class="p">()</span>
<span class="n">diagram</span> <span class="o">=</span> <span class="n">builder</span><span class="p">.</span><span class="n">Build</span><span class="p">()</span>
<span class="n">simulator</span> <span class="o">=</span> <span class="n">Simulator</span><span class="p">(</span><span class="n">diagram</span><span class="p">)</span>
</code></pre></div> </div>
<p>If you are prototyping code in a REPL environment (such as IPython / Jupyter)
and to reduce the number of import statements, consider using <code class="language-plaintext highlighter-rouge">pydrake.all</code> to
import a subset of symbols from a flattened namespace or import all modules
automatically. If you are writing non-prototype code, avoid using
<code class="language-plaintext highlighter-rouge">pydrake.all</code>; for more details, see <code class="language-plaintext highlighter-rouge">help(pydrake.all)</code>.</p>
<p>In all cases, try to avoid using <code class="language-plaintext highlighter-rouge">from pydrake.all import *</code>, as it may
introduce symbol collisions that are difficult to debug.</p>
<p>The above example, but using <code class="language-plaintext highlighter-rouge">pydrake.all</code>:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pydrake.all</span> <span class="kn">import</span> <span class="p">(</span>
<span class="n">AddMultibodyPlantSceneGraph</span><span class="p">,</span> <span class="n">DiagramBuilder</span><span class="p">,</span> <span class="n">FindResourceOrThrow</span><span class="p">,</span>
<span class="n">Parser</span><span class="p">,</span> <span class="n">Simulator</span><span class="p">)</span>
<span class="n">builder</span> <span class="o">=</span> <span class="n">DiagramBuilder</span><span class="p">()</span>
<span class="n">plant</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="n">AddMultibodyPlantSceneGraph</span><span class="p">(</span><span class="n">builder</span><span class="p">,</span> <span class="mf">0.0</span><span class="p">)</span>
<span class="n">Parser</span><span class="p">(</span><span class="n">plant</span><span class="p">).</span><span class="n">AddModels</span><span class="p">(</span>
<span class="n">FindResourceOrThrow</span><span class="p">(</span><span class="s">"drake/examples/pendulum/Pendulum.urdf"</span><span class="p">))</span>
<span class="n">plant</span><span class="p">.</span><span class="n">Finalize</span><span class="p">()</span>
<span class="n">diagram</span> <span class="o">=</span> <span class="n">builder</span><span class="p">.</span><span class="n">Build</span><span class="p">()</span>
<span class="n">simulator</span> <span class="o">=</span> <span class="n">Simulator</span><span class="p">(</span><span class="n">diagram</span><span class="p">)</span>
</code></pre></div> </div>
<p>An alternative is to use <code class="language-plaintext highlighter-rouge">pydrake.all</code> to import all modules, but then
explicitly refer to each symbol:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">pydrake.all</span>
<span class="n">builder</span> <span class="o">=</span> <span class="n">pydrake</span><span class="p">.</span><span class="n">systems</span><span class="p">.</span><span class="n">framework</span><span class="p">.</span><span class="n">DiagramBuilder</span><span class="p">()</span>
<span class="n">plant</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="n">pydrake</span><span class="p">.</span><span class="n">multibody</span><span class="p">.</span><span class="n">plant</span><span class="p">.</span><span class="n">AddMultibodyPlantSceneGraph</span><span class="p">(</span><span class="n">builder</span><span class="p">,</span> <span class="mf">0.0</span><span class="p">)</span>
<span class="n">pydrake</span><span class="p">.</span><span class="n">multibody</span><span class="p">.</span><span class="n">parsing</span><span class="p">.</span><span class="n">Parser</span><span class="p">(</span><span class="n">plant</span><span class="p">).</span><span class="n">AddModels</span><span class="p">(</span>
<span class="n">pydrake</span><span class="p">.</span><span class="n">common</span><span class="p">.</span><span class="n">FindResourceOrThrow</span><span class="p">(</span>
<span class="s">"drake/examples/pendulum/Pendulum.urdf"</span><span class="p">))</span>
<span class="n">plant</span><span class="p">.</span><span class="n">Finalize</span><span class="p">()</span>
<span class="n">diagram</span> <span class="o">=</span> <span class="n">builder</span><span class="p">.</span><span class="n">Build</span><span class="p">()</span>
<span class="n">simulator</span> <span class="o">=</span> <span class="n">pydrake</span><span class="p">.</span><span class="n">systems</span><span class="p">.</span><span class="n">analysis</span><span class="p">.</span><span class="n">Simulator</span><span class="p">(</span><span class="n">diagram</span><span class="p">)</span>
</code></pre></div> </div>
<h2 id="differences-with-c-api">Differences with C++ API</h2>
<p>In general, the <a href="/pydrake/index.html">Python API</a> should be close to the
<a href="/doxygen_cxx/index.html">C++ API</a>. There are some exceptions:</p>
<h3 id="c-class-template-instantiations-in-python">C++ Class Template Instantiations in Python</h3>
<p>When you define a general class template, e.g.
<code class="language-plaintext highlighter-rouge">template <typename T> class Value</code>, something like <code class="language-plaintext highlighter-rouge">Value<std::string></code> is
called the instantiation.</p>
<p>For certain C++ templated types, they are exposed in Pythons also as templates;
the parameter types (in this case, <code class="language-plaintext highlighter-rouge">T</code>) are the Python-equivalent types to the
C++ type. Some examples:</p>
<table>
<thead>
<tr>
<th>C++</th>
<th>Python</th>
</tr>
</thead>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">std::string</code></td>
<td><code class="language-plaintext highlighter-rouge">str</code></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">double</code></td>
<td><code class="language-plaintext highlighter-rouge">float, np.double, np.float64, ctypes.c_double</code></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">drake::AutoDiffXd</code></td>
<td><code class="language-plaintext highlighter-rouge">pydrake.autodiffutils.AutoDiffXd</code></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">drake::symbolic::Expression</code></td>
<td><code class="language-plaintext highlighter-rouge">pydrake.symbolic.Expression</code></td>
</tr>
</tbody>
</table>
<p>Thus, the instantiation <code class="language-plaintext highlighter-rouge">Value<std::string></code> will be bound in Python as
<code class="language-plaintext highlighter-rouge">Value[str]</code>.</p>
<h2 id="scalar-types">Scalar Types</h2>
<p>Most classes in the Systems framework and in the multibody dynamics
computational framework are templated on a scalar type, <code class="language-plaintext highlighter-rouge">T</code>.
For convenience (and backwards compatibility) in Python, a slightly different
binding convention is used.</p>
<p>For example, <code class="language-plaintext highlighter-rouge">Adder<T></code> is a Systems primitive which has a user-defined
number of inputs and outputs a single port which is the sum of all of the
inputs.</p>
<p>In C++, you would access the instantiations using <code class="language-plaintext highlighter-rouge">Adder<double></code>,
<code class="language-plaintext highlighter-rouge">Adder<AutoDiffXd></code>, and <code class="language-plaintext highlighter-rouge">Adder<Expression></code> for common scalar types.</p>
<p>In Python, <code class="language-plaintext highlighter-rouge">Adder</code> actually refers to the “default” instantiation, the
<code class="language-plaintext highlighter-rouge">Adder<double></code> C++ class. To access other instantiations, you should add an
<code class="language-plaintext highlighter-rouge">_</code> to the end of the C++ class name to get the Python template and then
provide the parameters in square braces, <code class="language-plaintext highlighter-rouge">[...]</code>. In this example, you should
use <code class="language-plaintext highlighter-rouge">Adder_[T]</code>.</p>
<p>To illustrate, you can print out the string representations of <code class="language-plaintext highlighter-rouge">Adder</code>,
<code class="language-plaintext highlighter-rouge">Adder_</code>, and some of its instantiations in Python:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="kn">from</span> <span class="nn">pydrake.systems.primitives</span> <span class="kn">import</span> <span class="n">Adder</span><span class="p">,</span> <span class="n">Adder_</span>
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">Adder</span><span class="p">)</span>
<span class="o"><</span><span class="k">class</span> <span class="err">'</span><span class="nc">pydrake</span><span class="p">.</span><span class="n">systems</span><span class="p">.</span><span class="n">primitives</span><span class="p">.</span><span class="n">Adder_𝓣float𝓤</span><span class="s">'>
>>> print(Adder_)
<TemplateClass pydrake.systems.primitives.Adder_>
>>> from pydrake.autodiffutils import AutoDiffXd
>>> from pydrake.symbolic import Expression
>>> print(Adder_[float])
<class '</span><span class="n">pydrake</span><span class="p">.</span><span class="n">systems</span><span class="p">.</span><span class="n">primitives</span><span class="p">.</span><span class="n">Adder_𝓣float𝓤</span><span class="s">'>
>>> print(Adder_[AutoDiffXd])
<class '</span><span class="n">pydrake</span><span class="p">.</span><span class="n">systems</span><span class="p">.</span><span class="n">primitives</span><span class="p">.</span><span class="n">Adder_𝓣AutoDiffXd𝓤</span><span class="s">'>
>>> print(Adder_[Expression])
<class '</span><span class="n">pydrake</span><span class="p">.</span><span class="n">systems</span><span class="p">.</span><span class="n">primitives</span><span class="p">.</span><span class="n">Adder_𝓣Expression𝓤</span><span class="s">'>
</span></code></pre></div> </div>
<p>In debugging output like the class <code class="language-plaintext highlighter-rouge">repr</code> shown above, you might encounter the
unicode letters 𝓣 and 𝓤. These are used for “name mangling” of template types;
we need to use “name mangling” to obey Python’s class and function naming rules.
If you see a mangled name, you can read it using the following legend: a <code class="language-plaintext highlighter-rouge">𝓣</code>
stands for an open bracket (<code class="language-plaintext highlighter-rouge">[</code>), a <code class="language-plaintext highlighter-rouge">𝓤</code> stands for a close bracket (<code class="language-plaintext highlighter-rouge">]</code>),
a <code class="language-plaintext highlighter-rouge">𝓬</code> stands for a comma (<code class="language-plaintext highlighter-rouge">,</code>), and a <code class="language-plaintext highlighter-rouge">𝓹</code> stands for a dot (<code class="language-plaintext highlighter-rouge">.</code>).</p>
<p>Additionally, you may convert an instance (if the conversion is available) using
<code class="language-plaintext highlighter-rouge">System_[T].ToAutoDiffXd</code> and <code class="language-plaintext highlighter-rouge">System_[T].ToSymbolic</code>:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="n">adder</span> <span class="o">=</span> <span class="n">Adder</span><span class="p">(</span><span class="n">num_inputs</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">size</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">adder</span><span class="p">)</span>
<span class="o"><</span><span class="n">pydrake</span><span class="p">.</span><span class="n">systems</span><span class="p">.</span><span class="n">primitives</span><span class="p">.</span><span class="n">Adder_𝓣float𝓤</span> <span class="nb">object</span> <span class="n">at</span> <span class="mi">0</span><span class="n">x</span><span class="p">...</span><span class="o">></span>
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">adder</span><span class="p">.</span><span class="n">ToAutoDiffXd</span><span class="p">())</span>
<span class="o"><</span><span class="n">pydrake</span><span class="p">.</span><span class="n">systems</span><span class="p">.</span><span class="n">primitives</span><span class="p">.</span><span class="n">Adder_𝓣AutoDiffXd𝓤</span> <span class="nb">object</span> <span class="n">at</span> <span class="mi">0</span><span class="n">x</span><span class="p">...</span><span class="o">></span>
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">adder</span><span class="p">.</span><span class="n">ToSymbolic</span><span class="p">())</span>
<span class="o"><</span><span class="n">pydrake</span><span class="p">.</span><span class="n">systems</span><span class="p">.</span><span class="n">primitives</span><span class="p">.</span><span class="n">Adder_𝓣Expression𝓤</span> <span class="nb">object</span> <span class="n">at</span> <span class="mi">0</span><span class="n">x</span><span class="p">...</span><span class="o">></span>
</code></pre></div> </div>
<h2 id="c-function-and-method-template-instantiations-in-python">C++ Function and Method Template Instantiations in Python</h2>
<p>The above section indicates that C++ types are generally registered with
Python, and a similar approach could be used for function and method templates.
However, these templates usually fit a certain pattern and can be Pythonized in
such a way that simplifies implementation, but may change the “feel” of the
signature.</p>
<p>Two common (non-metaprogramming) applications of templated functions and
methods present in Drake are <a href="https://en.cppreference.com/w/cpp/container/vector/emplace">emplace</a>-like
functionality (using <a href="https://en.cppreference.com/w/cpp/language/parameter_pack">parameter packs</a>) and
<a href="https://en.wikipedia.org/wiki/Type_erasure">type erasure</a>.
However, Python doesn’t literally support these C++ language features. So, in
binding them, they get “Pythonized”.</p>
<p>C++ APIs which use parameter packs, such as:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>DiagramBuilder<T>::AddSystem<SystemType>(args...)
MultibodyPlant<T>::AddJoint<JointType>(args...)
MultibodyPlant<T>::AddFrame<FrameType>(args...)
</code></pre></div> </div>
<p>will become the following in Python:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">DiagramBuilder_</span><span class="p">[</span><span class="n">T</span><span class="p">].</span><span class="n">AddSystem</span><span class="p">(</span><span class="n">SystemType</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="p">...))</span>
<span class="n">MultibodyPlant_</span><span class="p">[</span><span class="n">T</span><span class="p">].</span><span class="n">AddJoint</span><span class="p">(</span><span class="n">JointType</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="p">...))</span>
<span class="n">MultibodyPlant_</span><span class="p">[</span><span class="n">T</span><span class="p">].</span><span class="n">AddFrame</span><span class="p">(</span><span class="n">FrameType</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="p">...))</span>
</code></pre></div> </div>
<p>where the <code class="language-plaintext highlighter-rouge">*Type</code> tokens are replaced with the concrete type in question
(e.g. <code class="language-plaintext highlighter-rouge">Adder_[T]</code>, <code class="language-plaintext highlighter-rouge">RevoluteJoint_[T]</code>, <code class="language-plaintext highlighter-rouge">FixedOffsetFrame_[T]</code>).</p>
<p>Similarly, type-erasure C++ APIs that look like:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>InputPort<T>::Eval<ValueType>(context)
GeometryProperties::AddProperty<ValueType>(group_name, name, value)
</code></pre></div> </div>
<p>will become the following in Python:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">InputPort_</span><span class="p">[</span><span class="n">T</span><span class="p">].</span><span class="n">Eval</span><span class="p">(</span><span class="n">context</span><span class="p">)</span>
<span class="n">GeometryProperties</span><span class="p">.</span><span class="n">AddProperty</span><span class="p">(</span><span class="n">group_name</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
</code></pre></div> </div>
<h2 id="debugging-with-the-python-bindings">Debugging with the Python Bindings</h2>
<p>You may encounter issues with the Python Bindings that may arise from the
underlying C++ code, and it may not always be obvious what the root cause is.</p>
<p>The first step to debugging is to consider running your code using the
<code class="language-plaintext highlighter-rouge">trace</code> module. It is best practice to always have a <code class="language-plaintext highlighter-rouge">main()</code> function, and
have a <code class="language-plaintext highlighter-rouge">if __name__ == "__main__"</code> clause. If you do this, then it is easy to
trace. As an example:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">reexecute_if_unbuffered</span><span class="p">():</span>
<span class="s">"""Ensures that output is immediately flushed (e.g. for segfaults).
ONLY use this at your entrypoint. Otherwise, you may have code be
re-executed that will clutter your console."""</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">shlex</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="k">if</span> <span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">"PYTHONUNBUFFERED"</span><span class="p">)</span> <span class="ow">in</span> <span class="p">(</span><span class="bp">None</span><span class="p">,</span> <span class="s">""</span><span class="p">):</span>
<span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">[</span><span class="s">"PYTHONUNBUFFERED"</span><span class="p">]</span> <span class="o">=</span> <span class="s">"1"</span>
<span class="n">argv</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">)</span>
<span class="k">if</span> <span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="n">sys</span><span class="p">.</span><span class="n">executable</span><span class="p">:</span>
<span class="n">argv</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">sys</span><span class="p">.</span><span class="n">executable</span><span class="p">)</span>
<span class="n">cmd</span> <span class="o">=</span> <span class="s">" "</span><span class="p">.</span><span class="n">join</span><span class="p">([</span><span class="n">shlex</span><span class="p">.</span><span class="n">quote</span><span class="p">(</span><span class="n">arg</span><span class="p">)</span> <span class="k">for</span> <span class="n">arg</span> <span class="ow">in</span> <span class="n">argv</span><span class="p">])</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">flush</span><span class="p">()</span>
<span class="n">os</span><span class="p">.</span><span class="n">execv</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">argv</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">traced</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">ignoredirs</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
<span class="s">"""Decorates func such that its execution is traced, but filters out any
Python code outside of the system prefix."""</span>
<span class="kn">import</span> <span class="nn">functools</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">trace</span>
<span class="k">if</span> <span class="n">ignoredirs</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="n">ignoredirs</span> <span class="o">=</span> <span class="p">[</span><span class="s">"/usr"</span><span class="p">,</span> <span class="n">sys</span><span class="p">.</span><span class="n">prefix</span><span class="p">]</span>
<span class="n">tracer</span> <span class="o">=</span> <span class="n">trace</span><span class="p">.</span><span class="n">Trace</span><span class="p">(</span><span class="n">trace</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">count</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">ignoredirs</span><span class="o">=</span><span class="n">ignoredirs</span><span class="p">)</span>
<span class="o">@</span><span class="n">functools</span><span class="p">.</span><span class="n">wraps</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">wrapped</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="k">return</span> <span class="n">tracer</span><span class="p">.</span><span class="n">runfunc</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
<span class="k">return</span> <span class="n">wrapped</span>
<span class="c1"># NOTE: You don't have to trace all of your code. If you can identify a
# single function, then you can just decorate it with this. If you're
# decorating a class method, then be sure to declare these functions above
# it.
</span><span class="o">@</span><span class="n">traced</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="n">insert_awesome_code_here</span><span class="p">()</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">"__main__"</span><span class="p">:</span>
<span class="n">reexecute_if_unbuffered</span><span class="p">()</span>
<span class="n">main</span><span class="p">()</span>
</code></pre></div> </div>
<div class="note">
<p>If you are developing in Drake and are using the <code class="language-plaintext highlighter-rouge">drake_py_unittest</code> macro, you can specify the argument <code class="language-plaintext highlighter-rouge">--trace=user</code> to get the same behavior.</p>
</div>
<!-- TODO(eric.cousineau): Move this into pydrake.common.debug. -->
<p>Additionally, you can also decorate your function to break on an exception so
you can get a REPL (which works in a terminal or in a Jupyter notebook) to
actively inspect the context (like <code class="language-plaintext highlighter-rouge">dbstop if error</code> in MATLAB).</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">contextlib</span> <span class="kn">import</span> <span class="n">contextmanager</span>
<span class="kn">import</span> <span class="nn">pdb</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">traceback</span>
<span class="o">@</span><span class="n">contextmanager</span>
<span class="k">def</span> <span class="nf">launch_pdb_on_exception</span><span class="p">():</span>
<span class="s">"""
Provides a context that will launch interactive pdb console automatically
if an exception is raised.
Example usage with @iex decorator shorthand below:
@iex
def my_bad_function():
x = 1
assert False
my_bad_function()
# Should bring up debugger at `assert` statement.
"""</span>
<span class="c1"># Adapted from:
</span> <span class="c1"># https://github.com/gotcha/ipdb/blob/fc83b4f5f/ipdb/__main__.py#L219-L232
</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">yield</span>
<span class="k">except</span> <span class="nb">Exception</span><span class="p">:</span>
<span class="n">traceback</span><span class="p">.</span><span class="n">print_exc</span><span class="p">()</span>
<span class="n">_</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">tb</span> <span class="o">=</span> <span class="n">sys</span><span class="p">.</span><span class="n">exc_info</span><span class="p">()</span>
<span class="n">pdb</span><span class="p">.</span><span class="n">post_mortem</span><span class="p">(</span><span class="n">tb</span><span class="p">)</span>
<span class="c1"># Resume original execution.
</span> <span class="k">raise</span>
<span class="c1"># Mirror `@ipdb.iex` decorator. See docs for `launch_pdb_on_exception()`.
</span><span class="n">iex</span> <span class="o">=</span> <span class="n">launch_pdb_on_exception</span><span class="p">()</span>
</code></pre></div> </div>
<p>This generally should help you trace where the code is dying. However, if you
still need to dig in, you can build the bindings in debug mode, without symbol
stripping, so you can debug with <code class="language-plaintext highlighter-rouge">gdb</code> or <code class="language-plaintext highlighter-rouge">lldb</code>:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cmake -DCMAKE_BUILD_TYPE=Debug ../drake
</code></pre></div> </div>
<div class="warning">
<p>If you have SNOPT enabled (either <code class="language-plaintext highlighter-rouge">-DWITH_SNOPT=ON</code> or <code class="language-plaintext highlighter-rouge">-DWITH_ROBOTLOCOMOTION_SNOPT=ON</code>), symbols will <em>still</em> be stripped.</p>
</div>
<h2 id="for-developers">For Developers</h2>
<p>If you are developing Python bindings, please see the Doxygen page
<a href="/doxygen_cxx/group__python__bindings.html">Python Bindings</a> which provides information on programming conventions, documentation, tips
for debugging, and other advice.</p>
</article>
</div>
</section>
</div>
<footer class="site-footer padding">
<div class="contain">
<a href="/" class="drake-logo">
<img src="/images/drake-logo.svg">
</a>
<div class="footer-menu">
<ul>
<li>
<a href="/doxygen_cxx/index.html" class="site-menu-item">C++</a>
</li>
<li>
<a href="/pydrake/index.html" class="site-menu-item">Python</a>
</li>
<li class="github-link">
<a href="https://github.com/RobotLocomotion/drake" class="site-menu-item">GitHub <img src="/third_party/images/GitHub-Mark-64px.png" /></a>
</li>
</ul>
</div>
</div>
<!-- TODO(eric.cousineau): Consider placing copyright here. -->
</footer>
</div>
</div>
<script src="/assets/js/mobile.js"></script>
<!-- Search -->
<script src="/assets/js/search.js"></script>
</body>
</html>