Discussion - Running ros2_control on a real robot (Making a Mobile Robot Pt 13)

Blog Post

This is the discussion topic for the video and blog post linked above. Please keep all replies relevant to the content, otherwise create a new topic.

1 Like

Hi
i am getting thist error when trying to build diffdrive_arduino with colcon.

Starting >>> serial
Starting >>> serial_motor_demo_msgs
Finished <<< serial [1.69s]
Starting >>> diffdrive_arduino
Finished <<< serial_motor_demo_msgs [3.61s]
Starting >>> serial_motor_demo
--- stderr: diffdrive_arduino
CMake Error at CMakeLists.txt:16 (find_package):
  By not providing "Findhardware_interface.cmake" in CMAKE_MODULE_PATH this
  project has asked CMake to find a package configuration file provided by
  "hardware_interface", but CMake did not find one.

  Could not find a package configuration file provided by
  "hardware_interface" with any of the following names:

    hardware_interfaceConfig.cmake
    hardware_interface-config.cmake

  Add the installation prefix of "hardware_interface" to CMAKE_PREFIX_PATH or
  set "hardware_interface_DIR" to a directory containing one of the above
  files.  If "hardware_interface" provides a separate development package or
  SDK, be sure it has been installed.


---
Failed   <<< diffdrive_arduino [5.06s, exited with code 1]
Aborted  <<< serial_motor_demo [3.37s]

Summary: 2 packages finished [8.30s]
  1 package failed: diffdrive_arduino
  1 package aborted: serial_motor_demo
  1 package had stderr output: diffdrive_arduino

does anyone has an idea?
Thanks

Did you install ros2_control (e.g. with sudo apt install ros-foxy-ros2-control)?
That should provide the hardware_interface dependency.

Remember that if you already installed it on your dev machine but are now building on the Pi you need to install it there too! (I forgot when I was filming haha)

Edit: meant to say there’s also another bug preventing it from building which I’m going to fix right now…

looks like the controller manager services are not available?

So just to confirm, did you manage to build diffdrive_arduino after my last reply?

If the services are not available, that suggests the controller manager is not running - you can confirm this with ros2 node list. If it is not running, check that it’s in your launch file properly, that you are running the correct launch file, and that there are no errors in the output of the launch.

The diffdrive_arduino was succesfull build.
But i am getting errors when running “ros2 launch articubot_one launch_robot.launch.py”

[INFO] [ros2_control_node-2]: process started with pid [4577]
[INFO] [spawner.py-3]: process started with pid [4579]
[INFO] [spawner.py-4]: process started with pid [4581]
[ros2_control_node-2] [INFO] [1666217546.726356381] [DiffDriveArduino]: Configuring...
[ros2_control_node-2] terminate called after throwing an instance of 'serial::IOException'
[ros2_control_node-2]   what():  IO Exception (13): Permission denied, file /home/rosbot/robot_ws/src/serial/src/impl/unix.cc, line 151.
[spawner.py-4] [INFO] [1666217547.812861551] [spawner_diff_cont]: Waiting for /controller_manager services
[spawner.py-3] [INFO] [1666217547.840100623] [spawner_joint_broad]: Waiting for /controller_manager services
[ERROR] [ros2_control_node-2]: process has died [pid 4577, exit code -6, cmd '/opt/ros/foxy/lib/controller_manager/ros2_control_node --ros-args --params-file /tmp/launch_params_57dm5z2x --params-file /home/rosbot/robot_ws/install/articubot_one/share/articubot_one/config/my_controllers.yaml'].
[spawner.py-4] [INFO] [1666217549.844418248] [spawner_diff_cont]: Waiting for /controller_manager services
[spawner.py-3] [INFO] [1666217549.872518979] [spawner_joint_broad]: Waiting for /controller_manager services
[spawner.py-4] [INFO] [1666217551.875385029] [spawner_diff_cont]: Waiting for /controller_manager services
[spawner.py-3] [INFO] [1666217551.904104070] [spawner_joint_broad]: Waiting for /controller_manager services
[spawner.py-4] [INFO] [1666217553.907724653] [spawner_diff_cont]: Waiting for /controller_manager services
[spawner.py-3] [INFO] [1666217553.938034195] [spawner_joint_broad]: Waiting for /controller_manager services
[spawner.py-4] [INFO] [1666217555.937776050] [spawner_diff_cont]: Waiting for /controller_manager services
[spawner.py-3] [INFO] [1666217555.968601738] [spawner_joint_broad]: Waiting for /controller_manager services
[spawner.py-4] [ERROR] [1666217557.765990630] [spawner_diff_cont]: Controller manager not available
[spawner.py-3] [ERROR] [1666217557.798581779] [spawner_joint_broad]: Controller manager not available
[ERROR] [spawner.py-4]: process has died [pid 4581, exit code 1, cmd '/opt/ros/foxy/lib/controller_manager/spawner.py diff_cont --ros-args'].
[ERROR] [spawner.py-3]: process has died [pid 4579, exit code 1, cmd '/opt/ros/foxy/lib/controller_manager/spawner.py joint_broad --ros-args'].

