How to solve this ros2_control error? [ros2_control_node-1] what(): According to the loaded plugin descriptions the class ackermann_steering_controller/AckermannSteeringController with base class type hardware_interface::SystemInterface does not exist

Hello!

I have been working on making a real hardware robot(car) with ackermann steering with front steering and rear wheels for driving. I have managed to load my car on rviz2. I used ros2_controllers/ackermann_steering_controller package for ros2_control for driving the car.

The launch files are written with reference from ros2_control documentation. The documentation also contains the demo of ros2_control of different types of robot, unfortunately there is no ros2_control_demo for robot with ackermann steering controller.

However I configured the ros2_controller/ackermann_steering_controller in my project but it didnt work as expected and threw some errors at last of this post.

Even with all of the ros2_control dependencies installed, the controller manager seems to not be working. Every form on this same problem seems to be unsolved for people using the Humble version. Here are the logs and setup (sorry for the long post):

Parameters file for ackermann_steering_controller is written with reference of ackermann_steering_controller and steering_controller_library from ros2_controllers documentation.

Launch file for viewing the car only:

from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.conditions import IfCondition from launch.substitutions import Command, FindExecutable, LaunchConfiguration, PathJoinSubstitution
from launch_ros.actions import Node
from launch_ros.substitutions import FindPackageShare
def generate_launch_description():
# Declare arguments
declared_arguments = []
declared_arguments.append(
    DeclareLaunchArgument(
        "description_package",
        default_value="car_gazebo",
        description="Description package with robot URDF/xacro files. Usually the argument \
    is not set, it enables use of a custom description.",
    )
)

   declared_arguments.append(
    DeclareLaunchArgument(
        "gui",
        default_value="true",
        description="Start Rviz2 and Joint State Publisher gui automatically \
    with this launch file.",
    )
)

   # Initialize Arguments
gui = LaunchConfiguration("gui")

   # Get URDF via xacro
robot_description_content = Command(
    [
        PathJoinSubstitution([FindExecutable(name="xacro")]),
        " ",
        PathJoinSubstitution(
            [
                FindPackageShare("car_gazebo"),
                "urdf",
                "car.urdf.xacro",
            ]
        ),
    ]
)
robot_description = {"robot_description": robot_description_content}

   joint_state_publisher_node = Node(
    package="joint_state_publisher_gui",
    executable="joint_state_publisher_gui",
    condition=IfCondition(gui),
)
robot_state_publisher_node = Node(
    package="robot_state_publisher",
    executable="robot_state_publisher",
    output="both",
    parameters=[robot_description],
)
rviz_node = Node(
    package="rviz2",
    executable="rviz2",
    name="rviz2",
    output="log",
    condition=IfCondition(gui),
)

   nodes = [
    joint_state_publisher_node,
    robot_state_publisher_node,
    rviz_node,
]

   return LaunchDescription(declared_arguments + nodes)

Launch file for running the car in real with ros2_control_node and controller_manager

def generate_launch_description():
# Declare arguments
declared_arguments = []
declared_arguments.append(
    DeclareLaunchArgument(
        "gui",
        default_value="true",
        description="Start RViz2 automatically with this launch file.",
    )
)

   # Initialize Arguments
gui = LaunchConfiguration("gui")

   # Get URDF via xacro
robot_description_content = Command(
    [
        PathJoinSubstitution([FindExecutable(name="xacro")]),
        " ",
        PathJoinSubstitution(
            [
                FindPackageShare("car_gazebo"),
                "urdf",
                "car.urdf.xacro",
            ]
        ),
    ]
)

   robot_description = {"robot_description": robot_description_content}

   robot_controllers = PathJoinSubstitution(
    [
        FindPackageShare("car_gazebo"),
        "config",
        "ackermann_steering_controller.yaml",
    ]
)

   # rviz_config_file = PathJoinSubstitution(
#     [FindPackageShare("car_gazebo"), "rrbot/rviz", "rrbot.rviz"]
# )

   control_node = Node(
    package="controller_manager",
    executable="ros2_control_node",
    parameters=[robot_description, robot_controllers],
    output="both",
)

   robot_state_pub_node = Node(
    package="robot_state_publisher",
    executable="robot_state_publisher",
    output="both",
    parameters=[robot_description],
)

   rviz_node = Node(
    package="rviz2",
    executable="rviz2",
    name="rviz2",
    output="log",
    condition=IfCondition(gui),
)

   joint_state_broadcaster_spawner = Node(
    package="controller_manager",
    executable="spawner",
    arguments=["joint_state_broadcaster",
               "--controller-manager", "/controller_manager"],
)

   robot_controller_spawner = Node(
    package="controller_manager",
    executable="spawner",
    arguments=["ackermann_steering_base_controller",
               "--controller-manager", "/controller_manager"],
)

   # Delay rviz start after `joint_state_broadcaster`
