diff --git a/controller_manager/CMakeLists.txt b/controller_manager/CMakeLists.txt
index 3671179fae..5dea15c0d1 100644
--- a/controller_manager/CMakeLists.txt
+++ b/controller_manager/CMakeLists.txt
@@ -211,14 +211,6 @@ if(BUILD_TESTING)
controller_manager_msgs
)
- install(FILES test/test_controllers.yaml
- DESTINATION test)
-
- find_package(launch_testing_ament_cmake REQUIRED)
- add_launch_test(test/test_spawner_integration.py
- TIMEOUT 180
- )
-
find_package(ament_cmake_pytest REQUIRED)
install(FILES test/test_ros2_control_node.yaml
DESTINATION test)
diff --git a/controller_manager/package.xml b/controller_manager/package.xml
index b4b295656e..c0e02df044 100644
--- a/controller_manager/package.xml
+++ b/controller_manager/package.xml
@@ -32,10 +32,8 @@
ament_cmake_gmock
ament_cmake_pytest
hardware_interface_testing
- launch_testing_ament_cmake
python3-coverage
ros2_control_test_assets
- xacro
ament_cmake
diff --git a/controller_manager/test/test_controllers.yaml b/controller_manager/test/test_controllers.yaml
deleted file mode 100644
index a465e81ad6..0000000000
--- a/controller_manager/test/test_controllers.yaml
+++ /dev/null
@@ -1,105 +0,0 @@
----
-controller_manager:
- ros__parameters:
- update_rate: 100
-
- joint_state_broadcaster0:
- type: controller_manager/test_controller
- joint_state_broadcaster1:
- type: controller_manager/test_controller
- joint_state_broadcaster2:
- type: controller_manager/test_controller
- joint_state_broadcaster3:
- type: controller_manager/test_controller
- joint_state_broadcaster4:
- type: controller_manager/test_controller
- joint_state_broadcaster5:
- type: controller_manager/test_controller
- joint_state_broadcaster6:
- type: controller_manager/test_controller
- joint_state_broadcaster7:
- type: controller_manager/test_controller
- joint_state_broadcaster8:
- type: controller_manager/test_controller
- joint_state_broadcaster9:
- type: controller_manager/test_controller
- joint_state_broadcaster10:
- type: controller_manager/test_controller
- joint_state_broadcaster11:
- type: controller_manager/test_controller
- joint_state_broadcaster12:
- type: controller_manager/test_controller
- joint_state_broadcaster13:
- type: controller_manager/test_controller
- joint_state_broadcaster14:
- type: controller_manager/test_controller
- joint_state_broadcaster15:
- type: controller_manager/test_controller
- joint_state_broadcaster16:
- type: controller_manager/test_controller
- joint_state_broadcaster17:
- type: controller_manager/test_controller
- joint_state_broadcaster18:
- type: controller_manager/test_controller
- joint_state_broadcaster19:
- type: controller_manager/test_controller
- joint_state_broadcaster20:
- type: controller_manager/test_controller
- joint_state_broadcaster21:
- type: controller_manager/test_controller
- joint_state_broadcaster22:
- type: controller_manager/test_controller
- joint_state_broadcaster23:
- type: controller_manager/test_controller
- joint_state_broadcaster24:
- type: controller_manager/test_controller
- joint_state_broadcaster25:
- type: controller_manager/test_controller
- joint_state_broadcaster26:
- type: controller_manager/test_controller
- joint_state_broadcaster27:
- type: controller_manager/test_controller
- joint_state_broadcaster28:
- type: controller_manager/test_controller
- joint_state_broadcaster29:
- type: controller_manager/test_controller
- joint_state_broadcaster30:
- type: controller_manager/test_controller
- joint_state_broadcaster31:
- type: controller_manager/test_controller
- joint_state_broadcaster32:
- type: controller_manager/test_controller
- joint_state_broadcaster33:
- type: controller_manager/test_controller
- joint_state_broadcaster34:
- type: controller_manager/test_controller
- joint_state_broadcaster35:
- type: controller_manager/test_controller
- joint_state_broadcaster36:
- type: controller_manager/test_controller
- joint_state_broadcaster37:
- type: controller_manager/test_controller
- joint_state_broadcaster38:
- type: controller_manager/test_controller
- joint_state_broadcaster39:
- type: controller_manager/test_controller
- joint_state_broadcaster40:
- type: controller_manager/test_controller
- joint_state_broadcaster41:
- type: controller_manager/test_controller
- joint_state_broadcaster42:
- type: controller_manager/test_controller
- joint_state_broadcaster43:
- type: controller_manager/test_controller
- joint_state_broadcaster44:
- type: controller_manager/test_controller
- joint_state_broadcaster45:
- type: controller_manager/test_controller
- joint_state_broadcaster46:
- type: controller_manager/test_controller
- joint_state_broadcaster47:
- type: controller_manager/test_controller
- joint_state_broadcaster48:
- type: controller_manager/test_controller
- joint_state_broadcaster49:
- type: controller_manager/test_controller
diff --git a/controller_manager/test/test_spawner_integration.py b/controller_manager/test/test_spawner_integration.py
deleted file mode 100644
index 73299bf000..0000000000
--- a/controller_manager/test/test_spawner_integration.py
+++ /dev/null
@@ -1,194 +0,0 @@
-# Copyright 2024 FZI Forschungszentrum Informatik
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# Author: Felix Exner
-
-import time
-import pytest
-import unittest
-
-import launch
-import launch_testing.actions
-
-from launch.substitutions import (
- Command,
- FindExecutable,
- PathJoinSubstitution,
-)
-from launch_ros.substitutions import FindPackageShare
-from launch_ros.parameter_descriptions import ParameterFile
-
-from launch_ros.actions import Node as LaunchNode
-
-# Imports for tests
-import rclpy
-from rclpy.node import Node
-import logging
-
-from controller_manager_msgs.srv import ListControllers
-
-CONTROLLER_SPAWNER_TIMEOUT = "10"
-
-active_controllers = [
- "joint_state_broadcaster0",
- "joint_state_broadcaster1",
- "joint_state_broadcaster2",
- "joint_state_broadcaster3",
- "joint_state_broadcaster4",
- "joint_state_broadcaster5",
- "joint_state_broadcaster6",
- "joint_state_broadcaster7",
- "joint_state_broadcaster8",
- "joint_state_broadcaster9",
- "joint_state_broadcaster10",
- "joint_state_broadcaster11",
- "joint_state_broadcaster12",
- "joint_state_broadcaster13",
- "joint_state_broadcaster14",
- "joint_state_broadcaster15",
- "joint_state_broadcaster16",
- "joint_state_broadcaster17",
- "joint_state_broadcaster18",
- "joint_state_broadcaster19",
- "joint_state_broadcaster20",
- "joint_state_broadcaster21",
- "joint_state_broadcaster22",
- "joint_state_broadcaster23",
- "joint_state_broadcaster24",
- "joint_state_broadcaster25",
- "joint_state_broadcaster26",
- "joint_state_broadcaster27",
- "joint_state_broadcaster28",
- "joint_state_broadcaster29",
- "joint_state_broadcaster30",
- "joint_state_broadcaster31",
- "joint_state_broadcaster32",
- "joint_state_broadcaster33",
- "joint_state_broadcaster34",
- "joint_state_broadcaster35",
- "joint_state_broadcaster36",
- "joint_state_broadcaster37",
- "joint_state_broadcaster38",
- "joint_state_broadcaster39",
- "joint_state_broadcaster40",
- "joint_state_broadcaster41",
- "joint_state_broadcaster42",
- "joint_state_broadcaster43",
- "joint_state_broadcaster44",
- "joint_state_broadcaster45",
- "joint_state_broadcaster46",
- "joint_state_broadcaster47",
- "joint_state_broadcaster48",
- "joint_state_broadcaster49",
-]
-
-
-def controller_spawner(controllers, active=True):
- inactive_flags = ["--inactive"] if not active else []
- return LaunchNode(
- package="controller_manager",
- executable="spawner",
- arguments=[
- "--controller-manager",
- "/controller_manager",
- "--controller-manager-timeout",
- CONTROLLER_SPAWNER_TIMEOUT,
- ]
- + inactive_flags
- + controllers,
- )
-
-
-@pytest.mark.launch_test
-def generate_test_description():
- robot_description_content = Command(
- [
- PathJoinSubstitution([FindExecutable(name="xacro")]),
- " ",
- PathJoinSubstitution(
- [
- FindPackageShare("ros2_control_test_assets"),
- "urdf",
- "test_description_mock.urdf",
- ]
- ),
- ]
- )
- robot_state_publisher_node = LaunchNode(
- package="robot_state_publisher",
- executable="robot_state_publisher",
- output="both",
- parameters=[{"robot_description": robot_description_content}],
- )
-
- control_node = LaunchNode(
- package="controller_manager",
- executable="ros2_control_node",
- parameters=[
- ParameterFile(
- PathJoinSubstitution(
- [FindPackageShare("controller_manager"), "test", "test_controllers.yaml"]
- )
- )
- ],
- output="screen",
- )
-
- spawners = [controller_spawner([x]) for x in active_controllers]
-
- return launch.LaunchDescription(
- [
- robot_state_publisher_node,
- control_node,
- launch_testing.actions.ReadyToTest(),
- ]
- + spawners
- )
-
-
-class TestControllersRunning(unittest.TestCase):
- @classmethod
- def setUpClass(cls):
- # Initialize the ROS context
- rclpy.init()
- cls.node = Node("controller_spawner_test")
-
- def _wait_for_service(self, srv_name, srv_type, timeout=10):
- client = self.node.create_client(srv_type, srv_name)
-
- logging.info("Waiting for service '%s' with timeout %fs...", srv_name, timeout)
- if client.wait_for_service(timeout) is False:
- raise Exception(f"Could not reach service '{srv_name}' within timeout of {timeout}")
- logging.info(" Successfully connected to service '%s'", srv_name)
-
- return client
-
- def test_all_controllers_available(self):
- client = self._wait_for_service(
- srv_name="controller_manager/list_controllers", srv_type=ListControllers
- )
- # This is basically a dirty hack. It would be better to add events to all the spawners
- # exiting and emit ReadyToTest() only after all of them have quit. One problem there: They
- # do not necessarily quit, but can get into a deadlock waiting for a service response.
- time.sleep(30)
- request = ListControllers.Request()
- future = client.call_async(request)
- rclpy.spin_until_future_complete(self.node, future)
- if future.result() is None:
- raise Exception(
- f"Error while calling service '{client.srv_name}': {future.exception()}"
- )
-
- result = future.result()
- self.assertEqual(len(result.controller), len(active_controllers))
diff --git a/controller_manager/test/test_spawner_unspawner.cpp b/controller_manager/test/test_spawner_unspawner.cpp
index 3edf770436..3de8708235 100644
--- a/controller_manager/test/test_spawner_unspawner.cpp
+++ b/controller_manager/test/test_spawner_unspawner.cpp
@@ -374,6 +374,32 @@ TEST_F(TestLoadController, spawner_test_fallback_controllers)
}
}
+TEST_F(TestLoadController, spawner_with_many_controllers)
+{
+ std::stringstream ss;
+ const size_t num_controllers = 50;
+ const std::string controller_base_name = "ctrl_";
+ for (size_t i = 0; i < num_controllers; i++)
+ {
+ std::string controller_name = controller_base_name + std::to_string(static_cast(i));
+ cm_->set_parameter(
+ rclcpp::Parameter(controller_name + ".type", test_controller::TEST_CONTROLLER_CLASS_NAME));
+ ss << controller_name << " ";
+ }
+
+ ControllerManagerRunner cm_runner(this);
+ EXPECT_EQ(call_spawner(ss.str() + " -c test_controller_manager"), 0);
+
+ ASSERT_EQ(cm_->get_loaded_controllers().size(), num_controllers);
+
+ for (size_t i = 0; i < num_controllers; i++)
+ {
+ auto ctrl = cm_->get_loaded_controllers()[i];
+ ASSERT_EQ(ctrl.info.type, test_controller::TEST_CONTROLLER_CLASS_NAME);
+ ASSERT_EQ(ctrl.c->get_state().id(), lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE);
+ }
+}
+
class TestLoadControllerWithoutRobotDescription
: public ControllerManagerFixture
{
diff --git a/ros2_control_test_assets/CMakeLists.txt b/ros2_control_test_assets/CMakeLists.txt
index 8182766b44..d1bb895eed 100644
--- a/ros2_control_test_assets/CMakeLists.txt
+++ b/ros2_control_test_assets/CMakeLists.txt
@@ -14,10 +14,6 @@ install(
DIRECTORY include/
DESTINATION include/ros2_control_test_assets
)
-install(
- DIRECTORY urdf
- DESTINATION share/${PROJECT_NAME}
-)
install(TARGETS ros2_control_test_assets
EXPORT export_ros2_control_test_assets
ARCHIVE DESTINATION lib
diff --git a/ros2_control_test_assets/urdf/test_description_mock.urdf b/ros2_control_test_assets/urdf/test_description_mock.urdf
deleted file mode 100644
index 715de97540..0000000000
--- a/ros2_control_test_assets/urdf/test_description_mock.urdf
+++ /dev/null
@@ -1,91 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- mock_components/GenericSystem
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-