Why is the controller manager not running.
I use your file from github.

Ok so if my guess is correct, this is something I knew I should probably improve in the code which is exception handling to give a more helpful error message.

I think the problem is that it goes to start up the hardware interface but it can’t see the device on the specified serial port and so it fails. A few things to check here:

  • Firstly, that you are using the same setup as me (with the Arduino running that same code)
  • Have you set the device correctly in ros2_control.xacro (e.g. /dev/ttyUSB0 or /dev/serial/by-id...)
  • Is the specified device visible in the OS (e.g. if the parameter is set to /dev/ttyUSB0, does ls /dev/ttyUSB0 return something)
  • Have you added the user to the dialout group with sudo adduser $USER dialout ?
  • Can you connect to the arduino with a serial terminal e.g. miniterm -e <device path> 57600
  • Has the system got the lidar or other device and the Arduino the wrong way around*
  • Did you get the baud rate wrong? (That should be a different kind of problem though)

* I vaguely flagged this in the video, but I should not have used /dev/ttyUSB0 as that will sometimes be the lidar, instead I should set it by the path or ID (which I will do at some point).

Let me know how you go with that or if you need further assistance :slight_smile:

Very good hints !
The problem was the ‘dialout’ group.
After adding the user to the ‘dialou’ group everything works out fine.
Thank you , that was a excellent support.
Looking forward to the next video .

2 Likes

Great - I’m glad we got it sorted!

Hello, and thanks for great tutorials. I have noticed that my robot only drives about half the linear and angular velocity as the /cmd_vel command. The counts per revolutions is way lower at 392 tics and maybe that could have something to do with the problem? Also its mentioned that the pid uses the unit tics/loop rate. Should I set that number somewhere?

Hmm that is strange, but we should be able to figure it out by checking each step along the way. I’m assuming through this that you are using the same Arduino code as me and the diffdrive_arduino hardware interface.

  • Connect to the Arduino using a serial terminal (e.g. miniterm) and confirm your cpr is 392 using the “e” commands
  • Calculate the counts per loop to go at 1 rev/sec. In this case that will be 392/30=13.
  • Use the “m” command to set the motors at that speed and confirm it is correct (e.g. with a stopwatch).
  • Manually calculate and test the speed that you ultimately want your motors to be going. This might be where you are running into precision issues.
    • e.g. If your cmd_vel is 0.5m/s and your wheel radius was 0.06m
    • 0.5/(2 * pi * 0.06) = 1.32 rev/sec
    • = 17 counts/loop
    • If your wheels are big and you are trying to drive slow this is where you’ll fall apart
      • e.g. if you were aiming for 0.1m/s and had 0.08m radius wheels, you’re looking at 2.6 counts/loop
      • This is so low that being off by one will make a huge difference and so the PID controller will have a very hard time tracking it
      • In that case you may want to try driving faster, gearing the motors, lengthining the loop time, or tuning the PID
  • Assuming it did track that fine the problem must be further up the chain (which is great, means it’s just a software/config issue!)
  • Confirm that ros2_control.xacro has correct parameters, particularly the loop rate and counts per rev
  • Confirm that my_controllers.yaml has the correct wheel radius
  • At this point it should be working, but if not then you can dig into the diffdrive_arduino code (particularly arduino_comms.cpp and diffdrive_arduino.cpp and print out what that is sending to the Arduino - it should be the same numbers you calculated earlier!
  • Maybe also echo the cmd_vel topic to verify those numbers are correct.

I hope that helps, please let me know how you go!

Thank you for your great and fast answer! And it’s amazing to get a great tutorial on the whole motor control chain. For me it was a very hard issue to solve by myself.

I will try all your suggestions. I forgot to mention that the wheel radius is indeed quite large compared with your example (0.09[m]). The wheel separation is 0.43[m]. Also the test of driving a distance and spinning in rviz2 is correct compared to the real robot. (One meter in rviz is one meter on the robot and 360 deg is 360 deg on the robot). I am currently using the full navigation stack so the problem could be higher up but the issue of wrong speed remains when driving with a controller so the issue should not be there (checked agains /cmd_vel message).

Don’t know where to post this but I found an issue using the Velodyne 16 lidar to laser scan (2D lidar) in Slam toolbox node. It is a quite common lidar so maybe some other have the same issue. It took a long time for me to find the bug but apparently when converting the pointcloud message to laserscan message with the official driver the lidar can give the error of too many or too few scans per revolution. I think if the resolution in the .yaml file is not evenly divided it cases the error and then the slam toolbox is not able to start correctly. I did a bad fix of changing the resolution: 0.006 and it works.

Hope it can be to any help and thanks again. Will update when i have found the issue :slight_smile:

Hello! I wanted to thank you for these amazing tutorials and ask for some guidance on a problem I just ran into. While trying to build diffdrive_arduino, I received the following error:

doug@doug-desktop:~/ros2_ws$ colcon build --symlink-install
Starting >>> serial
Starting >>> arduino_com
Starting >>> my_bot
Starting >>> my_robot_controller
Finished <<< my_bot [3.89s]
Starting >>> robot_controller
Finished <<< serial [4.15s]
Starting >>> diffdrive_arduino
--- stderr: diffdrive_arduino
In file included from /home/doug/ros2_ws/src/diffdrive_arduino/src/diffdrive_arduino.cpp:1:
/home/doug/ros2_ws/src/diffdrive_arduino/include/diffdrive_arduino/diffdrive_arduino.h:7:10: fatal error: hardware_interface/base_interface.hpp: No such file or directory
    7 | #include "hardware_interface/base_interface.hpp"
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
gmake[2]: *** [CMakeFiles/diffdrive_arduino.dir/build.make:76: CMakeFiles/diffdrive_arduino.dir/src/diffdrive_arduino.cpp.o] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:139: CMakeFiles/diffdrive_arduino.dir/all] Error 2
gmake[1]: *** Waiting for unfinished jobs....
In file included from /home/doug/ros2_ws/src/diffdrive_arduino/src/fake_robot.cpp:1:
/home/doug/ros2_ws/src/diffdrive_arduino/include/diffdrive_arduino/fake_robot.h:7:10: fatal error: hardware_interface/base_interface.hpp: No such file or directory
    7 | #include "hardware_interface/base_interface.hpp"
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
gmake[2]: *** [CMakeFiles/fake_robot.dir/build.make:76: CMakeFiles/fake_robot.dir/src/fake_robot.cpp.o] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:165: CMakeFiles/fake_robot.dir/all] Error 2
gmake: *** [Makefile:146: all] Error 2
---
Failed   <<< diffdrive_arduino [5.76s, exited with code 2]
Aborted  <<< my_robot_controller [10.0s]
Aborted  <<< arduino_com [10.6s]
Aborted  <<< robot_controller [8.27s]

Summary: 2 packages finished [13.3s]
  1 package failed: diffdrive_arduino
  3 packages aborted: arduino_com my_robot_controller robot_controller
  1 package had stderr output: diffdrive_arduino

I think I figured out the problem… I am running ROS Humble and the Ros2_control package for humble doesn’t have hardware_interface/base_interface.hpp anymore. https://github.com/ros-controls/ros2_control/tree/humble/hardware_interface/include/hardware_interface

I wanted to check and see if there may be a workaround by editing the diffdrive_arduino.h file to not use base_interface? Any guidance would be greatly appreciated, thanks!

I am using Humble and my HW Plugin is based on the ros2_control_demos I found that I had to swap “position” and “velocity” name for the state_interfac, in the command_interface, in the ros2_control.xacro file. As the plugin was expecting Position first.
This now works for me.

    <ros2_control name="RealRobot" type="system">
        <hardware>
            <plugin>hover_diffdrive/HoverDiffDrive</plugin>
        </hardware>
        <joint name="left_wheel_joint">
            <command_interface name="velocity">
                <param name="min">-10</param>
                <param name="max">10</param>
            </command_interface>
            <state_interface name="position"/>            
            <state_interface name="velocity"/>
        </joint>
        <joint name="right_wheel_joint">
            <command_interface name="velocity">
                <param name="min">-10</param>
                <param name="max">10</param>
            </command_interface>
            <state_interface name="position"/>
            <state_interface name="velocity"/>
        </joint>
    </ros2_control>

Hey! This is an issue I’m well aware of (just this week someone flagged it on GitHub too), but have not put any energy into resolving yet.

As I understand it the fix is a bit more involved than just the dependence on that file, and that it was a more substantial change to the API.

My current plan is that at the end of the build series (which is drawing near!) I will do a video specifically on how to write a hardware interface for humble, and as a demo I will take my foxy one and upgrade it.

In the meantime I’m not sure if anyone else has forked /updated it (I think someone might have but
I can’t remember). If I do find out I’ll post here. As @BigShark3000 helpfully noted, you could have a go at porting it yourself using the ros2_control_demos - if you do then let us know! That’s also a helpful note about the requirement to swap the interface order.

Thanks for the responses BigShark3000 and Josh. I figured it wasn’t going to be a simple fix but thought I would ask to be sure! I’ve been looking through the ros2_control_demos and diffdrive_arduino code to try and understand how it all works… definitely have a ways to go there. If I do manage to get something working, I’ll be sure to share.

1 Like

This fork seems to work. It compiles I have not actually tested it as such but hopeful:

I am getting this error.

ubuntu@ubuntu:~/robot_ws$ colcon build --symlink-install
Starting >>> serial_motor_demo_msgs
— stderr: serial_motor_demo_msgs
CMake Error at CMakeLists.txt:19 (find_package):
By not providing “Findament_cmake.cmake” in CMAKE_MODULE_PATH this project
has asked CMake to find a package configuration file provided by
“ament_cmake”, but CMake did not find one.

Could not find a package configuration file provided by “ament_cmake” with
any of the following names:

ament_cmakeConfig.cmake
ament_cmake-config.cmake

Add the installation prefix of “ament_cmake” to CMAKE_PREFIX_PATH or set
“ament_cmake_DIR” to a directory containing one of the above files. If
“ament_cmake” provides a separate development package or SDK, be sure it
has been installed.


Failed <<< serial_motor_demo_msgs [0.38s, exited with code 1]

Summary: 0 packages finished [0.87s]
1 package failed: serial_motor_demo_msgs
1 package had stderr output: serial_motor_demo_msgs
1 package not processed
ubuntu@ubuntu:~/robot_ws$

Did you source your ROS installation first? (i.e. source /opt/ros/foxy/setup.bash)?

Yes now it work the problem was same that you have mentioned. Thank you