-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
pydrake documentation has c++ code in it #12591
Comments
This seems like a great idea, Russ. This (and many other things) suggests to me that proper support of PyDrake can't be fully automated -- I wonder if it is a big enough job to warrant a full time position for someone? |
We are in the process of automating, though it will be months rather than weeks to implement. |
@jamiesnape — my understanding is that you are automating the creation of bindings. I don’t know how you would automate this step (touching up the code samples in the docs?). Is that fair? |
We probably wouldn't ever want to automate those. The original idea of inserting |
"proper support of PyDrake" comes down to semantics. Ultimately, if that includes converting C++ code examples in doxygen to a python version, then the statement can easily be considered true. One thing @sherm1 and I vaguely discussed in this context is that a full-time role responsible for improving all aspects of the pydrake experience -- including creating/coordinating an appropriate set of tutorials, responsibility for the final look of python documentation (even if that means going in and adding If I were to take a liberty and define "proper support of PyDrake" to that highest level -- maximizing ease of use, then that will never be fully automated. And perhaps we need to consider if the value we place on it corresponds to dedicated personnel. |
Another random thought on the distinction between libdrake and pydrake. When we have a class that captures a non-owning reference to some other object, we carefully document this dependency and the need to keep it alive beyond the lifespan of the capturing instance. When that object is bound, we typically/always use In an ideal world, pydrake documentation wouldn't include that kind of guidance. These are the kinds of things that would improve the pydrake experience, currently aren't automated (although certainly could be with appropriate instrumentation -- some sort of |
+1 on the ideal of having someone fully devoted to quality pydrake development and maintenance; that would be awesome! However, I also agree with @jamiesnape that it's not necessary to support this feature. I think the proposed solution -- specifying what time of language is in a code segment -- is achievable without a full-time person. Regarding the full automation parts, yes, things that @SeanCurtis-TRI have pointed are certainly points that would most likely require some form of human annotation, either in pydrake docs or in hand-modified bindings code. As a request for keeping this issue on-topic, and keeping this input traceable, could you put those future notes about automation directly in #7889? |
Although the ability to mark a code snippet or example with its language needs to be implemented just once, someone has to write (and test) a pythonic code snippet to match each C++ snippet, both extant and future. That seems like a big job to me and one that should be in the capable hands of a devoted expert (or experts) rather than left to individual C++ programmers working on Drake's guts. |
Reassigning to Toffee for disposition. |
(Late response triggered by Drake Dev mtg :P)
Do we really do that for C++ code? I've seen bugs in the C++ docstring examples -- yes, they got fixed, but it indicates that we may not have rigorous testing / review at creation time.
Er, why? I feel like you're over-inflating the difficulty of Python? I feel like us trying to "do it 100% right the first time" is too high of a bar sometimes, hurts us in cases like this (where failure is not catastrophic), and can hurt the bigger picture? |
I feel confident that all the C++ developers in Dynamics can write C++ examples, likely cribbing from their C++ unit tests. I'm skeptical that non-users of our Python interface can write reasonable examples. But maybe that can be cleaned up in review. |
I have been looking through open issues related to documentation to see if there is anything I could reasonably help with (as I put together my series of pure Python tutorials); with an eye towards things that are too boring for anyone else to tackle. I was wondering if this @pycode label was ever added? I have been generating (very boring) minimal working Python examples (starting with pydrake.math, which is easy). As in: pydrake.math.abs: # Numerical Example:
numerical = math.abs(-13)
# Symbolic Example:
x = Variable("x")
expr = math.abs(x**3 - 5*x)
# AutoDiff Example:
x_ad = AutoDiffXd(-13, [1.0])
expr_ad = math.abs(x_ad**3 - 5*x_ad)
# Print results:
print("Numeric: ", numerical)
display(Markdown("Symbolic: $" + ToLatex(expr) + "$"))
print("AD value: ", expr_ad.value())
print("AD derivatives: ", expr_ad.derivatives()) This is painstaking boring work that I doubt anyone here wants to do, but I am just steadily adding examples like this for my own reference, and I am an obsessive enough personality that I just might make it through the majority of the python API. Every time I visit the docs for any method or class, I make a version for myself in a Jupyter notebook with a minimal working example. math.abs is probably not the best example of how this is useful, but it's helped me quite a bit to have a quick reference for other more complicated functions that require inputs with a specific Drake type. If you aren't familiar with the codebase, this usually equates to opening multiple tabs of documentation to figure out how to construct instances of different types, then setting them up until your constructor doesn't barf. I think the scipy documentation is a great example of what people want when they're getting started. You go to scipy.linalg.leslie, a fairly esoteric feature to model discrete-time, age-structured population growth and they have this:
It might seem silly if you are a developer at Toyota, but most of us mere mortals want to copy paste something, check the type of the output, check the shape of the output, see what happens if we change the shape of the input, and then move on to implementing it in our code. If someone makes it possible for me to share these, and yall let me know the best way to structure things, I would be happy to share. In fact, with a little coaching, I'm willing to commit to plowing through an entire namespace to get the ball rolling. Obviously, if/when I get to something like say, pydrake.math.BalanceQuadraticForms, it would be ideal if my example doesn't just run, but actually has a mathematically sensible input and output, which could get a little tricky, but I'm sure there are enough people here that know what that means to help me tidy up sloppy examples. As always, I am also content to keep it in a separate repo with my growing list of beginner tutorials, but I think the project is great and I'd love to help out with some of the boring bits so those of us following Russ' lectures from home can really get somewhere... That was a mouthful. -Drew |
@drewhamiltonasdf -- Thank you! I love the idea of making progress on this. A few of our key developers are traveling right now, but I'm sure they will weigh in soon. Here are a few quick thoughts from me:
|
@RussTedrake -- Great news! If there's no place to put them yet it really won't hold me up at all as far as generating all the... let's call them "snippets". I'm just keeping a little notebook locally for myself as I march through the different namespaces. I actually already finished putting a python snippet together for every class and function in math: https://github.com/drewhamiltonasdf/DrakeTutorials/blob/main/pydrake.math.ipynb At the top of notebook, I put the corresponding I also just went ahead and put snippets together for everything else, and I have quite a few that are significantly longer, for example for BSpline etc. Not sure if this is helpful, but maybe there is some place to stick these later if I get a good set of tutorials together. Lastly, I'm just wondering if it might be helpful for me to keep everything in one place, at least initially, for you guys to review before submitting pull requests that modify every header file in an entire namespace. This way you can see the output or run it (I suppose even test it?) before it gets turned into a Hope that's not too much. Just want the contribution to be useful and not require too much rework. |
FYI I'm working on a PR to provide the markup tags we'll need for this adventure. I'll backlink it here once it's posted. |
🙏Thanks! 🙏 |
See https://drake.mit.edu/documentation_instructions.html#python_detail_ for an example of the new markup. |
I have not forgotten about this. Still have a huge bucket full of code snippets I can contribute. Looking to get around to this soon. |
Some of the best documentation that we have (in c++/doxygen) has nice little code snippets, but always in c++. For a python user looking at the pydrake docs (especially one unfamiliar with c++), these are scary and even confusing.
MultibodyPlant's documentation has a few examples:
https://drake.mit.edu/pydrake/pydrake.multibody.plant.html#pydrake.multibody.plant.MultibodyPlant_
Thinking for a bit about how we could realistically/sustainably improve the situation, the doxygen code blocks are surrounded by
@code
@endcode
blocks. Would it be crazy to add a@pycode
block type that c++ doxygen would know to ignore and the pydrake sphinx code would know to render?Assigning to @sherm1 to start the discussion. cc @EricCousineau-TRI , @jamiesnape .
The text was updated successfully, but these errors were encountered: