This is a bit obscure. I am trying to run moveit2 on a raspberry pi zero 2 w but the systems resources are so low that I can not really compile on that machine.

So I got a pi 5 for building the whole project, then I rsync the "install" directory to the pi zero. When I do this the launch can't load the plugin and reports the following:

[ros2_control_node-4] [INFO] [1713065838.802180696] [controller_manager]: Subscribing to '/robot_description' topic for robot description.             
[ros2_control_node-4] [INFO] [1713065838.803190173] [controller_manager]: update rate is 100 Hz                                                                     
[ros2_control_node-4] [INFO] [1713065838.840194510] [controller_manager]: Received robot description from topic.                           
[ros2_control_node-4] [INFO] [1713065838.848604593] [resource_manager]: Loading hardware 'FakeSystem'                                                               
[ros2_control_node-4] [ERROR] [1713065838.849262821] [controller_manager]: The published robot description file (urdf) seems not to be genuine. The following error 
was caught:According to the loaded plugin descriptions the class k1_control/RobotSystem with base class type hardware_interface::SystemInterface does not exist. Dec
lared types are  mock_components/GenericSystem test_hardware_components/TestSystemCommandModes test_hardware_components/TestTwoJointSystem     

However is I compile the same code on the pi zero and launch it it works.

Both the pi zero and the pi 5 are running ubuntu 22.04 64 bit. I don't think it matters but the pi 5 only currently supports ubuntu 23.04 so I use Multipass to host a 22.04 container where the compiling takes place.

Also I can launch on the pi 5 and it works as well.

The paths for the source tree are different on the two systems because the container image just uses a generic user called "ubuntu" so the home directory is /home/ubuntu where the pi zero has a different user account name.

I essentially moved the destination of the install on the pi zero so it would have a matching path, sourced the setup.bash and tried to launch but still got the same failure.

Anyone have any thoughts?

Solution Posted Below

  • $\begingroup$ The list of declared types that it's trying to discover seems very short, and potentially only finding local resources. I would suggest looking at the discovery mechanism and make sure that it's not baking in the path on the build host with an absolute path. That would be a ticketable bug but seems to match the behavior. Can you configure a symlink to spoof the build path to test it out? $\endgroup$
    – Tully
    Commented Apr 14 at 7:34
  • $\begingroup$ The other thing that I would look for is content going to somewhere outside of the rsync path such as a user directory config file. Or into etc, it shouldn't, but maybe something is missing configured. $\endgroup$
    – Tully
    Commented Apr 14 at 7:36
  • $\begingroup$ I did create a symlink to spoof the original user home dir link to the installed homedir. $\endgroup$
    – Boilerbots
    Commented Apr 14 at 17:40
  • $\begingroup$ Also "ldd" on the plugin lib doesn't show anything strange or missing. $\endgroup$
    – Boilerbots
    Commented Apr 14 at 17:40

2 Answers 2


Well the problem and the solution are rather simple.

It seems that the main problem is that by device IO in my plugins is getting blocked or even failing to open on the Pi. This blocking behavior happens pretty much after the first start up and shutdown of my stack.

I must have always test first by running the code built on the zero first and it would work. Then I would try to run the code from the 5 and it would fail.

Eventually I just focused on the zero code to continue to make progress and eventually experienced the blocking failure and at that point had traced it to the file operations on the serial ports blocking.

The buffering and timing of the serial ports on the Pi compared to an Intel machine blew up my code in some strange ways. Especially considering the load on the zero's CPU when launching a big stack such as moveIt really choked the flow until it was up and running.

The current solution is to open and configure the ports using O_NONBLOCK and then switch to blocking using fcntl() calls. You can see here: https://github.com/boilerbots/flexo/blob/44cb4776f4508e9fe169f1c2488a55f4eef5229a/ros2/src/k1_control/src/k1_robot.cpp#L97

  • $\begingroup$ Glad you got it figured out, and that there wasn't a packaging issue. Finding these corner cases on the smaller systems are painful sometimes. $\endgroup$
    – Tully
    Commented Apr 15 at 5:05

I don't think copying of the install directory is ever a good idea. If you want to deploy compiled code you rather want to deploy binaries and then install directly on the target machine. However, the build system of ros2 does not directly allow that.

I liked one suggestion, which is creating a deb package and installing it through that.

But, overall I think it would be best to just pre install everything (like a normal ros2 build) inside the container that you are already using and deploy that.

  • $\begingroup$ This is what I have been doing on production robots for the past 8 years and never had a problem. I believe the point of having a nice packaged up "install" directory is just that, to install it. Both systems are installing the same packages and are kept sync'd up. I can't do much on a pi zero because the resources are very low, with 500M of RAM after boot there is only around 300M usable. I am already running zram and a swap file but the SD card interface is very slow so swap files really are slow. $\endgroup$
    – Boilerbots
    Commented Apr 14 at 17:44
  • $\begingroup$ Install directories are designed to be relocatable. Debian packages are just a standard delivery mechanism for said installation directories. You do need to be careful about the build being targeted for the destination system appropriately. This is again something that the debs do for you. $\endgroup$
    – Tully
    Commented Apr 15 at 5:02
  • $\begingroup$ I am sorry, I may have misunderstood the core problem. I also did not know the install directory is fully movable. I always thought that would be a bad idea considering exports within the target filesystem or environment hooks that are configured with fully rendered paths. That is why I suspected the act of installation may have been the missing piece. But thanks @Tully for clearing that up and glad Boilerbots figured it out :) $\endgroup$
    – Nyquist
    Commented Apr 15 at 5:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.