delay_rviz_after_joint_state_broadcaster_spawner = RegisterEventHandler(
    event_handler=OnProcessExit(
        target_action=joint_state_broadcaster_spawner,
        on_exit=[rviz_node],
    )
)

   # Delay start of robot_controller after `joint_state_broadcaster`
delay_robot_controller_spawner_after_joint_state_broadcaster_spawner = RegisterEventHandler(
    event_handler=OnProcessExit(
        target_action=joint_state_broadcaster_spawner,
        on_exit=[robot_controller_spawner],
    )
)

   nodes = [
    control_node,
    robot_state_pub_node,
    joint_state_broadcaster_spawner,
    delay_rviz_after_joint_state_broadcaster_spawner,
    delay_robot_controller_spawner_after_joint_state_broadcaster_spawner,
]

   return LaunchDescription(declared_arguments+nodes)

Here is the parameters file for the ackermann_steering_controller package

controller_manager:
  ros__parameters:
    update_rate: 30

    joint_state_broadcaster:
      type: joint_state_broadcaster/JointStateBroadcaster

    ackermann_steering_base_controller:
      type: ackermann_steering_controller/AckermannSteeringController

ackermann_steering_base_controller:
  ros__parameters:

    reference_timeout: 2.0
    front_steering: true

    rear_wheels_names: [rear_left_wheel_joint, rear_right_wheel_joint]
    front_wheels_names: [left_steering_joint, right_steering_joint]

    open_loop: false 
    velocity_rolling_window_size: 10

    publish_rate: 50.0
    odom_frame_id: odom
    base_frame_id: base_link

    enable_odom_tf: true

    twist_covariance_diagonal: [0.0, 7.0, 14.0, 21.0, 28.0, 35.0]
    pose_covariance_diagonal: [0.0, 7.0, 14.0, 21.0, 28.0, 35.0]

    position_feedback: false
    use_stamped_vel: false
    
    wheelbase: 0.46
    front_wheel_track: 1.8
    rear_wheel_track: 1.8
    front_wheels_radius: 0.115
    rear_wheels_radius: 0.115

Here is CMakeLists.txt raw file

cmake_minimum_required(VERSION 3.8)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
# uncomment the following section in order to fill in
# further dependencies manually.
# find_package(<dependency> REQUIRED)


if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
# the following line skips the linter which checks for copyrights
# comment the line when a copyright and license is added to all source files
set(ament_cmake_copyright_FOUND TRUE)
# the following line skips cpplint (only works in a git repo)
# comment the line when this package is in a git repo and when
# a copyright and license is added to all source files
set(ament_cmake_cpplint_FOUND TRUE)
ament_lint_auto_find_test_dependencies()
endif()

install(
  DIRECTORY launch rviz config worlds transforms src urdf
  DESTINATION share/${PROJECT_NAME}
)

ament_package()

Here is the ros2_control linked with hardware linked directly as specified in urdf of car.

<ros2_control name="ackermann_ros2_control" type="system">
    <hardware>
      <plugin>ackermann_steering_controller/AckermannSteeringController</plugin>
    </hardware>
    <joint name="rear_left_wheel_joint">
        <command_interface name="velocity" />
        <state_interface name="position" />
        <state_interface name="velocity" />
    </joint>
    <joint name="rear_right_wheel_joint">
        <command_interface name="velocity" />
        <state_interface name="position" />
        <state_interface name="velocity" />
    </joint>
    <joint name="left_steering_joint">
        <command_interface name="position" />
        <state_interface name="position" />
        <state_interface name="velocity" />
    </joint>
    <joint name="right_steering_joint">
        <command_interface name="position" />
        <state_interface name="position" />
        <state_interface name="velocity" />
    </joint>
</ros2_control>

THIS IS THE ERORR!!!

colcon build --symlink-install --allow-overriding ackermann_steering_controller ; source install/setup.bash ; ros2 launch car_gazebo car_bringup.launch.py 
[1.045s] WARNING:colcon.colcon_ros.prefix_path.ament:The path '/home/aarjan/minor_ros/install/ackermann_drive_controller' in the environment variable AMENT_PREFIX_PATH doesn't exist
[1.045s] WARNING:colcon.colcon_ros.prefix_path.catkin:The path '/home/aarjan/minor_ros/install/ackermann_drive_controller' in the environment variable CMAKE_PREFIX_PATH doesn't exist

Starting >>> ackermann_steering_controller
Starting >>> car_body
Starting >>> pubsub                                                                       
Finished <<< car_body [0.88s]                                                                                              
Finished <<< ackermann_steering_controller [1.08s]                                              
Starting >>> car_gazebo
Finished <<< car_gazebo [0.24s]                                              
Finished <<< pubsub [1.60s]   

