You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<spanclass="c"># Speed up the preview by only processing certain tool(s):</span>
191
191
<spanclass="nv">$ </span>bazel run //doc:pages <spanclass="nt">--</span><spanclass="nt">--serve</span><spanclass="c"># Only the main site.</span>
192
192
<spanclass="nv">$ </span>bazel run //doc/doxygen_cxx:build <spanclass="nt">--</span><spanclass="nt">--serve</span><spanclass="c"># Only the C++ API reference.</span>
193
-
<spanclass="nv">$ </span>bazel run //doc/pydrake:build <spanclass="nt">--</span><spanclass="nt">--serve</span><spanclass="c"># Only the Python API reference.</span>
193
+
<spanclass="nv">$ </span>bazel run //bindings/generated_docstrings:regenerate <spanclass="o">&&</span><spanclass="se">\</span>
194
+
<spanclass="c"># bazel run //doc/pydrake:build -- --serve # Only the Python API reference.</span>
194
195
<spanclass="nv">$ </span>bazel run //doc/styleguide:build <spanclass="nt">--</span><spanclass="nt">--serve</span><spanclass="c"># Only the Style Guide.</span>
195
196
196
197
<spanclass="c"># Further speed up preview generating only some API modules, e.g., math:</span>
197
198
<spanclass="nv">$ </span>bazel run //doc/doxygen_cxx:build <spanclass="nt">--</span><spanclass="nt">--serve</span> drake.math <spanclass="c"># C++ math API.</span>
198
-
<spanclass="nv">$ </span>bazel run //doc/pydrake:build <spanclass="nt">--</span><spanclass="nt">--serve</span> pydrake.math <spanclass="c"># Python math API.</span>
199
+
<spanclass="nv">$ </span>bazel run //bindings/generated_docstrings:regenerate <spanclass="o">&&</span><spanclass="se">\</span>
200
+
<spanclass="nv">$ </span> bazel run //doc/pydrake:build <spanclass="nt">--</span><spanclass="nt">--serve</span> pydrake.math <spanclass="c"># Python math API.</span>
199
201
<spanclass="nv">$ </span>bazel run //doc:build <spanclass="nt">--</span><spanclass="nt">--serve</span><spanclass="o">{</span>drake,pydrake<spanclass="o">}</span>.math <spanclass="c"># Both at once.</span>
200
202
201
203
<spanclass="c"># Further speed up preview by omitting expensive `dot` graphs (C++ API only):</span>
<p>Drake uses a modified version of <code>mkdoc.py</code> from <code>pybind11</code>, where <code>libclang</code> Python bindings are used to generate C++ docstrings accessible to the C++ binding code.</p>
273
-
<p>These docstrings are available within <code>constexpr struct ... pydrake_doc</code> as <code>const char*</code> values. When these are not available or not suitable for Python documentation, provide custom strings. If this custom string is long, consider placing them in a heredoc string.</p>
274
-
<p>An example of incorporating docstrings from <code>pydrake_doc</code>:</p>
275
-
<divclass="fragment"><divclass="line"><spanclass="preprocessor">#include "drake/bindings/pydrake/documentation_pybind.h"</span></div><divclass="line"></div><divclass="line">PYBIND11_MODULE(math, m) {</div><divclass="line"><spanclass="keyword">using namespace </span><aclass="code" href="namespacedrake_1_1math.html">drake::math</a>;</div><divclass="line"> constexpr <spanclass="keyword">auto</span>& doc = pydrake_doc.drake.math;</div><divclass="line"><spanclass="keyword">using</span> T = double;</div><divclass="line"> py::class_<RigidTransform<T>>(m, <spanclass="stringliteral">"RigidTransform"</span>, doc.RigidTransform.doc)</div><divclass="line"> .def(py::init(), doc.RigidTransform.ctor.doc_0args)</div><divclass="line"> ...</div><divclass="line"> .def(py::init<<spanclass="keyword">const</span><aclass="code" href="classdrake_1_1math_1_1_rotation_matrix.html">RotationMatrix<T></a>&>(), py::arg(<spanclass="stringliteral">"R"</span>),</div><divclass="line"> doc.RigidTransform.ctor.doc_1args_R)</div><divclass="line"> .def(py::init<<spanclass="keyword">const</span> Eigen::Quaternion<T>&, <spanclass="keyword">const</span> Vector3<T>&>(),</div><divclass="line"> py::arg(<spanclass="stringliteral">"quaternion"</span>), py::arg(<spanclass="stringliteral">"p"</span>),</div><divclass="line"> doc.RigidTransform.ctor.doc_2args_quaternion_p)</div><divclass="line"> ...</div><divclass="line"> .def(<spanclass="stringliteral">"set_rotation"</span>, &<aclass="code" href="classdrake_1_1math_1_1_rigid_transform.html">RigidTransform<T>::set_rotation</a>, py::arg(<spanclass="stringliteral">"R"</span>),</div><divclass="line"> doc.<aclass="code" href="classdrake_1_1math_1_1_rigid_transform.html#a8bedd8c483aaf5bc48587d10d7a3d485">RigidTransform</a>.set_rotation.doc)</div><divclass="line"> ...</div><divclass="line">}</div></div><!-- fragment --><p>An example of supplying custom strings:</p>
273
+
<p>These docstrings are available within nested <code>constexpr struct</code>trees as <code>const char*</code> values. When these are not available or not suitable for Python documentation, provide custom strings. If this custom string is long, consider placing them in a heredoc string.</p>
274
+
<p>An example of incorporating docstrings:</p>
275
+
<divclass="fragment"><divclass="line"><spanclass="preprocessor">#include "drake/bindings/generated_docstrings/math.h"</span></div><divclass="line"></div><divclass="line">PYBIND11_MODULE(math, m) {</div><divclass="line"><spanclass="keyword">using namespace </span><aclass="code" href="namespacedrake_1_1math.html">drake::math</a>;</div><divclass="line"> constexpr <spanclass="keyword">auto</span>& doc = pydrake_doc_math.drake.math;</div><divclass="line"><spanclass="keyword">using</span> T = double;</div><divclass="line"> py::class_<RigidTransform<T>>(m, <spanclass="stringliteral">"RigidTransform"</span>, doc.RigidTransform.doc)</div><divclass="line"> .def(py::init(), doc.RigidTransform.ctor.doc_0args)</div><divclass="line"> ...</div><divclass="line"> .def(py::init<<spanclass="keyword">const</span><aclass="code" href="classdrake_1_1math_1_1_rotation_matrix.html">RotationMatrix<T></a>&>(), py::arg(<spanclass="stringliteral">"R"</span>),</div><divclass="line"> doc.RigidTransform.ctor.doc_1args_R)</div><divclass="line"> .def(py::init<<spanclass="keyword">const</span> Eigen::Quaternion<T>&, <spanclass="keyword">const</span> Vector3<T>&>(),</div><divclass="line"> py::arg(<spanclass="stringliteral">"quaternion"</span>), py::arg(<spanclass="stringliteral">"p"</span>),</div><divclass="line"> doc.RigidTransform.ctor.doc_2args_quaternion_p)</div><divclass="line"> ...</div><divclass="line"> .def(<spanclass="stringliteral">"set_rotation"</span>, &<aclass="code" href="classdrake_1_1math_1_1_rigid_transform.html">RigidTransform<T>::set_rotation</a>, py::arg(<spanclass="stringliteral">"R"</span>),</div><divclass="line"> doc.<aclass="code" href="classdrake_1_1math_1_1_rigid_transform.html#a8bedd8c483aaf5bc48587d10d7a3d485">RigidTransform</a>.set_rotation.doc)</div><divclass="line"> ...</div><divclass="line">}</div></div><!-- fragment --><p>An example of supplying custom strings:</p>
276
276
<divclass="fragment"><divclass="line">constexpr <spanclass="keywordtype">char</span> another_helper_doc[] = R<spanclass="stringliteral">"""(</span></div><divclass="line"><spanclass="stringliteral">Another helper docstring. This is really long.</span></div><divclass="line"><spanclass="stringliteral">And has multiple lines.</span></div><divclass="line"><spanclass="stringliteral">)""";</span></div><divclass="line"><spanclass="stringliteral"></span></div><divclass="line"><spanclass="stringliteral">PYBIND11_MODULE(example, m) {</span></div><divclass="line"><spanclass="stringliteral"> m.def(</span><spanclass="stringliteral">"helper"</span>, []() { <spanclass="keywordflow">return</span> 42; }, <spanclass="stringliteral">"My helper method"</span>);</div><divclass="line"> m.def(<spanclass="stringliteral">"another_helper"</span>, []() { <spanclass="keywordflow">return</span> 10; }, another_helper_doc);</div><divclass="line">}</div></div><!-- fragment --><dlclass="section note"><dt>Note</dt><dd>Consider using scoped aliases to abbreviate both the usage of bound types and the docstring structures. Borrowing from above:</dd></dl>
277
-
<divclass="fragment"><divclass="line">{</div><divclass="line"><spanclass="keyword">using</span> Class = RigidTransform<T>;</div><divclass="line"> constexpr <spanclass="keyword">auto</span>& cls_doc = doc.RigidTransform;</div><divclass="line"> py::class_<Class>(m, <spanclass="stringliteral">"RigidTransform"</span>, cls_doc.doc)</div><divclass="line"> .def(py::init(), cls_doc.ctor.doc_0args)</div><divclass="line"> ...</div><divclass="line">}</div></div><!-- fragment --><p>To view the documentation rendered in Sphinx: </p><preclass="fragment">bazel run //doc/pydrake:serve_sphinx [-- --browser=false]
277
+
<divclass="fragment"><divclass="line">{</div><divclass="line"><spanclass="keyword">using</span> Class = RigidTransform<T>;</div><divclass="line"> constexpr <spanclass="keyword">auto</span>& cls_doc = doc.RigidTransform;</div><divclass="line"> py::class_<Class>(m, <spanclass="stringliteral">"RigidTransform"</span>, cls_doc.doc)</div><divclass="line"> .def(py::init(), cls_doc.ctor.doc_0args)</div><divclass="line"> ...</div><divclass="line">}</div></div><!-- fragment --><p>To view the documentation rendered in Sphinx: </p><preclass="fragment">bazel run -- //doc/pydrake:build --serve [--browser=false]
278
278
</pre><dlclass="section note"><dt>Note</dt><dd>Drake's online Python documentation is generated on Ubuntu Noble, and it is suggested to preview documentation using this platform. Other platforms may have slightly different generated documentation.</dd></dl>
279
-
<p>To browse the generated documentation strings that are available for use (or especially, to find out the names for overloaded functions' documentation), generate and open the docstring header: </p><preclass="fragment">bazel build //bindings/pydrake:documentation_pybind.h
<p>To browse the generated documentation strings that are available for use (or especially, to find out the names for overloaded functions' documentation), re-generate and open the docstring header: </p><preclass="fragment">bazel run //bindings/generated_docstrings:regenerate
</pre><p>Search the comments for the symbol of interest, e.g., <code><aclass="el" href="classdrake_1_1math_1_1_rigid_transform.html#a8bedd8c483aaf5bc48587d10d7a3d485">drake::math::RigidTransform::RigidTransform</a><T></code>, and view the include file and line corresponding to the symbol that the docstring was pulled from.</p>
282
-
<dlclass="section note"><dt>Note</dt><dd>This file may be large, on the order of ~100K lines; be sure to use an efficient editor!</dd>
283
-
<dd>
284
-
If you are debugging a certain file and want quicker generation and a smaller generated file, you can hack <code>mkdoc.py</code> to focus only on your include file of choice. As an example, debugging <code><aclass="el" href="mathematical__program_8h.html">mathematical_program.h</a></code>: <divclass="fragment"><divclass="line">...</div><divclass="line"><spanclass="keyword">assert</span> len(include_files) > 0 <spanclass="comment"># Existing code.</span></div><divclass="line">include_files = [<spanclass="stringliteral">"drake/solvers/mathematical_program.h"</span>] <spanclass="comment"># HACK</span></div></div><!-- fragment --> This may break the bindings themselves, and should only be used for inspecting the output.</dd></dl>
282
+
<dlclass="section note"><dt>Note</dt><dd>This file may be large, on the order of ~10K lines; be sure to use an efficient editor!</dd></dl>
285
283
<p>For more detail:</p>
286
284
<ul>
287
-
<li>Each docstring is stored in <code>documentation_pybind.h</code> in the nested structure <code>pydrake_doc</code>.</li>
288
-
<li>The docstring for a symbol without any overloads will be accessible via <code>pydrake_doc.drake.{namespace...}.{symbol}.doc</code>.</li>
285
+
<li>Docstrings are stored in files named after the subdirectory where the original C++ header file lives, e.g., <code><aclass="el" href="multibody__tree_8h.html">multibody_tree.h</a></code> for <code>drake/multibody/tree</code> docs.</li>
286
+
<li>The constants sit within structures named <code>pydrake_doc_{directory_names}</code>, e.g., <code>pydrake_doc_multibody_tree</code> for <code>drake/multibody/tree</code> docs.</li>
287
+
<li>The docstring for a symbol without any overloads will be accessible via <code>pydrake_doc_{directory_names}.drake.{namespace...}.{symbol}.doc</code>.</li>
289
288
<li>The docstring for an overloaded symbol will be <code>.doc_something</code> instead of just <code>.doc</code>, where the <code>_something</code> suffix conveys some information about the overload. Browse the documentation_pybind.h (described above) for details. Most commonly, the names will be <code>doc_1args</code>, <code>doc_3args</code>, etc. Be sure that the pydrake binding's signature is consistent with the docstring argument count.</li>
290
289
<li>If two or more docstrings are the same, only one new symbol is introduced.</li>
291
290
<li>To suppress a Doxygen comment from mkdoc, add the custom Doxygen command <code>@exclude_from_pydrake_mkdoc{Explanation}</code> to the API comment text. This is useful to help dismiss unbound overloads, so that mkdoc's choice of <code>_something</code> name suffix is simpler for the remaining overloads, especially if you see the symbol <code>.doc_was_unable_to_choose_unambiguous_names</code> in the generated documentation.</li>
0 commit comments