-
Notifications
You must be signed in to change notification settings - Fork 69
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
Python interface #210
Comments
I want to bring a topic to discuss, Right now we are using SWIG to generate the Python interfaces. I would like to consider pybind11 as library to implement this wrapper. pybind11 is a lightweight header-only library that exposes C++ types in Python that we can use it as an alternative to SWIG. The main difference is that pybind11 uses C++ templates with compile time introspection to generate wrapper code, where SWIG uses a custom C++ parser. In Pybind11 types need to be wrapped explicitly by specifying the classes and (member) functions. This has the downside of having to write and maintain the wrappers but has the advantage of being explicit and allowing wrappers to be made more Pythonic. SWIG requires to learn a new tools but with pybind11, developers only need proficiency in two languages (C++ and Python). I would say that maybe it does make sensor for ign-math to use SWIG, because it has classes that make math (I believe without threading) but for other packages we may require to have more control about what's happening such as ign-gazebo. I don't know which is going to be the final decision but I think we should stick with one library for all the packages. And right now it's the time because only few classes are already ported with SWIG in ign-math. By the way, pybind11 is used in rclpy @chapulina @scpeters Thoughts ? |
Thanks for bringing up pybind11. I think it makes sense for
For I think it's ok for us to use different approaches in each library, since they serve different purposes and have different requirements. |
One tricky aspect in using different approaches for different (but that depend on each other) libraries is that it may be tricky to easily bind in Python the methods in ignition-gazebo that take in input and return ign-math* types. If both ign-math and ign-gazebo use either SWIG or pybind11, then both system offer facilities to easily permit to create a object with ign-math bindings, and pass it then to the interface in ign-gazebo that expects a ign-math object. If ign-math bindings are based on swig and the ign-gazebo are based on pybind11, this interoperability may not be so straightforward, at least in my experience. See ami-iit/bipedal-locomotion-framework#214 for a related discussion (in that case iDynTree was the library with SWIG-based bindings, and bipedal-locomotion-framework the library with pybind11-based bindings). |
Just for information, there are several projects that build on top of pybind11 that promise to at least reduce the amount of boilerplate to write. To be honest however I never used any of those in an actual project, but you can find some references to them in:
|
Thanks for the heads up, @traversaro . I was hoping that there would be a way for I see you use SWIG in |
Just to clarify, that may be indeeed possible. However, we never tried, while the use case that is instead fully supported by both SWIG and pybind11 is use in their API classes that are exposed by SWIG and pybind11 respectively.
Probably @diegoferigo can provide a more educated answer. Personally, I am a big fan of the "no glue code" approach of swig or other similar systems, and there are several powerful ways to customize the output code such as typemaps (http://www.swig.org/Doc4.0/Typemaps.html), even to make it more "Pythonic" in the Python case, but those feature may not be obvious to use to developers without SWIG experience. However, in the past we found problems applying SWIG to existing codebases that made heavy use of C++17 features, especially if the codebase was already there and it did not evolved considering SWIG additional constraints from the beginning, see ami-iit/bipedal-locomotion-framework#129 for that specific case I am referring to. In that case, even coming up with a MVP in SWIG was complicated, so we went for pybind11 as it seemed to work fine. Probably in this case, it could make sense to try to first wrap a few classes in a complex project that could create the most challenges, such as ign-gazebo, and only afterwards take a decision also for the "simple" projects. This may feel strange as it goes against the tipical workflow of proceding by incremental complexities, but in this case proceeding by incremental complexity may risk to lead to integration challenges. |
In the past few years we've got some experience with SWIG and pybind11, both have pros and cons, and the choice really depends on where the maintainers want to put their effort. From what I've read about your target, neither of them are 100% compatible. I'll keep this short, if I can provide more details let me know, I can elaborate more if needed. Here below a rather unorganized list of thoughts. The most important difference between two options is the language support, pybind11 only supports Python (and any language that can call Python code like Matlab). So, if you really need Ruby, pybind11 is not an option [1]. On one hand, SWIG is fairly straightforward if the public APIs do not use extensively C++17 types (e.g. In case you want to play with both of them, I maintain a simple example you can use as starting point. Maybe this can be useful. This being said, from my knowledge and experience of your APIs, I'd feel to recommend playing with pybind11. However, the language support could be the real blocker here. Not sure if this is the best point to drop links, but especially for ign-gazebo, this functional documentation could be insightful. I'm not aware of any similar functionality offered by SWIG. [1] Then, it would be interesting to understand whether Ruby is used extensively by anyone outside OR or, in the case Python bindings would become complete, if there would be any interest from the community of using Ruby instead of Python. For JS the situation is a bit different, but maybe WebAssembly or similar technologies could offer a more modern approach to expose C++ code to the web.
Requoting the same question, for ScenarIO (the C++ backend behind gym-ignition) we use SWIG for historical reasons. When the project started we never used pybind11 and we didn't even considered it initially. Today, I often think to switch to pybind11, and it's likely to happen in a future major release. |
Just FYI, cross-language callback functionalities are provided by SWIG "Directors" feature (see http://www.swig.org/Doc4.0/SWIGDocumentation.html#SWIGPlus_target_language_callbacks), but at the moment that feature does not support |
I did a bit of investigation into python bindings generators for rclpy and summarized it in this google doc. There's a section with the advantages and disadvantages of SWIG. Ultimately we chose pybind11 for rclpy.
+1 to this, to give more detail: Say you're binding an Ignition Gazebo C++ function that accepts an Does |
Thanks for the inputs so far, everyone! We're discussing them all. I just wanted to address one comment which I think is important:
The equivalent for C++ is often asked: why would someone choose It's important to point out that Ignition Math is not "just" another linear algebra library. It provides lots of robotics-specific functionality on top of a few basic types, which are really useful in the context of simulation and other robotic applications. Picking a few classes from the complete list:
We recognize the advantages of specialized libraries like Eigen and NumPy, and strive to be inter-operable with them. We already provide conversion functions for Eigen, and once we have a Python API, it would be great to provide conversions to NumPy as well. |
I just noticed the eigenpy project that provides efficient bindings between numpy and Eigen using boost-python:
the boost dependency is not ideal, but otherwise it sounds pretty compelling |
Looks like pybind11 has built-in support for Eigen and numpy https://pybind11.readthedocs.io/en/stable/advanced/cast/eigen.html. |
We added SWIG wrappers to all of Ignition Math, then converted them all to pybind11 wrappers and kept the SWIG files for the Ruby interface. That was a lot of work by @LolaSegura , @WagnerMarcos , @francocipollone and @ahcorde 👏 What's left to close this issue:
|
Done! |
Desired behavior
We should provide a Python interface to Ignition Math to make its APIs available to more users.
We've been using SWIG to generate Ruby interfaces, and can do the same for Python. Issue #101 is tracking the addition of SWIG interfaces.
Alternatives considered
Implementation suggestion
https://github.com/ignitionrobotics/ign-math/blob/6534dab9a2ddaaa7659e7ec132f218068a767365/src/CMakeLists.txt#L41
python3-ignition-math6
Debian packageAdditional context
Ignition Math's Python interface will be useful for gazebosim/gz-sim#790.
The text was updated successfully, but these errors were encountered: