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

Hi Josh, Thanks for a great series. I got pretty much stuck on getting it all to work on a real robot. I’m running Humble on Ubuntu 22.04. Since ROS-Serial has been replaced by MicroRos I went that route.

Here’s my setup:
Ubuntu 22.04 on a virtual machine (some issues along the way as you mentioned but all sorted)
Completed diff drive robot with RPi4 (Ubuntu 22.04), Arduino Due (MicroRos), L298N motor driver.

I can control the robot with Twist messages and I can publish odometry from the Arduino. The problem is getting it to work with ros2_control and specifically implementing a hardware interface.

The way I understand it is that diffdrive_arduino won’t work in this scenario because it relies on ROS-Serial. I did try to use ros2_control_demos to solve the problem but did not succeed.

So my question is:
Can diffdrive_arduino work in this setup?
If so, how do I get that to work?
If diffdrive_arduino can’t work, what are my options?

The MicroRos and ros2_control combo seems pretty new and I can find very little about it. I’ve been working on this for a few weeks now but I’m not getting any further.

Yeah so the confusion here (and it’s not just you, others have had the same issue) is that diffdrive_arduino does NOT use rosserial (or micro-ROS for that matter).

rosserial is a method for sending ROS messages over a serial line (to an Arduino or similar). And now with micro-ROS those kinds of problems can be solved differently.

Whereas diffdrive_arduino isn’t sending ROS messages at all, it is making a pure serial connection to software on the other end, speaking a (very simple) custom protocol. So you shouldn’t have rosserial or micro-ROS running on the Arduino, it doesn’t know anything about ROS, just some simple motor control serial commands. diffdrive_arduino is doing all the translation from ROS to serial.

If you really want to use micro-ROS on the Arduino, it probably makes sense to skip ros2_control completely. And that is a perfectly acceptable setup - just not what I’ve done in my tutorials. In that case you’ll probably want to have the Arduino receiving a Twist and handling all the diff-drive calculations (which it seems you are doing), rather than implenting it on the ROS side.

I hope that clears things up, if not please ask further questions!

1 Like

Thanks for the super quick reply Josh, that clears it all up. I’m going to stick with your route so that I can follow your track in coming videos. I’m going back to the motor control video to implement RosArduinoBridge and then implement diffdrive_arduino. Plenty of time to play around with MicroRos etc later.

1 Like

Hi, I’m having a problem getting my pi to locate the ros2 control package using ‘sudo apt install’. It just cannot find it. I’ve updated and upgraded, following the instructions here: Ubuntu (binary) — ROS 2 Documentation: Humble documentation

Any idea what’s going wrong? I’m surprised I can’t get the system to locate it. Is there a workaround? Thanks for any help!

@JoshNewans sir . I was able to run the robot in real time but unable to run in the rviz i.e the robot was not moving in the rviz
I have tried to change frames but no result , is there any solution I was using ros2 humble and 22.04

Hey Jon, this should be fixed with the latest humble update, so if you try an apt update and then go again hopefully it will be there. Let me know if you have further troubles.

Hi,

Thanks for the great tutorial. I followed everything correctly till Ros2 Controller. My setup is a 4 wheel robot instead of 2 wheels. I have used differential drive and setup wheel count as 2. Everything worked perfectly until I added diffdrive_arduino package. I have modified the package to take in four wheels as input. However the issues are:

  1. When I try driving, all the wheels are reversed. I modified the diffdrive package to take inverted inputs (- for all vel1, vel2, vel3 and vel4). This seems to fix and motors driving correctly
  2. Teleop twist keyboard can be used to control the robot only if linear and angular velocity is set to 0.4xxx. Anything more than 5 or less than 3 does not move the wheels at all.
  3. Not all motors rotate at the same speed.

So, my questions are:

  1. Can I use the previous serial_motor_demo library to complete SLAM setup?
  2. Any ideas why the robot is not responding to twist correctly?

Hi Praveen!

There are a bunch of places that wheel reversing can occur, depending on your hardware. Getting the wrong pins on the driver in, the driver out, the controller, the wrong axis direction in URDF, etc. It sounds like what you’ve done there is probably not the “correct” solution, but if it works, it works :slight_smile:

That’s very odd. To start with diagnosing I’ll need more detail on your motors/controllers/drivers etc. (which might also help us with problem 1). Depending on how things are being mapped it’s not unusual for there to be a lower limit that it won’t turn below, but an upper limit is strange.

