#74 Declined
Repository
Branch
feature/py_wrap
Repository
Branch
develop
Author
  1. Andrew Melim
Reviewers
Description

In progress python wrapper code. Creating the pull request so we have an area for discussion and way to easily look at the current progress of the wrapper

Comments (17)

    1. Andrew Melim author

      Hey Paul, I think I'm good for now. I'm in the process of traveling for the holidays some haven't had the chance to try your recommendations on the includes yet. I'll let you know of it's still an issue once I add the fix.

  1. Frank Dellaert

    @Ellon Paiva I will look into this now (slowly, don't have a lot of extra time). Can you remind me:

    • How do I invoke the wrapping in the python case?
    • why are there two calls to wrap_and_install_python? (I see two CmakeLists.txt where there is one below)
    1. Ellon Paiva

      (Sorry, I didn't realized you were also mentioning me from this PR)

      Good to hear things are working! I'm refreshing my memory regarding the automatic generation of the wrapper. I'll answer your question below asap.

      Meanwhile, did you manage to load the auto-generated python module (gtsampy)? I'm getting an error here:

      In [1]: import gtsampy
      ---------------------------------------------------------------------------
      ImportError                               Traceback (most recent call last)
      <ipython-input-1-94a2b19c360f> in <module>()
      ----> 1 import gtsampy
      
      /home/emendes/devel/lib/python2.7/site-packages/gtsampy/__init__.py in <module>()
      ----> 1 from ._libgtsampy import *
      
      ImportError: dynamic module does not define init function (init_libgtsampy)
      
    2. Ellon Paiva

      Basically the problem was that the grammar of the automatic wrapper currently does not accept numbers (and I think basic types as well) as template arguments.

      In boost python sometimes we need to create function pointers to specify which method we're calling when the method has overloads that take different lists of arguments. To create the function pointer we need the full signature of the method (longer list of arguments), and the problem arises when the method uses templated types like Optional Jacobian. When this happens, we need to write the templated type (OptionalJacobian<4,3> for example) in the interface file gtsampy.h, so it gets copied in the generated file used to compile the module, but this kind of construction is not accepted by the grammar.

      I don't know if I was clear enough. I explained it with some examples here and here before starting wrapping everything by hand.

      1. Frank Dellaert

        Awesome, yes! This is a great summary of the issue, and your handwritten Pose3.cpp class gives a good target to work towards. I'll see what I can do (though I'm rusty now on wrap).

      2. Frank Dellaert

        BTW, @Ellon Paiva OptionalJacobian is of course meant to return a Jacobian. Do you have an example with your Pose3 wrapping (or any other class) that actually achieves this? It is not obvious to me (yet) how to make this happen.....

        1. Ellon Paiva

          No, I do not have an example. In fact, I just found the problem because when wrapping I found some methods that I couldn't expose via the simple way (overloading macro + .def line).

          I'm not sure how to return the jacobian through the method arguments in python, it it can be done at all. From what I read, the pythonic way of doing it would be to return the jacobian as extra arguments of the method, since python accepts returning more than one value, like in Matlab. To do this in the wrapper, I think a interface function needs to be created (like Quaternion_0 and Quaternion_1 on python/handwritten/geometry/Rot3.cpp), that will call the C++ method, receive the jacobians from the method, then compose the result and the jacobians in a tuple and finally return it to python.

          1. Frank Dellaert

            Interesting. The issue with that solution is that we would always compute the derivatives then, no? Or can we detect how many output arguments are asked for? And which ones?

            Still seems to me it could be possible to pass a writeable reference to an np.array, which is what I would prefer (but I don't know how to do).

            1. Ellon Paiva

              Yes, these are good questions. I also don't have the knowledge on python or boost python to answer them.

              I quick search tells me that passing a "mutable parameter" to a function makes it possible to return the jacobian matrix by parameter, like it is currently in C++. Although I think adding a named parameter to the method (something like "..., jacobians=true") to the function call would be the best way to trigger the computation of jacobians, returning them together with the values as a tuple. I'll dig more into it next week.

              1. Frank Dellaert

                Actually, I looked into the numpy_eigen code and I think it can be done. We just need a type_convertor from Python to OptionalJacobian, that takes either None or a numpy array of the correct size. It should be seamless. I'll experiment a bit..