Summary: 4 packages finished [2.60s]
[INFO] [launch]: All log files can be found below /home/aarjan/.ros/log/2024-02-12-21-58-28-865613-robotics-25902
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [ros2_control_node-1]: process started with pid [25905]
[INFO] [robot_state_publisher-2]: process started with pid [25907]
[INFO] [spawner-3]: process started with pid [25909]
[ros2_control_node-1] [WARN] [1707754409.129160634] [controller_manager]: [Deprecated] Passing the robot description parameter directly to the control_manager node is deprecated. Use '~/robot_description' topic from 'robot_state_publisher' instead.

[ros2_control_node-1] [INFO] [1707754409.129328123] [resource_manager]: Loading hardware 'ackermann_ros2_control' 
[ros2_control_node-1] terminate called after throwing an instance of 'pluginlib::LibraryLoadException'
[ros2_control_node-1]   what():  According to the loaded plugin descriptions the class ackermann_steering_controller/AckermannSteeringController with base class type hardware_interface::SystemInterface does not exist. Declared types are  fake_components/GenericSystem mock_components/GenericSystem test_hardware_components/TestSystemCommandModes test_hardware_components/TestTwoJointSystem test_system test_unitilizable_system turtlebot3_manipulation_hardware/TurtleBot3ManipulationSystemHardware

[ros2_control_node-1] Stack trace (most recent call last):
[ros2_control_node-1] #16   Object "", at 0xffffffffffffffff, in 
[ros2_control_node-1] #15   Object "/opt/ros/humble/lib/controller_manager/ros2_control_node", at 0x55fb7f788d84, in 
[robot_state_publisher-2] [INFO] [1707754409.131011613] [robot_state_publisher]: got segment base_footprint
[robot_state_publisher-2] [INFO] [1707754409.131083738] [robot_state_publisher]: got segment base_link
[robot_state_publisher-2] [INFO] [1707754409.131088347] [robot_state_publisher]: got segment chassis
[robot_state_publisher-2] [INFO] [1707754409.131091102] [robot_state_publisher]: got segment front_left_wheel
[robot_state_publisher-2] [INFO] [1707754409.131093672] [robot_state_publisher]: got segment front_right_wheel
[robot_state_publisher-2] [INFO] [1707754409.131095965] [robot_state_publisher]: got segment left_steering_link
[robot_state_publisher-2] [INFO] [1707754409.131098241] [robot_state_publisher]: got segment rear_left_wheel
[robot_state_publisher-2] [INFO] [1707754409.131100390] [robot_state_publisher]: got segment rear_right_wheel
[robot_state_publisher-2] [INFO] [1707754409.131102542] [robot_state_publisher]: got segment right_steering_link

[ros2_control_node-1] #14   Source "../csu/libc-start.c", line 392, in __libc_start_main_impl [0x7fcd9d629e3f]
[ros2_control_node-1] #13   Source "../sysdeps/nptl/libc_start_call_main.h", line 58, in __libc_start_call_main [0x7fcd9d629d8f]
[ros2_control_node-1] #12   Object "/opt/ros/humble/lib/controller_manager/ros2_control_node", at 0x55fb7f78889e, in 
[ros2_control_node-1] #11   Object "/opt/ros/humble/lib/libcontroller_manager.so", at 0x7fcd9e0b5719, in controller_manager::ControllerManager::ControllerManager(std::shared_ptr<rclcpp::Executor>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, rclcpp::NodeOptions const&)
[ros2_control_node-1] #10   Object "/opt/ros/humble/lib/libcontroller_manager.so", at 0x7fcd9e0b0e04, in controller_manager::ControllerManager::init_resource_manager(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
[ros2_control_node-1] #9    Object "/opt/ros/humble/lib/libhardware_interface.so", at 0x7fcd9dd18d9d, in hardware_interface::ResourceManager::load_urdf(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool, bool)
[ros2_control_node-1] #8    Object "/opt/ros/humble/lib/libhardware_interface.so", at 0x7fcd9dd171ce, in 
[ros2_control_node-1] #7    Object "/opt/ros/humble/lib/libhardware_interface.so", at 0x7fcd9dcf832a, in 
[ros2_control_node-1] #6    Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30", at 0x7fcd9daae4d7, in __cxa_throw
[ros2_control_node-1] #5    Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30", at 0x7fcd9daae276, in std::terminate()
[ros2_control_node-1] #4    Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30", at 0x7fcd9daae20b, in 
[ros2_control_node-1] #3    Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30", at 0x7fcd9daa2b9d, in 
[ros2_control_node-1] #2    Source "./stdlib/abort.c", line 79, in abort [0x7fcd9d6287f2]
[ros2_control_node-1] #1    Source "../sysdeps/posix/raise.c", line 26, in raise [0x7fcd9d642475]
[ros2_control_node-1] #0  | Source "./nptl/pthread_kill.c", line 89, in __pthread_kill_internal
[ros2_control_node-1]     | Source "./nptl/pthread_kill.c", line 78, in __pthread_kill_implementation
[ros2_control_node-1]       Source "./nptl/pthread_kill.c", line 44, in __pthread_kill [0x7fcd9d6969fc]
[ros2_control_node-1] Aborted (Signal sent by tkill() 25905 1000)