This is unfortunate, but not too surprising. Again, we’ll need more details on how you have things hooked up but this is where the PID controller comes into play (which if you’re following the tutorials will be external to ROS/Pi stuff, in an Arduino or some other dedicated controller). The quality control of the motors will be a factor, but the PID controller should be able to be tuned to get the motors performing fairly similarly. If you don’t have a PID controller and are running in open loop, that might also be the cause of problem 2.

Sort of. You could modify it to accept a Twist and have differential drive control, but you’d be better off fixing the other issues instead and things should just work.

Yeah, by the sound of things it’s worth stepping through the details of your setup and making sure the low-level motor control is working before touching the ROS-level stuff. If it’s broken then no amount of ROS tweaking will fix things!

So please post some more details about your hardware and how it’s wired up (you can upload pictures to imgur and embed them here) and we’ll see what we can figure out :slight_smile:

[INFO] [launch]: All log files can be found below /home/system/.ros/log/2023-03-21-14-56-32-932971-mapperbot-5148
[INFO] [launch]: Default logging verbosity is set to INFO
[ERROR] [launch]: Caught exception in launch (see debug for traceback): Caught exception when trying to load file of format [py]: name ‘Command’ is not defined

Is there an import I’m missing?

1 Like

There most certainly was :slight_smile:
from launch.substitutions import Command

1 Like

Hi Josh,

Is it possible to set a parameter for defining the Serial Port of arduino in the launch file. I can scan the ports automatically and say on which port is my Lidar and on which is the Arduino Motor Control but I do not know how to set it dynamically in the diffdrive_arduino.

Thank you very much!

Cheers,
Ivo

Hi,

I have lidar and arduino motor control on srial ports of my robot (on usbs of my raspberry pi). Sometimes lidar and arduino changes serial ports (lidar is on 1 instead of 0 and arduino on 0 instead of 1)and i have to change the configuration of both of them and recompile and start again. Is there an way to make it automatically on the start.

Thank you very much!

Best regards,
Ivo

Hi Josh, do you know if it is possible to implement a real controller of a robot (reality) and in parallel a Gazebo simulation so that ros2_control controls both the hardware and the behavior in Gazebo like a digital twin? In your article i understood that its either the real robot or gazebo simulation.

Hello
All the hardware and software I use are the same as the one you use. The router is the same. When I connect the router to the development machine with ethernet as you do, and when I connect it to the raspberry pi 4, when I want to control the robot as in the 13th video, it gives a biiiip sound and cuts the internet for a short time. It gives buffer.cpp error, where could I have made a mistake?

Hi Ivo, sorry for not getting back to you (and many other people).

The simplest way to achieve what you want is instead of referencing the devices as /dev/ttyUSB0 or whatever, instead use /dev/serial/by-id/xxx or /dev/serial/by-path/xxx. These paths are tied to either the identifier of the hardware, or the actual USB port it is plugged into, so as long as you keep them in the same ports, the OS should identify them by the same path each time!

If you really want to have it in the launch file you can use an xacro argument and pass it in, similar to how we handle the sim mode and ros2_control mode in rsp.launch.py.

Again, sorry it’s late but I hope that helps!

That’s a great question and I’ve never really thought about it!
In short, I think the answer is no…but sort of yes?
The ros2_control controller expects to only control one hardware interface, so to achieve what you’re talking about you’d just have to run two independent controllers and have them both listening to the same twist topic (but avoid them publishing to the same feedback).

You could achieve a similar result if you bypassed ros2_control completely and wrote a custom node that interacted with Gazebo and also your robot but it gets…messy (and I suspect probably won’t achieve the desired result, especially with something like a mobile robot. It might be good for an arm)

Wow that is a strange issue, I’m not sure, sorry.
Also I haven’t mentioned this but I actually swapped to a different router as I thought the first one was maybe causing me problems…but then I still had problems with the new one too so I never said anything.

When you say it beeps, do you mean the router beeps or the Pi beeps? Perhaps it is a power issue? How are you powering the router?

Hi Josh, thanks a lot for your tutorials,

I am using Arduino UNO instead of Nano, there is no issues when I do launch launch_robot file and it tells me that all controllers configured correctly but when I try to drive it with teleop, none of the motors move!!.. my driver EN pins on the UNO are 6,3,9,5.

Please help me, my graduation project is depending on that

