Skip to content
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

port python_orocos_kdl to ros2 #4

Closed
wants to merge 5 commits into from
Closed

Conversation

mjbogusz
Copy link

@mjbogusz mjbogusz commented Dec 8, 2017

This PR enables PyKDL usage in ROS2.

Fixes in SIP are by @rkojcev and @vmayoral, so is basic adaptation of package.xml and CMakeLists.txt to ament, I've additionally added triggering PYTHONPATH hook (as ament does not support SIP packages yet) and improved installation of compiled objects.

@@ -39,7 +39,7 @@
// If argument is a Python string, assume it's UTF-8
if (sipIsErr == NULL)
#if PY_MAJOR_VERSION < 3
return (PyString_Check(sipPy) || PyUnicode_Check(sipPy));
return (PyBytes_Check(sipPy) || PyUnicode_Check(sipPy));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the PyBytes_X functions are Python3 only (https://docs.python.org/2.7/c-api/string.html) so the PyString_X calls within the #if PY_MAJOR_VERSION < 3 should stay unchanged AFAICT

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems right. As stated in the PR, changes within the SIPs are by @rkojcev, but if needed I can rebase and remove those changes.

if (PyString_Check(sipPy)) {
*sipCppPtr = new std::string(PyString_AS_STRING(sipPy));
if (PyBytes_Check(sipPy)) {
*sipCppPtr = new std::string(PyBytes_AS_STRING(sipPy));
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above, this is within a #if PY_MAJOR_VERSION < 3 block so probably it can be left untouched.

@mikaelarguedas mikaelarguedas added the in review Waiting for review (Kanban column) label Dec 11, 2017
@mjbogusz
Copy link
Author

I've removed the unnecessary changes and added one additional python2/python3 check so that it should work with both.
@mikaelarguedas fyi

@mjbogusz mjbogusz force-pushed the ros2-pykdl branch 2 times, most recently from f0e3f64 to 7ef822c Compare December 12, 2017 20:15
@mikaelarguedas
Copy link
Member

thanks @mjbogusz for iterating.

Do you have any reference code you use for testing the good functionment of this package ? (as it doesn't have tests)

@mjbogusz
Copy link
Author

Currently I do not, I'm yet to create my modules utilizing PyKDL (as of now I'm only creating some frames and multiply them together - this much seems to work).

However if you'd point me towards a good example of how to set up tests in ament_cmake I can try to run the ones included in python_orocos_kdl/tests. Is ros2/system_tests, specifically test_communication, a good point of reference besides the overcomplicated CMakeLists?

@mjbogusz
Copy link
Author

mjbogusz commented Dec 15, 2017

I've fixed the included tests (Class.None, opening a file in binary mode and some whitespace problems) and they all pass.

I'm working on including them in CMakeLists.txt.

Edit: I've just noticed that those tests use unittest while ament only supports pytest... This might take a while.

@mjbogusz
Copy link
Author

Tests are in 👍

@mikaelarguedas
Copy link
Member

Thanks @mjbogusz !

I've additionally added triggering PYTHONPATH hook (as ament does not support SIP packages yet) and improved installation of compiled objects.

Yeah ament_python has some macros that go in that direction but nothing that would work out of the box for sip packages AFAICT.

I've removed the unnecessary changes and added one additional python2/python3 check so that it should work with both.

👍

I don't have write access to this branch so I pushed a few fixups to https://github.com/ros2/orocos_kinematics_dynamics/tree/ros2-pykdl (mostly to get the tests to run without having to source the workspace). Would you mind cherry-picking them on this branch ?

I think with the fixups it's good to be merged 👍

Looks like just installing sip was not enough to get it to build on our farm:

  • Linux Build Status
  • Linux-aarch64 Build Status
  • macOS Build Status
  • Windows Build Status

I'll take a closer look at it early next week

@mikaelarguedas mikaelarguedas self-assigned this Dec 15, 2017
@mjbogusz
Copy link
Author

mjbogusz commented Dec 16, 2017

Would you mind cherry-picking them on this branch ?

You mean, merging them into my PR branch?

@mikaelarguedas
Copy link
Member

You mean, merging them into my PR branch?

Yes please 👍 , any solution bringing the changes from 20b998a into this PR branch is fine

@mjbogusz
Copy link
Author

mjbogusz commented Dec 17, 2017

Done
I've also moved find_package(ament_cmake_pytest) inside the if(BUILD_TESTING) block so that it's not required without --build-tests - this way it also builds on R2B3 (I'm yet to port my project onto 1.0 - I have a feeling this should've been beta4...).

Edit: I've also added a status message in FindSIP.cmake - I have a suspicion that FindSIP.py is being run with the default python (as in: python2).
Edit2: I'm quite sure of it - the reported error is ImportError while Python3 would report ModuleNotFoundError. No idea why it's not respecting the PYTHON_EXECUTABLE variable though.

@mikaelarguedas
Copy link
Member

Edit: I've also added a status message in FindSIP.cmake - I have a suspicion that FindSIP.py is being run with the default python (as in: python2).
Edit2: I'm quite sure of it - the reported error is ImportError while Python3 would report ModuleNotFoundError. No idea why it's not respecting the PYTHON_EXECUTABLE variable though.

As we are using Ubuntu Xenial (python3.5) the error would be ImportError (ModuleNotFoundError is a 3.6 feature AFAICT). If you look at the OSX and Windows jobs that failed above (they use 3.6.3) they do raise ModuleNotFoundError as expected.

I looked a bit into it and I it looks like its using the right python interpreter its because of a mismatch between the sip modules installed when installing python3-sip from apt and sip from pip3

The one from apt (python3-sip(-dev)) provides a sipconfig module as well as a sip executable. The one from pip doesn't provide any of those only a sip python module. I started modifying the script to support both configurations but it's not working/tested yet: 465eb14

@mjbogusz
Copy link
Author

I've run this file on some configurations. Seems just about right 👌 maybe except the doubled output when sipconfig is not available ;)

However while I'm not sure if that's an issue here, SIP's pip page says:

All wheels include the sip extension module but do not include the code generator.


Anyway, here are outputs from different configs:

Arch with python 3.6.3 and SIP installed via pacman (python-sip - python 3 is the default here):

sip_version:041306
sip_version_str:4.19.6
sip_bin:/usr/bin/sip
default_sip_dir:/usr/share/sip
sip_inc_dir:/usr/include/python3.6m

WSL (aka Bash on Windows - here acting as Xenial) with python 3.5.2 and SIP from pip3:

could not import 'sipconfig' module, try to import 'sip' instead
sip_version:041306
sip_version_str:4.19.6
sip_bin:/usr/bin/sip
default_sip_dir:/usr/share/sip
sip_inc_dir:/usr/include/python3.5m
sip_version:041306
sip_version_str:4.19.6
sip_bin:/usr/bin/sip
default_sip_dir:/usr/share/sip
sip_inc_dir:/usr/include/python3.5m

Same WSL with SIP from apt (python3-sip):

sip_version:041100
sip_version_str:4.17
sip_bin:/usr/bin/sip
default_sip_dir:/usr/share/sip
sip_inc_dir:/usr/include/python3.5m

Also it's quite interesting what files are inside the packages available for Xenial:

/usr/lib/python3/dist-packages/sip.cpython-35m-x86_64-linux-gnu.so
/usr/lib/python3/dist-packages/sipconfig.py
/usr/lib/python3/dist-packages/sipconfig_nd5.py
/usr/share/doc/python3-sip/changelog.Debian.gz
/usr/share/doc/python3-sip/copyright
/usr/share/python3/dist/python3-sip
  • pip3 (printed when uninstalling):
  /usr/local/lib/python3.5/dist-packages/sip-4.19.6.dist-info/INSTALLER
  /usr/local/lib/python3.5/dist-packages/sip-4.19.6.dist-info/METADATA
  /usr/local/lib/python3.5/dist-packages/sip-4.19.6.dist-info/RECORD
  /usr/local/lib/python3.5/dist-packages/sip-4.19.6.dist-info/WHEEL
  /usr/local/lib/python3.5/dist-packages/sip.so

@mjbogusz
Copy link
Author

Also while scrolling through jenkins logs I've found out that it installs SIP from both apt (while building dockerfile, at 14:34:05 of this specific run) and from pip3 (while installing python packages within the container in venv, 14:40:48, 14:40:54 and 14:40:55)

@mikaelarguedas
Copy link
Member

maybe except the doubled output when sipconfig is not available ;)

Haha yeah its just me printing my debug output to stderr. That's not going to stay :)

Also while scrolling through jenkins logs I've found out that it installs SIP from both apt (while building dockerfile, at 14:34:05 of this specific run) and from pip3 (while installing python packages within the container in venv, 14:40:48, 14:40:54 and 14:40:55)

Yes you're right, sorry I should have pointed it out earlier, we currently do the same venv setup for all platforms (including linux regardless of what has been installed via apt in the Dockerfile), that's definitely something we could iterate on the later. The main thing I wanted to confirm is "is installing sip from pip is enough to build this code?".

As you saw in the release notes and as I confirmed locally: the answer is no (we need the sip headers, libraries and generator for this package to build). I confirmed that building sip from source and installing it provides all the necessary files so tweaking the FindSIP.py script will become irrelevant (as the from source install does provide the sipconfig python module).

So what we need is a way to get the full sip on all platforms:

  • on MacOS: sip is available from homebrew so it "should be easy": (brew install sip)
  • on Windows: I didnt see a chocolatey package for it: we need to either:

@mjbogusz
Copy link
Author

I'd say that a chocolatey package is better - both vendor packages you've linked are working OK, but some are not as good, e.g. rviz_yaml_cpp_vendor (ros2/rviz#152 and related PRs).

Also I think it'll save some time when RQT tools will start getting ported to ROS2 - I may be mistaken but I think PyQT required SIP.

@mikaelarguedas
Copy link
Member

mikaelarguedas commented Dec 17, 2017

I may be mistaken but I think PyQT required SIP.

You're totally right, I actually think that SIP was developed by the PyQt effort.

I'd say that a chocolatey package is better - both vendor packages you've linked are working OK, but some are not as good, e.g. rviz_yaml_cpp_vendor (ros2/rviz#152 and related PRs).

Yeah in the case of the ones I linked, they provide a failsafe as if users don't have the dep on their system it will download and install it for them. So they work "in addition to" the chocolatey packages.
So maybe I shouldn't have presented them as mutually exclusive. Either option would get us something that will allow to build python_orocos_kdl. Having both would provide a better user experience in general.

I'll test the MacOS test case on Monday.

If it works out of the box:

  • let's focus on the chocolatey package

If it doesnt work out of the box and seems painful:

  • let's focus on the vendor package (as it will solve both the MacOS and Windows use case).

How does that sound ?

@mjbogusz
Copy link
Author

Sounds A-OK.

I've tried looking into creating a choco package, but I've spent way too much time setting up the whole required VC++ stack.

Also I have no idea how to install python modules using chocolatey - assuming e.g. "C:\Python36\Lib\site-packages" is not the best option. And last but not least we have to install sip.h in a way it's accessible for the code generated by SIP via #include <sip.h>...

@mikaelarguedas
Copy link
Member

So it looks like python modules installed via brew are not findable in a python virtualenv, they recommend using pip instead. As the sip version doesnt provide us the files we need we'll have to do a vendor package for now.

Also I have no idea how to install python modules using chocolatey - assuming e.g. "C:\Python36\Lib\site-packages" is not the best option. And last but not least we have to install sip.h in a way it's accessible for the code generated by SIP via #include <sip.h>...

That;s a good question, we haven't packages any mixed python/C++ packages with choco yet. Maybe @nuclearsandwich will have some insights on the preferred install locations

@mjbogusz
Copy link
Author

python modules installed via brew are not findable in a python virtualenv

It should work if one was to believe the docs... And as per https://stackoverflow.com/a/26322102/3217805 (the 'edit' part) it might be required to manually set PYTHONPATH:

editing PYTHONPATH in ~/.bash_profile forces virtual environments to inherit global packages

However I have no experience with brew (or development on osx) whatsoever so that's just a


About choco: I've found out that PYTHONPATH env variable should work under Windows more or less as expected and choco can set it for us (caveat: we might have to add python's main site-packages to that variable too).

Also, if I understand it well enough, VsDevCmd.bat (VS's native tools command prompt) sets the include directories for VC++ so we should be able to add our path to those too:

@if not "%WindowsSdkDir%" == "" @set PATH=%WindowsSdkDir%bin\x86;%PATH%
@if not "%WindowsSdkDir%" == "" @set INCLUDE=%WindowsSdkDir%include\%WindowsSDKVersion%shared;%WindowsSdkDir%include\%WindowsSDKVersion%um;%WindowsSdkDir%include\%WindowsSDKVersion%winrt;%INCLUDE%
@if not "%WindowsSdkDir%" == "" @set LIB=%WindowsSdkDir%lib\%WindowsSDKLibVersion%um\x86;%LIB%
@if not "%WindowsSdkDir%" == "" @set LIBPATH=%WindowsLibPath%;%ExtensionSDKDir%\Microsoft.VCLibs\14.0\References\CommonConfiguration\neutral;%LIBPATH%
:: and then
@if exist "%VCINSTALLDIR%ATLMFC\INCLUDE" set INCLUDE=%VCINSTALLDIR%ATLMFC\INCLUDE;%INCLUDE%
@if exist "%VCINSTALLDIR%INCLUDE" set INCLUDE=%VCINSTALLDIR%INCLUDE;%INCLUDE%

@clalancette clalancette added in progress Actively being worked on (Kanban column) and removed in review Waiting for review (Kanban column) labels Jan 18, 2018
@mjbogusz
Copy link
Author

A colleague of mine has tried using this package in Ubuntu 17.10 and 16.04 and he was consistently encountering a segmentation fault when requiring PyKDL (stacktrace pointed at missing strcmp_avx2 or something like that).
Seems like there's something wrong either with the functions called in ifdefs or with those ifdefs themselves.
I'll try to reproduce that behaviour and possibly fix it, but for now I'm considering this PR broken.

As a sidenote, any news on the vendor package?

@mikaelarguedas mikaelarguedas added ready Work is about to start (Kanban column) and removed in progress Actively being worked on (Kanban column) labels Mar 22, 2018
@allenh1
Copy link

allenh1 commented Dec 6, 2019

@clalancette is anyone working on this at the moment?

@clalancette
Copy link

@clalancette is anyone working on this at the moment?

Not that I know of; @mjbogusz may still be interested. I think there is the open question about SIP, but it is worth looking at again.

@ivanpauno ivanpauno added backlog and removed ready Work is about to start (Kanban column) labels Feb 13, 2020
@ivanpauno
Copy link
Member

Closing due to long time inactivity._

@Flova
Copy link

Flova commented Dec 9, 2021

Any updates on this?
It breaks the tf2_geometry_msgs package which is quite essential for many python nodes that use tf2.
Are there any obvious workarounds for this, that I have missed?

@Flova
Copy link

Flova commented Dec 9, 2021

See ros2/geometry2#285

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants