I’m glad you got it sorted but I’m a bit confused by your solution.
It seems like xacro itself was failing - possibly you had an error in your URDF?
I’m glad you got it sorted but I’m a bit confused by your solution.
It seems like xacro itself was failing - possibly you had an error in your URDF?
Hello I’m a beginner in robotics, im mainly a software guy. With that said, i have a question.
Welcome!
Yep
The disadvantages are:
When you say
What do you mean? Essentially all a ros2_control harware interface is is a C++ plugin that does that, but takes the input from ros2_control rather than your own calculation.
But yeah, doing it the long way is always an option (and not a bad one for learning how differential drive control works) but at some point it makes sense to take the more robust, flexible option of ros2_control.
(P.S. I’ve responded to your other message)
What i mean with i can send only motor commands. Is that by using pyserial and ESP32 in my laptop, i’ll just write a certain string that indicated the speed value of both motors for example, the string is “0.5,1.0&\n” (0.5 = left motor speed, 1.0 = right motor speed) then i use arduino.write() to send those command sending it to another ESP32 that has arduino attached to it.
I did this because the hardware guy just told me to send those string via esp32, and he just do the rest of the hardware control thing.
We don’t use rasberry pi btw, just like you did.
So it’s basically i’m sending a string command with my laptop connected to esp32 then another esp32 connected to arduino just received the command, and i don’t know how the hardware guy works around with that string i have sent. I can ask him if necessary to provide more information.
Is our approach in doing this project correct? Is there anyway i can expose state interfaces with robot with our current approach? Thanks
I have a sort of weird problem. I’ve resumed this project after a couple of months and actually started it over as I’d forgotten a bit. The serial motor demo and gui works great on my setup, the motors behave as expected. However, after completing the ros2 control files and code, using teleop causes the motors to go crazy. They will start slowly in the same direction, then they will quickly climb to FULL speed of my motors, one flipping direction in the process and the robot would spin in place at full speed (I have it on blocks so this won’t happen). Nothing I’ve messed with seems to have made any difference. It almost reminds me of an uncontrolled PID controller, like the motors are trying to match a value or catch up with something and max out. Does anyone have any ideas?
Honestly, that sounds very similar to how mine works, just with a few extra steps - which means it shouldn’t be too hard to modify!
I recommend watching my motor tutorial first, so that you understand how mine is structured (and how it is similar and different to yours).
Then watch the hardware interface tutorial which shows how to connect that to ros2_control. You should be able to pretty much take my hardware interface and make some small modifications to the class that handles the comms.
Bizarre! Yeah it does sound like a PID controller behaving badly.
One possible issue if you are using my exact code is that the PID settings might have changed since the earlier version? The latest hardware interface is here and it gives you the ability to tweak the PID parameters.
That version SHOULD leave them as default if you don’t set them, but I think there were other versions with a hardcoded value so you may have that?
My other suggestion would be to add print statements into the hardware interface to confirm exactly what is being sent to the motors. That’s a little tedious but should get to the bottom of it.
It looks like that branch is for Humble. I’m using Foxy, can it be used with it or do I need to upgrade?
Hey @JoshNewans thank you for the great tutorial, it has been of great benefit to us as students. We are having difficulty loading the /controller_manager services, we’ve tried the solutions you suggested earlier in the thread to @Sasffm, but it is still not working. We have the same setup, and the device port has been set correctly, even the user has been added to the dialout group. The following is the error obtained on running the launch file.
[INFO] [launch]: All log files can be found below /home/vahin/.ros/log/2023-06-07-09-52-16-628234-ubuntu-13541
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [robot_state_publisher-1]: process started with pid [13544]
[robot_state_publisher-1] Parsing robot urdf xml string.
[robot_state_publisher-1] Link chassis had 2 children
[robot_state_publisher-1] Link caster_wheel had 0 children
[robot_state_publisher-1] Link laser_frame had 0 children
[robot_state_publisher-1] Link left_wheel had 0 children
[robot_state_publisher-1] Link right_wheel had 0 children
[robot_state_publisher-1] [INFO] [1686131537.466259297] [robot_state_publisher]: got segment base_link
[robot_state_publisher-1] [INFO] [1686131537.466644027] [robot_state_publisher]: got segment caster_wheel
[robot_state_publisher-1] [INFO] [1686131537.466723784] [robot_state_publisher]: got segment chassis
[robot_state_publisher-1] [INFO] [1686131537.466753468] [robot_state_publisher]: got segment laser_frame
[robot_state_publisher-1] [INFO] [1686131537.466781004] [robot_state_publisher]: got segment left_wheel
[robot_state_publisher-1] [INFO] [1686131537.466809170] [robot_state_publisher]: got segment right_wheel
[INFO] [ros2_control_node-2]: process started with pid [13606]
[INFO] [spawner.py-3]: process started with pid [13608]
[INFO] [spawner.py-4]: process started with pid [13610]
[ros2_control_node-2] [INFO] [1686131543.680967466] [DiffDriveArduino]: Configuring...
[ros2_control_node-2] [INFO] [1686131543.687668416] [DiffDriveArduino]: Finished Configuration
[ros2_control_node-2] [INFO] [1686131543.688505651] [DiffDriveArduino]: Starting Controller...
[ros2_control_node-2] [INFO] [1686131545.719892550] [controller_manager]: update rate is 30 Hz
[ros2_control_node-2] [INFO] [1686131545.762545973] [controller_manager]: Loading controller 'diff_cont'
[ros2_control_node-2] [ERROR] [1686131545.762714005] [controller_manager]: Loader for controller 'diff_cont' not found.
[ros2_control_node-2] [INFO] [1686131545.762758207] [controller_manager]: Available classes:
[ros2_control_node-2] [INFO] [1686131545.762797873] [controller_manager]: controller_manager/test_controller
[ros2_control_node-2] [INFO] [1686131545.762828928] [controller_manager]: controller_manager/test_controller_failed_init
[ros2_control_node-2] [INFO] [1686131545.762866667] [controller_manager]: controller_manager/test_controller_with_interfaces
[ros2_control_node-2] [INFO] [1686131545.835433835] [controller_manager]: Loading controller 'joint_broad'
[ros2_control_node-2] [ERROR] [1686131545.835685402] [controller_manager]: Loader for controller 'joint_broad' not found.
[ros2_control_node-2] [INFO] [1686131545.835744493] [controller_manager]: Available classes:
[ros2_control_node-2] [INFO] [1686131545.835786603] [controller_manager]: controller_manager/test_controller
[ros2_control_node-2] [INFO] [1686131545.835817731] [controller_manager]: controller_manager/test_controller_failed_init
[ros2_control_node-2] [INFO] [1686131545.835846286] [controller_manager]: controller_manager/test_controller_with_interfaces
[ERROR] [spawner.py-4]: process has died [pid 13610, exit code 1, cmd '/opt/ros/foxy/lib/controller_manager/spawner.py diff_cont --ros-args'].
[ERROR] [spawner.py-3]: process has died [pid 13608, exit code 1, cmd '/opt/ros/foxy/lib/controller_manager/spawner.py joint_broad --ros-args'].
Is there something we’ve missed out on? The controller_manager had issues earlier as well when running on the dev machine but it was sorted when it was rerun a few times.
Ok so the main error here is that it goes to load diff_cont
and joint_broad
but can’t find them. Instead it is finding one called test_controller
(I’m not sure if you’ve put that in or if it’s standard?)
Do you have a controllers.yaml
file that you are passing in? What is inside it? You should have the diff drive controller and joint state broadcaster defined in there.
If that is set up correctly, then make sure it is actually being loaded!
Yeah the old branch is foxy but I’m not really maintaining it.
The principles are all pretty similar so if you compare the two and watch this video you should be able to figure it out.
Thank you for your prompt response and suggestions, we will look into it.
I have a really weird Issue. The robot drives forwards and backwards fine but it doesn’t turn.
Hmm that is odd.
Is this with teleoperation or autonomous control?
I’d first use ros2 topic echo
to check the contents of your cmd_vel topic are correct and you are sending a Z rotation.
If that is all ok then check your diff drive parameters (wheel spacing etc) are all correct and you don’t have anything odd in there like rotational limits.
Both it is even a problem when I just use the ROS-Arduino-Bridge.ino and miniterm. When I type o 255 255 or negative it works fine. When I type o 255 -255 the motors don’t turn at all.
After fooling around with it quite a bit, I do see that it is the PID values, possible something else as well. I could sit and fool with the values, but the behavior is still strange (the motors start slow and rev up to the required speed, but overshoot it and reverse directions). Open loop control works great. I would love to rewrite this thing at some point. I’m fuzzy on a few things I need to research first, like how to translate input tick count to speed to PWM. I’m also not sure what “Ko” is in the PID code. Josh, what are the RPM speeds of your motors? I think mine are about 250 or so, maybe too much for this application (if that even makes a difference). Anyway, I’ll keep fussing with it.
[INFO] [launch]: All log files can be found below /home/cliff/.ros/log/2023-06-11-09-19-26-129315-cliff-Legion-4342
[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=PackageNotFoundError("package 'twist_mux' not found, searching: ['/home/cliff/dev_ws/install/serial_motor_demo', '/home/cliff/dev_ws/install/serial_motor_demo_msgs', '/home/cliff/dev_ws/install/diffdrive_arduino', '/home/cliff/dev_ws/install/serial', '/home/cliff/dev_ws/install/articubot_one', '/opt/ros/foxy']")>
Traceback (most recent call last):
File "/opt/ros/foxy/lib/python3.8/site-packages/ament_index_python/packages.py", line 50, in get_package_prefix
content, package_prefix = get_resource('packages', package_name)
File "/opt/ros/foxy/lib/python3.8/site-packages/ament_index_python/resources.py", line 48, in get_resource
raise LookupError(
LookupError: Could not find the resource 'twist_mux' of type 'packages'
During handling of the above exception, another exception occurred:
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 1 more time]
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 453, in execute
ret = super().execute(context)
File "/opt/ros/foxy/lib/python3.8/site-packages/launch/actions/execute_process.py", line 823, in execute
self.__expand_substitutions(context)
File "/opt/ros/foxy/lib/python3.8/site-packages/launch/actions/execute_process.py", line 668, in __expand_substitutions
cmd = [perform_substitutions(context, x) for x in self.__cmd]
File "/opt/ros/foxy/lib/python3.8/site-packages/launch/actions/execute_process.py", line 668, in <listcomp>
cmd = [perform_substitutions(context, x) for x in self.__cmd]
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_ros/substitutions/executable_in_package.py", line 76, in perform
package_prefix = super().perform(context)
File "/opt/ros/foxy/lib/python3.8/site-packages/launch_ros/substitutions/find_package.py", line 79, in perform
result = self.find(package)
File "/opt/ros/foxy/lib/python3.8/site-packages/launch_ros/substitutions/find_package.py", line 96, in find
return get_package_prefix(package_name)
File "/opt/ros/foxy/lib/python3.8/site-packages/ament_index_python/packages.py", line 52, in get_package_prefix
raise PackageNotFoundError(
ament_index_python.packages.PackageNotFoundError: "package 'twist_mux' not found, searching: ['/home/cliff/dev_ws/install/serial_motor_demo', '/home/cliff/dev_ws/install/serial_motor_demo_msgs', '/home/cliff/dev_ws/install/diffdrive_arduino', '/home/cliff/dev_ws/install/serial', '/home/cliff/dev_ws/install/articubot_one', '/opt/ros/foxy']"
Task exception was never retrieved
future: <Task finished name='Task-8' coro=<LaunchService._process_one_event() done, defined at /opt/ros/foxy/lib/python3.8/site-packages/launch/launch_service.py:226> exception=RuntimeError('Signal event received before subprocess transport available.')>
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 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/actions/opaque_function.py", line 75, in execute
return self.__function(context, *self.__args, **self.__kwargs)
File "/opt/ros/foxy/lib/python3.8/site-packages/launch/actions/execute_process.py", line 443, in __on_signal_process_event
raise RuntimeError('Signal event received before subprocess transport available.')
RuntimeError: Signal event received before subprocess transport available.
[INFO] [robot_state_publisher-1]: process started with pid [4345]
[robot_state_publisher-1] Parsing robot urdf xml string.
[robot_state_publisher-1] Link base_footprint had 0 children
[robot_state_publisher-1] Link chassis had 4 children
[robot_state_publisher-1] Link camera_link had 1 children
[robot_state_publisher-1] Link camera_link_optical had 0 children
[robot_state_publisher-1] Link caster_wheel had 0 children
[robot_state_publisher-1] Link face_link had 0 children
[robot_state_publisher-1] Link laser_frame had 0 children
[robot_state_publisher-1] Link left_wheel had 0 children
[robot_state_publisher-1] Link right_wheel had 0 children
[robot_state_publisher-1] [INFO] [1686455366.472416353] [robot_state_publisher]: got segment base_footprint
[robot_state_publisher-1] [INFO] [1686455366.472564150] [robot_state_publisher]: got segment base_link
[robot_state_publisher-1] [INFO] [1686455366.472588526] [robot_state_publisher]: got segment camera_link
[robot_state_publisher-1] [INFO] [1686455366.472606757] [robot_state_publisher]: got segment camera_link_optical
[robot_state_publisher-1] [INFO] [1686455366.472624637] [robot_state_publisher]: got segment caster_wheel
[robot_state_publisher-1] [INFO] [1686455366.472642309] [robot_state_publisher]: got segment chassis
[robot_state_publisher-1] [INFO] [1686455366.472659212] [robot_state_publisher]: got segment face_link
[robot_state_publisher-1] [INFO] [1686455366.472675486] [robot_state_publisher]: got segment laser_frame
[robot_state_publisher-1] [INFO] [1686455366.472692599] [robot_state_publisher]: got segment left_wheel
[robot_state_publisher-1] [INFO] [1686455366.472709362] [robot_state_publisher]: got segment right_wheel
[ERROR] [robot_state_publisher-1]: process[robot_state_publisher-1] failed to terminate '5' seconds after receiving 'SIGINT', escalating to 'SIGTERM'
[INFO] [robot_state_publisher-1]: sending signal 'SIGTERM' to process[robot_state_publisher-1]
[ERROR] [robot_state_publisher-1]: process has died [pid 4345, exit code -15, cmd '/opt/ros/foxy/lib/robot_state_publisher/robot_state_publisher --ros-args --params-file /tmp/launch_params_zw350_hn'].
Cant find whats actually going wrong, feels like its ros not building properly
Very odd, I’m suspicious of maybe a wiring issue with the motors/driver/arduino?
Do
o 255 0
o -255 0
o 0 255
o 0 -255
Interesting, I have had similar problems with other motors. I still got them to work but they were a bit more sensitive to the PID settings.
Yeah me too. I didn’t write the Arduino code (just made some small mods) and would like to do it from scratch.
I also found this confusing. I believe this and also the reason everything is done in “encoder ticks per loop” is to avoid doing floating point arithmetic in the Arduino. So the Ko
just scales things up. E.g. if we want Kp = 0.5
(and Ko = 1
) we can’t do that, so instead we set Kp = 5
and Ko = 10
.
It’s a little while since I dug into it though so that might be not quite right.
Pretty sure they are 110RPM. 250 is pretty fast, especially if your encoders aren’t super fast. E.g. your requests might boil down to the difference between a few integers in counts per loop and the PID will be jumping rapidly between them.
Make sure when posting code blocks (I have edited yours) you put backticks (the ~
key without shift) around it to make it easier to read, like this:
```
My code here
```
Your issue here is you don’t have twist_mux
installed (sudo apt install ros-foxy-twist-mux
).
This error should be clearer, except I have not explicitly made twist_mux
a dependency of articubot_one
so it tries to run without checking that it exists, and you get that very messy error.