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

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:


  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?

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 .

1 Like

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: