-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
New Python API #3801
New Python API #3801
Conversation
Edit: For anyone arriving here late who doesn't want to scroll down through what has now become a great wall of text, here is a link to my current draft of this New Python API. It's still fairly rough, but is quite usable already, and will keep improving. Bug reports and suggestions welcome! https://github.com/Justin-Fisher/new_python_api_for_webots Continuing discussion from #2358. The proposed export mechanism to make constants available in .dll's looks like it would be useful, and this would provide a nice means for other languages' API's to always get up-to-date values for the constants. I wasn't sure about the names you export them as though. In the C documentation, these are given names beginning upper-case Is there a unified list of all Webots constants somewhere (or a list of all the ones that we'd want to export for use in other languages' API's anyway)? This could be a useful checklist if you're looking to add similar exports to the remaining constants. If not, I have available a list of how all the constants appear in the swig/C++ version, and I have an algorithm that does pretty well at translating those names into the C naming scheme which matches the documented names for the dozen or so that I manually checked, but if any constants have idiosyncratic names this algorithm might not handle them correctly, and without a list to check against I don't have a good way to be sure, short of trying to go look them all up in a bunch of different places, which I'm not eager to do. Even if my list isn't perfect, it might still be a useful checklist. |
I believe both versions are needed. the switch(node_type) {
case wb_NODE_CONE:
... Because |
Also, is the roundabout import into Python using Incidentally, I've set my version up to have a small handler handle API calls so (at least for now) I could use the swig/C++ names for API methods and have the handler automatically translate them to the corresponding C-name (and cache the results so there's no notable performance hit). This approach would support the fairly attractive notation of using |
The list of constants is computed by the matlab script and they will appear as files in the matlab folder with uppercase filenames (not on github, but in your local installation). |
If one version will be used only under the hood in the C source code (will it?), and the other version will be exported for other people to use, then I would suggest making the version that gets exported have the name that matches the documentation. E.g., call the enumerated local version |
I just test it but unfortunately, it doesn't work... We have to rely on the more complex version. |
The |
The more explicit type conversion like that we have to do, the more annoying it will be to write the Python controller manually, though I can probably jerry-rig a system that hides these extra steps under a convenient notation. For some reason, the Edit: Reading up a bit more, it looks like |
This will be annoying only for us, developing the webots python module, not for users, but if you can jerry-rig something to make this smoother, that would be nice.
Yes, but generating a |
I just added a helper function to make it easier for us to retrieve constants. |
So I've extracted all the constants from the Matlab controller, and I've gone through all the constants that were used in the swig-produced
I think the first two are probably errors of omission in the Matlab controller, since it doesn't seem to define anything like these, so perhaps these should be added there? So, anyway, I've now caught us up to the Matlab controller regarding constant-importation. Whenever constants get changed, the Matlab controller would have to be manually updated. If we're happy enough having the new python controller be like that too (at least for now), then I've got a copy of the matlab constants ready for us to use, and I can automatically-rewrite the swig controller.py to use these. (Of course, it would be nice eventually to have both Matlab and Python import current values for these constants, so that they wouldn't require manual updating whenever constants change.) Another quality-assurance check I should probably do, since it'd be pretty easy, is checking whether MATLAB and swig/C++ actually do assign the same values to all the constants! |
I believe the problems come from the scoping of these constants. In C and Matlab, no scoping is possible hence all the constants are defined at a global scope. In OO languages, such as C++, Java and Python, the constants are scope with objects, e.g., Supervisor.MOVIE_READY or Field.MF_ROTATION which looks better. As a consequence there is no one-to-one match between the C/Matlab implementation and the C++/Java/Python implementations. However, there is not a huge number of constants and I believe that a minimum of manual maintenance for them is acceptable, as it would be quite difficult to automate this fully. |
Yes, much of the automated name-translation system I came up with was translating between the Matlab/C naming system that keeps everything at global scope, and the swig naming system which also transfers the constants from C++ to Python using constants with global scope, but uses different naming conventions to reflect which local scope each constant will live at in the C++/Python API's. The exceptions I listed above aren't just further examples of this. The Matlab API doesn't define anything at all for these constants, not just some different way of naming them. The only Matlab constants that don't have analogs among the swig constants are It looks to me like the Matlab API doesn't offer any way of telling whether a node is an Altimeter by comparing it to a constant like Similarly, the Matlab API doesn't define The various |
Ok, I have compared the constant values produced by the swig/C++ controller to the corresponding constant values produced by the Matlab controller. The good news is that most of these match up perfectly, which confirms that my name-translation system is working well, and that the list of constants I've produced is mostly right. The bad news is that most of the node-type constants are one smaller in the Matlab version than they are in the swig/C++ version of Webots, which, as I speculated above, probably stems from the fact that Matlab left Edit: I submitted a PR #3808 to fix the constants in the Matlab generator. |
Thank you for reporting this bug in a separate issue. We will look into it and hopefully fix it soon. |
Just a note to report that I've been making good progress, with the supervisor/world near-completely tested (as much as I'm planning to, anyway) and filling out a lot of the ordinary robot devices that I'd been delaying. My real life will have some upheaval due to travel over the next two weeks, but I expect to continue making progress on my laptop. |
What sorts of The Display documentation says "WB_IMAGE_BGRA is the recommended one and the image format returned by a Camera device" but then the sample code it gives immediately after that which is supposed to convey a camera image to a display instead uses I've generally been processing In other, somewhat related news, nightly builds on my laptop are having lots of difficulties with textures, saying that jpeg is an unsupported image format, and not showing |
Thank you for pointing out the inconsistencies in the documentation, I just fixed them in #4550. To summarize the current behavior of the C API:
|
In asking what sorts of I agree that it'd also be best to be able to somehow handle each of the permutations like |
Ideally, the formats the new Python API should use and support for images ( Webots copies the received input image independently from the format, but if the image is in BGRA format the copy method is slightly faster. From my limited personal use of images in Python, I'm currently not very convinced that representing images in the Python API as a list of Color objects is the best approach to achieve the optimal compatibility and ease-of-use. |
This has become a wall of text, so I'll boldface the questions and important bits. At a minimum it seems like we should aim to provide backwards compatibility with whatever If there are other datatypes that the old API didn't accept that are easy enough to implement, I'm happy to add on. I have now set this up to very efficiently handle (There may be some wrinkles involving common cases where people slice/stride their Numpy arrays (e.g. to pick out a rectangular sub-region, to transpose an array, or to sample only those pixels whose x and y values are both even), whereas Webots needs the data to be contiguously packed. But I think I may be able to find a general work-around for those too.) You're right that C is generally faster than Python, but if we still want to accept lists of non-byte numbers (do we?), I think I'll have no choice but to munge them in Python, to convert them to the byte color components that the C-API requires -- or can the C-API for You seem to think I'm keen to create 2D lists of And some more questions about display images. Are images supposed to be tied to particular displays, or could the same image be pasted to multiple displays? If they're not supposed to be tied to particular displays, why do When a controller stops, is it important that the controller explicitly Is it fine to |
Here are some answers
Yes, the current Python API accepts two different inputs where the type of each pixel value is a 'char' or integer 0-255.
I think it is fine.
I'm not sure why we should accept lists of non-bytes numbers.
No. Only chars (integer 0-255) are supported.
It is straightforward to convert lists to Numpy array. We could deprecated the lists as input but still continue to support it for backward compatibility.
In the first version of the new Python API I think it could be better to stick to the current functionalities.
Images are passed only to the Display device with the corresponding tag.
Yes, Webots clears all the images when the world is unloaded.
Yes. |
What is the preferred way to provide sample controllers in multiple languages for the various included Webots sample worlds?
I'm not sure how many of these samples I'll end up making New Python API versions of. Thus far I've just been re-doing the ones that changed more in the new API, like supervisor ones, or ones with high-bandwidth devices like cameras and radar. |
By default, Webots will run the executable file if any (compiled from a C or C++ source). If not found, it will search for a
This is something we did with the nao_demo_python example which is the counterpart of the nao_demo C controller. However, we did not provide a corresponding world file for the Python version, so users have to change manually the controller from the C one to the Python one, which is not ideal. Making a copy of the world file is also bad because it introduce a lot of redundancy. Finally, having the
That might be a good idea. We started this inside the python project folder. It would be possible to put more example in there as well. The big advantage of this approach is that python simulations would run out-of-the-box and controller folders wouldn't be cluttered with C code. I see two drawbacks: (a) world files will be duplicated (redundancy and maintenance problem) and (b) the comparison between the C and Python controller is more difficult than in (1).
I would recommend to go for approach (1), as it seems to be the best one to me. Note: we decided a long time ago to give priority to binary code in controllers (instead of Python code) simply because when you install Webots on Windows, there is not necessarily Python installed and hence the Python controllers will be unable to start, giving a bad first impression. We could however reconsider this. To avoid the bad impression effect, we could simply test for the existence of Python and if not present we would not attempt to run the Python controller, but run the binary controller instead. However, this means that every controller (at least in the guided tour) should have at least a binary version to ensure it will always start-up on Windows without Python. Note: the code for the controller language priority is here. |
For now I'm accumulating finished variants of Webots samples in my work-in-progress version of the new API. I have been preserving copies of the old C / C++ versions alongside, mostly in case I or anyone else wanted to compare. At some point we can decide whether to merge these in with the samples for other languages (which would require adding supervisor powers to some of the sample robots) or just to include them in a separate folder of python samples. Yeah it makes sense to have the auto-tour not try to run things that won't run on a given computer. It's actually given bad impressions to me and my students the way it is, because (a) the executables that you have it run often trigger anti-virus checks and Webots often crashes waiting for the check to complete, and (b) because one of the early samples is the drone-flying one which, for some reason, is super processor-intensive and runs extremely sluggishly on many computers that can run other simulations just fine. So there's definitely room for improvement in first impressions from what the auto-tour plays. I noticed in the radar sample that the radar device gives negative I don't yet understand |
Thank you for this feedback. It is indeed very useful. We are currently very busy preparing the new release of Webots R2022b scheduled for the end of June. Hopefully, we will have time to take into account this feedback. |
Okay, it took quite a bit of wrestling but I now have lidar point clouds working, and a much more informative sample lidar for the new python API, showing how to transfer lidar range/cloud images to numpy, how to do a bit of processing on them, e.g. to paste back into webots display images and/or to do simple wayfinding. I can now confirm that the answer to my above question is that the lidar cloud is just a full rectangular image (though with some 'inf' values that cause a sort of sparseness), and that its Webots docs sometimes say that a returned pointer points to memory managed by the simulation and should not be released by the controller. They do not explicitly say this for the pointer to an array of RecognitionObjects returned by Also related to such pointers, one design decision I'm running into is when to make a copy of pointed-to information? For high-bandwidth devices like Cameras and Rangefinders, I had not been intentionally copying information at all (aside from offering a Anyway it could help to know:
Update: I've now gotten it set up to work as I described in 3. I think the only shared-memory objects that ordinary users should now receive are |
In other news, I'm happy to report that I think my version of the New Python API is now quite close to being feature-complete. I.e., there aren't any more big things that I know I need to add to it. There may however be many bugs, especially because I haven't yet exposed all the devices to thorough testing. The main items that remain on my to-do list for this are:
It should be quite feasible to have this all done by end of month if you wanted? Or it might make sense to gather input from more beta testers first. Up to you! |
It's great to finally see the first version of this new python API! Congratulations! |
Sure, it'd be good to get feedback from whatever testers you can find. It's currently far from perfect though, but it's getting there, and hopefully they'll understand that there may still be lots of bugs. |
All right, then I will post some announcements about it. |
I noticed that I left out Does Webots keep track of two separate contact points tracking statuses: one for including descendants, one for not? So you could be tracking one of these, or the other, or both? Or can there be at most one sort of tracking happening at a time, and either it includes descendants or it doesn't? (I implemented the new Python API in a way that effectively presumes the latter "just one sort of tracking at a time" reading, but perhaps that was mistaken?) |
Yes, unfortunately.
Yes, you are correct, only one sort of tracking can be active at a time. |
Now that we are done with the release of Webots R2022b, I wanted to inquire on the status of this PR. Did you receive any feedback from users? Did you progress with the documentation? I would like to move forward integrating this new API in Webots R2023a. I guess the first step would be to create a PR here that would basically import your code from https://github.com/Justin-Fisher/new_python_api_for_webots and add the documentation in the Webots user guide and reference manual. Shall we go ahead this way? |
I would like first to try to re-implement the current Python API without swing to improve the user experience for Python users (our library won't be tied to any specific version of Python) and simplify our Python workflow. So, I will close this PR and open a new one on the same branch to go ahead with this implementation. This should facilitate the implementation of the new API, which could be implemented in a second step, once this branch is merged in the develop branch (or even earlier, on a new branch targeting this branch). |
Fixes #2385.
This PR aims at implementing a new python controller API for Webots replacing the previous one with the following advantages:
Robot.get_device()
method.