Ros2_control - spawner.py not found

Hi

I have a simple robot, the robot is controlled with a raspberry pi gpio, L298N. I’m working on creature hardware interface. it’s a black magician for me.

based on your code trying to understand how to do it i have some problems with it

My setup:

Ubuntu 22.04

Ros2 Humble

My code: GitHub - mkonwerski/diffdrive_arduino at lolo

lolo@lolo:~/robot_sw$ source install/setup.sh
lolo@lolo:~/robot_sw$ ros2 launch articubot_one launch_robot.launch.py
[INFO] [launch]: All log files can be found below /home/lolo/.ros/log/2022-10-28-21-49-48-170830-lolo-3406
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [robot_state_publisher-1]: process started with pid [3419]
[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] [1666986591.834266827] [robot_state_publisher]: got segment base_link
[robot_state_publisher-1] [INFO] [1666986591.835206611] [robot_state_publisher]: got segment camera_link
[robot_state_publisher-1] [INFO] [1666986591.835403277] [robot_state_publisher]: got segment camera_link_optical
[robot_state_publisher-1] [INFO] [1666986591.835505932] [robot_state_publisher]: got segment caster_wheel
[robot_state_publisher-1] [INFO] [1666986591.835603900] [robot_state_publisher]: got segment chassis
[robot_state_publisher-1] [INFO] [1666986591.835699837] [robot_state_publisher]: got segment face_link
[robot_state_publisher-1] [INFO] [1666986591.835796607] [robot_state_publisher]: got segment laser_frame
[robot_state_publisher-1] [INFO] [1666986591.835907648] [robot_state_publisher]: got segment left_wheel
[robot_state_publisher-1] [INFO] [1666986591.836107594] [robot_state_publisher]: got segment right_wheel
[INFO] [ros2_control_node-2]: process started with pid [3483]
[ERROR] [launch]: Caught exception in launch (see debug for traceback): executable 'spawner.py' not found on the libexec directory '/opt/ros/humble/lib/controller_manager'
[INFO] [ros2_control_node-2]: sending signal 'SIGINT' to process[ros2_control_node-2]
[INFO] [robot_state_publisher-1]: sending signal 'SIGINT' to process[robot_state_publisher-1]
[ERROR] [ros2_control_node-2]: process has died [pid 3483, exit code -2, cmd '/opt/ros/humble/lib/controller_manager/ros2_control_node --ros-args --params-file /tmp/launch_params_hyw5g_8t --params-file /home/lolo/robot_sw/install/articubot_one/share/articubot_one/config/my_controllers.yaml'].
[robot_state_publisher-1] [INFO] [1666986599.524392759] [rclcpp]: signal_handler(signum=2)
[INFO] [robot_state_publisher-1]: process has finished cleanly [pid 3419]
lolo@lolo:~/robot_sw$ ros2 run controller_manager spawner
usage: spawner [-h] [-c CONTROLLER_MANAGER] [-p PARAM_FILE] [--load-only] [--stopped] [--inactive] [-t CONTROLLER_TYPE]
               [-u] [--controller-manager-timeout CONTROLLER_MANAGER_TIMEOUT]
               controller_name
spawner: error: the following arguments are required: controller_name
[ros2run]: Process exited with failure 2
lolo@lolo:~/robot_sw$ ls /opt/ros/humble/lib/controller_manager
ros2_control_node  spawner  unspawner
lolo@lolo:~/robot_sw$ /opt/ros/humble/lib/controller_manager/ros2_control_node --ros-args --params-file /tmp/launch_params_hyw5g_8t --params-file /home/lolo/robot_sw/install/articubot_one/share/articubot_one/config/my_controllers.yaml


