Here is a GIST of the Error, my findings and links to the supporting data
-John
ROS Resources: ROS Homepage | Media and Trademarks | Documentation | ROS Index | How to Get Help | Q&A Help Site | Discussion Forum | Service Status |
Here is a GIST of the Error, my findings and links to the supporting data
-John
Okay, so you are trying to install something on an unsupported platform (Ubuntu 23.x) per REP 2000: REP 2000 -- ROS 2 Releases and Target Platforms (ROS.org)
You are also pip
installing a package that isn’t part of ROS: accelerate · PyPI
And you are running into a Python language change where you shouldn’t be installing python packages system-wide per PEP 668 (PEP 668 – Marking Python base environments as “externally managed” | peps.python.org)
I don’t think any of this is a ROS or ROS tooling problem and not particularly relevant to the thread.
Hmm, this detour reminded me of one more thing that seems hard to understand to newcomers, and with which they fight a lot - the practically non-existing support for creating ROS workspaces in Python virtual environments. I think this might be one of the larger pain points for people coming from pure Python world.
However, I don’t say I know how to solve this issue. I know that just pulling the newest versions of everything from pip would not work. I know that starting from a requirements.txt with APT versions of respective packages, you could get quite close to get a working system. But given the general brokenness of pypi packages, it will almost inevitably happen that some unrelated packages will update some vital package to a non-supported version (one of the pytorch dependencies started recently installing upstream cmake distributed via pip - holy cow!). But it would be great if somebody could come up with at least a partial solution (in the sense that it works well for building my one tiny beginner DL CNN LLM package that just wants to communicate via ROS, while it might be unusable if you’d want to create a library for others to depend on). This could be similar to how python3-*-pip
rosdep keys work now. You can use them in local installs, but the buildfarm will choke on them.
Thinking about this a bit more, shouldn’t we consider providing an option to create “2nd class citizen” packages, in the sense that these packages could only be “leaves” of the dependency graph, but such packages could be much simpler to create (and maybe even to build)?. This might be sufficient for a lot of beginners. It would hinder the (so far great) ability to reuse ROS packages, but it might help lower the traction for newcomers…
Not to sound like a broken record, but our friends at the pixi
project (and conveniently robostack) may have come up with an answer for this as well: Unleashing PyPI support in pixi | prefix.dev
It should be safe to conclude that:
From my personal experience with ROS/ROS2 build system (only the C++ part), I think a lot of the issues are from the balance between readability/maintainability and easiness of use.
One example is the many “convenience macros” (especially the family of ament_auto_*) for CMake from ament_cmake. For use cases that are well covered by these macros, they are indeed convenient. But remember we live in an imperfect world and not every user understands the limitations and suitable use cases of the macros well enough to always use them properly. When things break, it becomes more frustrating to find a fix, for both beginners and amateurs. In my opinion, ament_cmake should target guiding people to use modern plain CMake properly and only introduce convenience macros for ROS-specific staff when necessary, not trying to hide CMake or overly simplify the CMakeLIsts.txt by making a lot of things implicit. In this way, students (not familiar with both C++ and ROS) will be able to gradually acquire the skills to use CMake and C++ both inside and outside the ROS world. At the same time, experienced C++ developers (who may not be so familiar with the ROS build system), can still find most of the things familiar. At least for ROS C++ packages, sacrificing a little convenience, doing things in the plain-CMake way as much as possible, and documenting the ROS-specific part more clearly should make the situation a little better.
Here’s some small actionable changes that would make the build system easier to work with:
Make ros-dev-tools
depend on python3-colcon-mixin
and ship with default mixins, and then start recommending them in docs. colcon: error: argument verb_name: invalid choice: 'mixin' on Ubuntu 22 · Issue #36 · colcon/colcon-mixin-repository · GitHub
Make colcon build
and colcon test
have the same verbosity level as the undelrying tool by default so users don’t have to find the --event-handlers=console_cohesion+
every time they want to see the output they are used to with straight cmake or pytest.
Merge all the PR’s in colcon for color output in the terminal. These have been sitting around forever, are extremely helpful when chasing down failures in tests, and most people can see color. We aren’t all colorblind and working on a kindle e-ink display. All of the ones I’ve tested locally work great. Why does calling colcon mean I have to lose color display from the underlying tool?
Put effort into contributing changes upstream to packages instead of maintaining the (hacky) vendored forks. I’ve been working with the ubuntu packaging maintainers on fixing a bunch of CMake problems upstream of the vendored ones so we can use find_package(foo CONFIG)
in the next version of ROS. Those packages don’t use ament, and there’s no problem using them in a ROS environment if they have a proper configuration export.
Side note - If CMake is a pain for you, I highly recommend reading Craig Scott’s book.
I have more, but it would be nice to see if anyone agrees with the above.
ROS has a mentality to wrap everything under the Sun via a set of custom tools. Here we discuss build tools and package managers mainly but this mentality goes down to the transport layer as well.
This wrapping mentality cripples abilities of underlying tools and provides users a lesser experience otherwise they would get from using these tools directly. Forcing users to this “convenient” yet inferior experience is the main discussion point of these threads.
Here I learned ROS Python users are not able to declare dependency on Pypi packages and cannot install if the package is not a part of ROS (as far as I understand). This is a fine example of how the practice of wrapping cripples the user experience as installing Python packages from Pypi is one of the cornerstones of the Python language. Sadly, the user is getting blamed here.
Trying to wrap everything is a dead end. Please let us use regular C++, Python, and Rust tooling. And clean ROS documentation from the custom magic for the future generation. Let them be proper software engineers, not babysitted individuals.
For the Rust and Python tools, your statement is not true as far as I know. Of course you’re allowed to use crates.io (RUST) or Pypi (Python). ROS wants to know what dependencies you want to use. That’s what package.xml is for.
If you really want to compile your projects using only cmake (C; C++) cargo (RUST) or not (Python; Julia), that’s fine, and they’ll work as ros2 nodes when you run them. Then you’ll have to deal with parts of your ros2 toolchain not recognising your package.
My understanding is that wrapping everything and making it easier to use is the origin of the success of ROS. Standardization, putting every single file inside a package, is what allows sharing tools and running everything with a few launch files.
For people willing to, it is still possible to :
I do not feel babysitted when using ROS and the accompanying tools, because I am not a software engineer but a roboticist. My goal is to be able to build a mobile robot, mount a lidar and using it with the nav stack in the same day. Or to welcome a new PhD student and have them run an underwater simulation so they can focus on control / perception / localization, and not CMake and install path voodoo.
Many people just use (and learn) ROS to do robotics. While they sometimes sigh when introduced to packages, workspaces and tooling, I think most of them have no idea what troubles they avoid.
As the end of the year is approaching i’d like to recall this and thank all contributors
Please don’t claim things you haven’t verified yourself.
What you write is objectively false.
It’s perfectly possible to create, build and install packages depending on Pypi packages.
The only thing that is not supported is having them built by the ROS buildfarm.
That’s it.
And the reason? Debian packaging policies. Not something “the ROS community/people in charge have made up”.
So if you’d like your package to be installable using apt
, only then you can’t depend on Pypi packages.
(and if you really, really want to depend on Pypi packages and release them on the ROS buildfarm, you could cheat and ship an entire venv
using something like catkin_virtualenv
)
No one is doing that. And no one is requiring you to do that.
Please stop positing the same things over and over without actually showing concrete examples of how to do what you suggest. No progress will be made by you annoying others by claiming “[this] can be done in a better way” without actually showing how to do that.
And no, writing “come to me for advice when you’re ready / have proven you want to change” is not contributing. Neither is telling people what they are doing is wrong and they shouldn’t be doing it. Hand-waving will also not help. Dismissing people’s motivations, problems or reasoning with a reference to some general principle from scientific literature (which is often so generalised as to be almost useless) will also not help and quite frankly I find it almost insulting to people who actually contribute.
This is true. I have acknowledged that in an earlier thread that ROS1 is successful because of the kitchen sink approach. But it is the exactly same reason why ROS in its current state is unacceptable for professional robotic software development. This is not my imagination, being production grade is one of the design goals of ROS2. As I said, many times I never criticized ROS1 but ROS2. Even though they are very similar from build tooling perspective. But this thread is about ROS2.
Also I suggest any academician here to study Eclipse Zenoh and its build system. Ask your students’ opinion about their experience when building a Zenoh application. Then ask them the names of build tools to build a Zenoh node and compare it with the ROS case.
Note: I respond to community members whom I think replied with good intentions. Similarly, if you think I am with bad intentions or trolling, please don’t respond to my comments. Don’t feed the troll.
Just to provide some practical pointers to anyone interested in using/consuming ROS2 libraries and tools in C++ without using ament. The same content is probably available somewhere, but I think it may be useful to report them in this discussion that I guess is getting a bit of attention.
As already pointed out by @mjcarroll the point of view of “consuming it” rclcpp
and other ROS2 libraries is a completely “regular” CMake package. Just to provide an example of doing that from a non-trivial CMake project, see bipedal-locomotion-framework/cmake/BipedalLocomotionFrameworkDependencies.cmake at v0.16.1 · ami-iit/bipedal-locomotion-framework · GitHub and bipedal-locomotion-framework/src/System/RosImplementation/CMakeLists.txt at v0.16.1 · ami-iit/bipedal-locomotion-framework · GitHub .
ros1_external_use
A good reference for consuming ROS 1 with regular tooling was GitHub - gerkey/ros1_external_use , it would be convenient to have something similar for ROS 2. I really would like to say “so I will work on it myself”, but to be honest to myself I do not think I would be able to do that in the short term.
I am not sure if this is documented explicitly anywhere, but it is relatively easy to have a “regular” CMake package that installs a ROS package. With “ROS package”, in this context I mean something that it is found if you do:
rospack find <pkgname>
in ROS 1 or:
ros2 pkg prefix <pkgname>
in ROS 2.
What you need to do is:
package.xml
in <install_prefix>/share/<pkgname>
<pkgname>
in <install_prefix>/share/ament_index/resource_index/packages
At CMake level, this boils down to:
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/package.xml
DESTINATION share/${PROJECT_NAME})
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_empty_file "")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_empty_file
DESTINATION share/ament_index/resource_index/packages
RENAME ${PROJECT_NAME})
At least for me, this always worked fine, but it is possible that I am not considering some workflow.
For an example of this pattern, icub-models
is a package that you can install independently of ROS, for example just from conda-forge (but it could be any distribution or package manager):
conda install -c conda-forge icub-models
And then, if you install ROS 1 or ROS 2, rospack find iCub
and ros2 pkg prefix iCub
will work out of the box. We actually test this in CI, see icub-models/.github/workflows/cxx-ci.yml at v2.4.1 · robotology/icub-models · GitHub .
As @tylerweaver pointed out, the tricky thing is integrating packages like this in ROS-specific steps like the build farm, but if you need to avoid depending on ament packages, probably you are not interested in that.
In the wild west of C++ code there is no standard for what a C++ library even is, tools just try to guess by looking at your filesystem.
Hopefully this will be solved by CPS (Introduction — Common Package Specification v0.9.0, https://www.youtube.com/watch?v=IwuBZpLUq8Q), Kitware and Bloomberg are backing its development, so hopefully it will be widely adopted at some point in the future.
Slightly off-topic, but:
Interesting to see a similar rationale in that introductory document about CPS for the “duplication” between CMakeLists.txt
and package.xml
(in CPS: the .cps
) which often confuses (new) ROS developers (from here):
CMake exported targets provide a richly featured mechanism for describing packages as a set of individual components, along with the necessary details for consuming each individual component. This generally works well… for CMake. The biggest problem with this system is not any internal flaw in the system, but the fact that it relies on the CMake language. Consumers have to parse not only CMake syntax, but in some cases need to cope with CMake generator expressions. Moreover, packages have access to the entire CMake language, which is Turing complete and capable of executing external processes. It would be exceptionally difficult for non-CMake tools to consume CMake package specifications without effectively reimplementing most or all of CMake itself. Clearly, this is not practical.
This was also what @dirk-thomas wrote in CMakeLists.txt vs package.xml.
Thanks for the actionable suggestions.
This one is something we actively do. You will see that many of the _vendor
packages are essentially shims to system versions if the system version meets the correct set of criteria. In the case of yaml-cpp
, this is always true on Ubuntu Jammy.
Many of these vendor packages exist because the situation on Windows is pretty dicey at best and there were multiple packages that weren’t conveniently available over there.
This is only a limitation in the buildfarm and comes from Debian packaging rules, so it influences ROS packaging rules. This would be a limitation if you choose to submit your software into upstream Ubuntu or Debian distributions, all dependencies have to be apt
-installable.
If you have no interest in the ROS buildfarm as a packaging/distribution mechanism, you are free to manage dependencies however you would like. You could use virtualenv, brew, conda, or even other packages that you have built/installed locally from source. It’s always been important to not interfere with those workflows.
The issue that @Phil_Brown is running into is also a new behavior from python as of version 3.11, so users on Debian bookworm and Ubuntu 23+ are going to start seeing it. In this case, Phil is our unfortunate canary, and we probably haven’t seen many reports of it since most of our users stick to the latest LTS. Python wants everyone using virtual environments rather than interfering with the system python install from 3.11 forward.
I am not sure. Let’s assume that I want to write a ROS Python package but it is only available on Github. You know I can install any Python package repository using pip install git+...
So sharing my package would be trivial in the standard way if it was not a ROS package.
But we know ROS packages are written to be shared with the community. This is the beauty of open source spirits. Now could you explain me how a happy ROS user will use my package?
The happy ROS user needs to do the exact steps I should because my package is not findable by rosdep
, which is the way they used to. But they are not determined as I do for software voodoo, perhaps they are just newcomers. They will give up or curse me for that.
This is how the build system cripples my ability to share my package with the community and forces me to use ROS tooling. Then I cannot use external pip dependencies according to your post.
I may be missing something, but can’t you just add the git+...
dependency you want to install to install_dependencies
in setup.py (see examples/rclpy/topics/minimal_publisher/setup.py at 355adf068fccd1b147acd89de62ad7d1bece9a78 · ros2/examples · GitHub), exactly as you would do for a non-ROS Python package?
I don’t know. Assume the happy ROS user develops a C++ ROS package and wants to declare a dependency to my ROS Python package.
Maybe I can put a rosdep key for my Python repo but what if my package depends on other ROS packages. Pip would not install them? No?
If you provide a package.xml along with your Python package, then rosdep will install everything that’s needed. Pip will not as it doesn’t know about the other ROS packages. But really, would you like pip to be automatically able to call apt to install packages? I think not…
Generally, when you’re crossing cross-ecosystem boundaries (apt, pypi, crates, …), you need a meta tool that knows them all. That’s rosdep. As long as you stick within a single ecosystem, things should be easier. Or - better said - you install base of ROS with apt, and then you can stick to your ecosystem dependency resolver/build tool.
That’s right. But rosdep
does not solve this case: The happy ROS user develops a C++ ROS package and declares a dependency on my Python package via a rosdep
key pointing to git+...
. Rosdep runs pip
. Pip does not know about my package.xml
. You somewhat assume my package is their workspace but this is the task for rosdep
if it is the tool you claim.
Effectively it only handles system dependencies without cross-language abilities.