[ERROR] [ros2_control_node-1]: process has died [pid 25905, exit code -6, cmd '/opt/ros/humble/lib/controller_manager/ros2_control_node --ros-args --params-file /tmp/launch_params_8qnwt2ax --params-file /home/aarjan/minor_ros/install/car_gazebo/share/car_gazebo/config/ackermann_steering_controller.yaml'].
[spawner-3] [INFO] [1707754411.348236298] [spawner_joint_state_broadcaster]: Waiting for '/controller_manager' node to exist
[spawner-3] [INFO] [1707754413.365302157] [spawner_joint_state_broadcaster]: Waiting for '/controller_manager' node to exist
[spawner-3] [INFO] [1707754415.384160723] [spawner_joint_state_broadcaster]: Waiting for '/controller_manager' node to exist
[spawner-3] [INFO] [1707754417.401642295] [spawner_joint_state_broadcaster]: Waiting for '/controller_manager' node to exist
[spawner-3] [ERROR] [1707754419.422091681] [spawner_joint_state_broadcaster]: Controller manager not available
[ERROR] [spawner-3]: process has died [pid 25909, exit code 1, cmd '/opt/ros/humble/lib/controller_manager/spawner joint_state_broadcaster --controller-manager /controller_manager --ros-args'].
[INFO] [spawner-4]: process started with pid [26024]
[INFO] [rviz2-5]: process started with pid [26026]
[rviz2-5] [INFO] [1707754419.880410912] [rviz2]: Stereo is NOT SUPPORTED
[rviz2-5] [INFO] [1707754419.880543949] [rviz2]: OpenGl version: 4.6 (GLSL 4.6)
[rviz2-5] [INFO] [1707754419.895533589] [rviz2]: Stereo is NOT SUPPORTED

[rviz2-5] [WARN] [1707754419.957731402] [rcl.logging_rosout]: Publisher already registered for provided node name. If this is due to multiple nodes with the same name then all logs for that logger name will go out over the existing publisher. As soon as any node with that name is destructed it will unregister the publisher, preventing any further logs for that name from being published on the rosout topic.
[rviz2-5] [WARN] [1707754419.960753279] [rcl.logging_rosout]: Publisher already registered for provided node name. If this is due to multiple nodes with the same name then all logs for that logger name will go out over the existing publisher. As soon as any node with that name is destructed it will unregister the publisher, preventing any further logs for that name from being published on the rosout topic.
[spawner-4] [INFO] [1707754421.811967419] [spawner_ackermann_steering_base_controller]: Waiting for '/controller_manager' node to exist
[spawner-4] [INFO] [1707754423.832159604] [spawner_ackermann_steering_base_controller]: Waiting for '/controller_manager' node to exist
[spawner-4] [INFO] [1707754425.852644375] [spawner_ackermann_steering_base_controller]: Waiting for '/controller_manager' node to exist
[spawner-4] [INFO] [1707754427.872454754] [spawner_ackermann_steering_base_controller]: Waiting for '/controller_manager' node to exist
[spawner-4] [ERROR] [1707754429.893425903] [spawner_ackermann_steering_base_controller]: Controller manager not available
[ERROR] [spawner-4]: process has died [pid 26024, exit code 1, cmd '/opt/ros/humble/lib/controller_manager/spawner ackermann_steering_base_controller --controller-manager /controller_manager --ros-args'].

This is the code from ackermann_steering_controller/src/ackermann_steering_controller.cpp Maybe the problem is causing due to

#include "pluginlib/class_list_macros.hpp"

// <controller_name_namespace>::<ControllerName>
// second the base class, controller_interface::ControllerInterface.
PLUGINLIB_EXPORT_CLASS(
    ackermann_steering_controller::AckermannSteeringController,
    controller_interface::ChainableControllerInterface)

means that ackermann_steering_controller is exported with base class type as controller_interface::ChainableControllerInterface but ros2_control_node is expecting it to be of base class type as hardware_interface::SystemInterface.

How can I solve this, DO I modify the code in package file or do some other things?

Could you please help me tackling this error or have some solution that might help me…

Thank You!

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.