[INFO] [1666990050.219291726] [resource_manager]: Loading hardware 'RealRobot'
[INFO] [1666990050.255340732] [resource_manager]: Initialize hardware 'RealRobot'
[INFO] [1666990050.258260654] [DiffDriveArduino]: -----------------------------*
[INFO] [1666990050.258455288] [DiffDriveArduino]: step: on_init
[INFO] [1666990050.259081793] [DiffDriveArduino]: -----------------------------!
[INFO] [1666990050.259239552] [resource_manager]: Successful initialization of hardware 'RealRobot'
[INFO] [1666990050.259347520] [DiffDriveArduino]: -----------------------------*
[INFO] [1666990050.259439550] [DiffDriveArduino]: step: export_state_interfaces
[INFO] [1666990050.260059597] [DiffDriveArduino]: -----------------------------!
[INFO] [1666990050.260246626] [DiffDriveArduino]: -----------------------------*
[INFO] [1666990050.260646050] [DiffDriveArduino]: step: export_command_interfaces
[INFO] [1666990050.261204222] [DiffDriveArduino]: -----------------------------!
[INFO] [1666990050.261453335] [resource_manager]: 'configure' hardware 'RealRobot'
[INFO] [1666990050.261562396] [resource_manager]: Successful 'configure' of hardware 'RealRobot'
[INFO] [1666990050.261667708] [resource_manager]: 'activate' hardware 'RealRobot'
[INFO] [1666990050.261796769] [DiffDriveArduino]: -----------------------------*
[INFO] [1666990050.261895987] [DiffDriveArduino]: step: on_activate
[INFO] [1666990050.261995778] [DiffDriveArduino]: Activating ...please wait...
[INFO] [1666990050.262117027] [DiffDriveArduino]: Successfully activated!
[INFO] [1666990050.262208849] [DiffDriveArduino]: -----------------------------!
[INFO] [1666990050.262306973] [resource_manager]: Successful 'activate' of hardware 'RealRobot'
[INFO] [1666990050.304599986] [controller_manager]: update rate is 30 Hz
[INFO] [1666990050.305668779] [controller_manager]: RT kernel is recommended for better performance
[INFO] [1666990050.305954349] [DiffDriveArduino]: -----------------------------*
[INFO] [1666990050.306044140] [DiffDriveArduino]: step: read
[INFO] [1666990050.306116900] [DiffDriveArduino]: Got position state 0.00000 and velocity state 0.00000 for 'left_wheel_joint'!
[INFO] [1666990050.306188879] [DiffDriveArduino]: Got position state 0.00000 and velocity state 0.00000 for 'right_wheel_joint'!
[INFO] [1666990050.306296326] [DiffDriveArduino]: Joints successfully read! (0.00000,0.00000,0.00000)
[INFO] [1666990050.306364033] [DiffDriveArduino]: -----------------------------!
[INFO] [1666990050.306437262] [DiffDriveArduino]: -----------------------------*
[INFO] [1666990050.306491116] [DiffDriveArduino]: step: write
[INFO] [1666990050.306542313] [DiffDriveArduino]: Writing...
[INFO] [1666990050.306595021] [DiffDriveArduino]: Got command 0.00000 for 'left_wheel_joint'!
[INFO] [1666990050.306664812] [DiffDriveArduino]: Got command 0.00000 for 'right_wheel_joint'!
[INFO] [1666990050.306721739] [DiffDriveArduino]: Joints successfully written!
[INFO] [1666990050.306773769] [DiffDriveArduino]: -----------------------------!
[INFO] [1666990050.339467596] [DiffDriveArduino]: -----------------------------*```

So sorry for taking such a long time to reply!

There’s a bit to unpack here. Firstly, good on you for having a crack at converting the hardware interface to humble! I will be doing so myself eventually but probably at the end of the series.

It’s a little hard to tell exactly what’s going on from your text snippets but here’s a few comments (that you’ve possibly already figured out):

  • Under foxy, the controller activation process is:
    • Run the ros2 control node with the appropriate params to load the controller up into the system. This will also start the hardware components.
    • Run ros2 run controller_manager spawner <controller_name> or use the equivalent ros2 control ... cli tool (or call a service) to start the controller
  • I think under humble (which I’ve not used ros2_control with yet) you have the option to auto-run controllers when ros2_control_node starts or run them manually.
  • As per the video, the controller manager needs to know the URDF as a robot_description parameter so that it can spawn the hardware components and it needs the controller params so that it can run the controllers. I assume that the temporary params file you are passing in (which is an unusual approach, possibly part of your troubleshooting process?) contains the robot description parameter.
  • Your DiffDriveArduino prints are coming from the hardware component but I’m not quite sure if you’ve got the controller running or not (something is causing read/writes from the hardware?)
  • If your controller is not running yet, then try running the spawner with the controller name, that’s what the error you are getting is saying (spawner: error: the following arguments are required: controller_name)

Assuming that’s all understood, taking quick look at your code suggests some confusion between the role of controller and hardware component.
The controller should handle the conversion from body velocity input to motor velocities (in rad/s). The hardware component/interface should handle the translation of motor velocity requests to motor control commands.

For a simple diff drive robot, you should be able to rely on the provided diff_drive_controller for the controller, and only need to supply the hardware component (e.g. my one that you have modified).

Parts of your code such as this suggest that controller/diff_drive stuff is creeping in to your hardware component*. Maybe that is just a debugging thing you’ve put in there, I’m not sure, but it would not normally live there.

I’m not sure if any of that is helpful, if not feel free to reply with more details and I’m sure we’ll be able to figure it out :smiley:

*I do recognise that my package and variable names could create some confusion in this area. It would probably be better if I just named them “Motor A” and “Motor B” as there is nothing inherently “diff-drive specific” to the code, it is just designed for that kind of configuration.