Hi Josh, thanks for this great tutorial. However I’m facing issue when unbreaking gazebo. I follow your tutorial exactly, but when i launch my launch_sim.launch.py, i get this error instead

afiq@afiq-VM:~/dev_ws$ ros2 launch my_bot launch_sim.launch.py world:=src/my_bot/worlds/obstacles.world
[INFO] [launch]: All log files can be found below /home/afiq/.ros/log/2023-06-02-08-25-17-400678-afiq-VM-24746
[INFO] [launch]: Default logging verbosity is set to INFO
Task exception was never retrieved
future: <Task finished name='Task-2' coro=<LaunchService._process_one_event() done, defined at /opt/ros/foxy/lib/python3.8/site-packages/launch/launch_service.py:226> exception=SubstitutionFailure('executed command failed. Command: xacro /home/afiq/dev_ws/install/my_bot/share/my_bot/description/robot.urdf.xacro use_ros2_control:=true sim_mode:=true')>
Traceback (most recent call last):
  File "/opt/ros/foxy/lib/python3.8/site-packages/launch/launch_service.py", line 228, in _process_one_event
    await self.__process_event(next_event)
  File "/opt/ros/foxy/lib/python3.8/site-packages/launch/launch_service.py", line 248, in __process_event
    visit_all_entities_and_collect_futures(entity, self.__context))
  File "/opt/ros/foxy/lib/python3.8/site-packages/launch/utilities/visit_all_entities_and_collect_futures_impl.py", line 45, in visit_all_entities_and_collect_futures
    futures_to_return += visit_all_entities_and_collect_futures(sub_entity, context)
  File "/opt/ros/foxy/lib/python3.8/site-packages/launch/utilities/visit_all_entities_and_collect_futures_impl.py", line 45, in visit_all_entities_and_collect_futures
    futures_to_return += visit_all_entities_and_collect_futures(sub_entity, context)
  File "/opt/ros/foxy/lib/python3.8/site-packages/launch/utilities/visit_all_entities_and_collect_futures_impl.py", line 45, in visit_all_entities_and_collect_futures
    futures_to_return += visit_all_entities_and_collect_futures(sub_entity, context)
  [Previous line repeated 3 more times]
  File "/opt/ros/foxy/lib/python3.8/site-packages/launch/utilities/visit_all_entities_and_collect_futures_impl.py", line 38, in visit_all_entities_and_collect_futures
    sub_entities = entity.visit(context)
  File "/opt/ros/foxy/lib/python3.8/site-packages/launch/action.py", line 108, in visit
    return self.execute(context)
  File "/opt/ros/foxy/lib/python3.8/site-packages/launch_ros/actions/node.py", line 444, in execute
    self._perform_substitutions(context)
  File "/opt/ros/foxy/lib/python3.8/site-packages/launch_ros/actions/node.py", line 399, in _perform_substitutions
    evaluated_parameters = evaluate_parameters(context, self.__parameters)
  File "/opt/ros/foxy/lib/python3.8/site-packages/launch_ros/utilities/evaluate_parameters.py", line 164, in evaluate_parameters
    output_params.append(evaluate_parameter_dict(context, param))
  File "/opt/ros/foxy/lib/python3.8/site-packages/launch_ros/utilities/evaluate_parameters.py", line 71, in evaluate_parameter_dict
    evaluated_value = perform_substitutions(context, list(value))
  File "/opt/ros/foxy/lib/python3.8/site-packages/launch/utilities/perform_substitutions_impl.py", line 26, in perform_substitutions
    return ''.join([context.perform_substitution(sub) for sub in subs])
  File "/opt/ros/foxy/lib/python3.8/site-packages/launch/utilities/perform_substitutions_impl.py", line 26, in <listcomp>
    return ''.join([context.perform_substitution(sub) for sub in subs])
  File "/opt/ros/foxy/lib/python3.8/site-packages/launch/launch_context.py", line 232, in perform_substitution
    return substitution.perform(self)
  File "/opt/ros/foxy/lib/python3.8/site-packages/launch/substitutions/command.py", line 116, in perform
    raise SubstitutionFailure(f'executed command failed. Command: {command_str}')
launch.substitutions.substitution_failure.SubstitutionFailure: executed command failed. Command: xacro /home/afiq/dev_ws/install/my_bot/share/my_bot/description/robot.urdf.xacro use_ros2_control:=true sim_mode:=true

How do i solve this?

Solved this. Figure out don’t need to install gazebo ros2 control package