Skip to content

Commit

Permalink
Merge branch 'master' into add/test_utils
Browse files Browse the repository at this point in the history
  • Loading branch information
saikishor authored Dec 19, 2024
2 parents df209eb + 65d4092 commit 7bd97e2
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 3 deletions.
3 changes: 3 additions & 0 deletions controller_manager/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,12 @@ target_link_libraries(ros2_control_node PRIVATE
if(BUILD_TESTING)
find_package(ament_cmake_gmock REQUIRED)
find_package(ros2_control_test_assets REQUIRED)
find_package(example_interfaces REQUIRED)

# Plugin Libraries that are built and installed for use in testing
add_library(test_controller SHARED test/test_controller/test_controller.cpp)
target_link_libraries(test_controller PUBLIC controller_manager)
ament_target_dependencies(test_controller PUBLIC example_interfaces)
target_compile_definitions(test_controller PRIVATE "CONTROLLER_MANAGER_BUILDING_DLL")
pluginlib_export_plugin_description_file(controller_interface test/test_controller/test_controller.xml)
install(
Expand Down Expand Up @@ -210,6 +212,7 @@ if(BUILD_TESTING)
)
target_link_libraries(test_hardware_spawner
controller_manager
test_controller
ros2_control_test_assets::ros2_control_test_assets
)

Expand Down
16 changes: 16 additions & 0 deletions controller_manager/controller_manager/spawner.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
load_controller,
switch_controllers,
unload_controller,
set_controller_parameters,
set_controller_parameters_from_param_files,
bcolors,
)
Expand Down Expand Up @@ -145,6 +146,12 @@ def main(args=None):
action="store_true",
required=False,
)
parser.add_argument(
"--controller-ros-args",
help="The --ros-args to be passed to the controller node for remapping topics etc",
default=None,
required=False,
)

command_line_args = rclpy.utilities.remove_ros_args(args=sys.argv)[1:]
args = parser.parse_args(command_line_args)
Expand Down Expand Up @@ -203,6 +210,15 @@ def main(args=None):
+ bcolors.ENDC
)
else:
if controller_ros_args := args.controller_ros_args:
if not set_controller_parameters(
node,
controller_manager_name,
controller_name,
"node_options_args",
controller_ros_args.split(),
):
return 1
if param_files:
if not set_controller_parameters_from_param_files(
node,
Expand Down
4 changes: 3 additions & 1 deletion controller_manager/doc/userdoc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ There are two scripts to interact with controller manager from launch files:
$ ros2 run controller_manager spawner -h
usage: spawner [-h] [-c CONTROLLER_MANAGER] [-p PARAM_FILE] [-n NAMESPACE] [--load-only] [--inactive] [-u] [--controller-manager-timeout CONTROLLER_MANAGER_TIMEOUT]
[--switch-timeout SWITCH_TIMEOUT] [--activate-as-group] [--service-call-timeout SERVICE_CALL_TIMEOUT]
[--switch-timeout SWITCH_TIMEOUT] [--activate-as-group] [--service-call-timeout SERVICE_CALL_TIMEOUT] [--controller-ros-args CONTROLLER_ROS_ARGS]
controller_names [controller_names ...]
positional arguments:
Expand All @@ -167,6 +167,8 @@ There are two scripts to interact with controller manager from launch files:
Time to wait for a successful state switch of controllers. Useful if controllers cannot be switched immediately, e.g., paused
simulations at startup
--activate-as-group Activates all the parsed controllers list together instead of one by one. Useful for activating all chainable controllers altogether
--controller-ros-args CONTROLLER_ROS_ARGS
The --ros-args to be passed to the controller node for remapping topics etc
The parsed controller config file can follow the same conventions as the typical ROS 2 parameter file format. Now, the spawner can handle config files with wildcard entries and also the controller name in the absolute namespace. See the following examples on the config files:
Expand Down
1 change: 1 addition & 0 deletions controller_manager/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
<test_depend>robot_state_publisher</test_depend>
<test_depend>ros2_control_test_assets</test_depend>
<test_depend>sensor_msgs</test_depend>
<test_depend>example_interfaces</test_depend>

<export>
<build_type>ament_cmake</build_type>
Expand Down
35 changes: 35 additions & 0 deletions controller_manager/src/controller_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,17 @@ controller_interface::ControllerInterfaceBaseSharedPtr ControllerManager::load_c
controller_spec.info.fallback_controllers_names = fallback_controllers;
}

const std::string node_options_args_param = controller_name + ".node_options_args";
std::vector<std::string> node_options_args;
if (!has_parameter(node_options_args_param))
{
declare_parameter(node_options_args_param, rclcpp::ParameterType::PARAMETER_STRING_ARRAY);
}
if (get_parameter(node_options_args_param, node_options_args) && !node_options_args.empty())
{
controller_spec.info.node_options_args = node_options_args;
}

return add_controller_impl(controller_spec);
}

Expand Down Expand Up @@ -3453,6 +3464,18 @@ rclcpp::NodeOptions ControllerManager::determine_controller_node_options(
node_options_arguments.push_back(arg);
}

// Add deprecation notice if the arguments are from the controller_manager node
if (
check_for_element(node_options_arguments, RCL_REMAP_FLAG) ||
check_for_element(node_options_arguments, RCL_SHORT_REMAP_FLAG))
{
RCLCPP_WARN(
get_logger(),
"The use of remapping arguments to the controller_manager node is deprecated. Please use the "
"'--controller-ros-args' argument of the spawner to pass remapping arguments to the "
"controller node.");
}

for (const auto & parameters_file : controller.info.parameters_files)
{
if (!check_for_element(node_options_arguments, RCL_ROS_ARGS_FLAG))
Expand All @@ -3475,6 +3498,18 @@ rclcpp::NodeOptions ControllerManager::determine_controller_node_options(
node_options_arguments.push_back("use_sim_time:=true");
}

// Add options parsed through the spawner
if (
!controller.info.node_options_args.empty() &&
!check_for_element(controller.info.node_options_args, RCL_ROS_ARGS_FLAG))
{
node_options_arguments.push_back(RCL_ROS_ARGS_FLAG);
}
for (const auto & arg : controller.info.node_options_args)
{
node_options_arguments.push_back(arg);
}

std::string arguments;
arguments.reserve(1000);
for (const auto & arg : node_options_arguments)
Expand Down
11 changes: 11 additions & 0 deletions controller_manager/test/test_controller/test_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,17 @@ CallbackReturn TestController::on_init() { return CallbackReturn::SUCCESS; }

CallbackReturn TestController::on_configure(const rclcpp_lifecycle::State & /*previous_state*/)
{
const std::string service_name = get_node()->get_name() + std::string("/set_bool");
service_ = get_node()->create_service<example_interfaces::srv::SetBool>(
service_name,
[this](
const std::shared_ptr<example_interfaces::srv::SetBool::Request> request,
std::shared_ptr<example_interfaces::srv::SetBool::Response> response)
{
RCLCPP_INFO_STREAM(
get_node()->get_logger(), "Setting response to " << std::boolalpha << request->data);
response->success = request->data;
});
return CallbackReturn::SUCCESS;
}

Expand Down
6 changes: 4 additions & 2 deletions controller_manager/test/test_controller/test_controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@
#ifndef TEST_CONTROLLER__TEST_CONTROLLER_HPP_
#define TEST_CONTROLLER__TEST_CONTROLLER_HPP_

#include <memory>
#include <string>
#include <vector>

#include "controller_interface/controller_interface.hpp"
#include "controller_manager/visibility_control.h"
#include "example_interfaces/srv/set_bool.hpp"
#include "rclcpp/rclcpp.hpp"
#include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp"

namespace test_controller
Expand Down Expand Up @@ -68,10 +71,9 @@ class TestController : public controller_interface::ControllerInterface
CONTROLLER_MANAGER_PUBLIC
std::vector<double> get_state_interface_data() const;

const std::string & getRobotDescription() const;

void set_external_commands_for_testing(const std::vector<double> & commands);

rclcpp::Service<example_interfaces::srv::SetBool>::SharedPtr service_;
unsigned int internal_counter = 0;
bool simulate_cleanup_failure = false;
// Variable where we store when cleanup was called, pointer because the controller
Expand Down
39 changes: 39 additions & 0 deletions controller_manager/test/test_spawner_unspawner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,45 @@ TEST_F(TestLoadController, spawner_with_many_controllers)
}
}

TEST_F(TestLoadController, test_spawner_parsed_controller_ros_args)
{
ControllerManagerRunner cm_runner(this);
cm_->set_parameter(rclcpp::Parameter("ctrl_1.type", test_controller::TEST_CONTROLLER_CLASS_NAME));
cm_->set_parameter(rclcpp::Parameter("ctrl_2.type", test_controller::TEST_CONTROLLER_CLASS_NAME));
std::stringstream ss;

EXPECT_EQ(call_spawner("ctrl_1 -c test_controller_manager"), 0);
ASSERT_EQ(cm_->get_loaded_controllers().size(), 1ul);

// Now as the controller is active, we can call check for the service
std::shared_ptr<rclcpp::Node> node = rclcpp::Node::make_shared("set_bool_client");
auto set_bool_service = node->create_client<example_interfaces::srv::SetBool>("/set_bool");
ASSERT_FALSE(set_bool_service->wait_for_service(std::chrono::seconds(2)));
ASSERT_FALSE(set_bool_service->service_is_ready());
// Now check the service availability in the controller namespace
auto ctrl_1_set_bool_service =
node->create_client<example_interfaces::srv::SetBool>("/ctrl_1/set_bool");
ASSERT_TRUE(ctrl_1_set_bool_service->wait_for_service(std::chrono::seconds(2)));
ASSERT_TRUE(ctrl_1_set_bool_service->service_is_ready());

// Now test the remapping of the service name with the controller_ros_args
EXPECT_EQ(
call_spawner(
"ctrl_2 -c test_controller_manager --controller-ros-args '-r /ctrl_2/set_bool:=/set_bool'"),
0);

ASSERT_EQ(cm_->get_loaded_controllers().size(), 2ul);

// Now as the controller is active, we can call check for the remapped service
ASSERT_TRUE(set_bool_service->wait_for_service(std::chrono::seconds(2)));
ASSERT_TRUE(set_bool_service->service_is_ready());
// Now check the service availability in the controller namespace
auto ctrl_2_set_bool_service =
node->create_client<example_interfaces::srv::SetBool>("/ctrl_2/set_bool");
ASSERT_FALSE(ctrl_2_set_bool_service->wait_for_service(std::chrono::seconds(2)));
ASSERT_FALSE(ctrl_2_set_bool_service->service_is_ready());
}

class TestLoadControllerWithoutRobotDescription
: public ControllerManagerFixture<controller_manager::ControllerManager>
{
Expand Down
1 change: 1 addition & 0 deletions doc/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ controller_manager
* The ``--controller-type`` or ``-t`` spawner arg is removed. Now the controller type is defined in the controller configuration file with ``type`` field (`#1639 <https://github.com/ros-controls/ros2_control/pull/1639>`_).
* The ``--namespace`` or ``-n`` spawner arg is deprecated. Now the spawner namespace can be defined using the ROS 2 standard way (`#1640 <https://github.com/ros-controls/ros2_control/pull/1640>`_).
* Added support for the wildcard entries for the controller configuration files (`#1724 <https://github.com/ros-controls/ros2_control/pull/1724>`_).
* The spawner now supports the ``--controller-ros-args`` argument to pass the ROS 2 node arguments to the controller node to be able to remap topics, services and etc (`#1713 <https://github.com/ros-controls/ros2_control/pull/1713>`_).
* The spawner now supports parsing multiple ``-p`` or ``--param-file`` arguments, this should help in loading multiple parameter files for a controller or for multiple controllers (`#1805 <https://github.com/ros-controls/ros2_control/pull/1805>`_).
* ``--switch-timeout`` was added as parameter to the helper scripts ``spawner.py`` and ``unspawner.py``. Useful if controllers cannot be switched immediately, e.g., paused simulations at startup (`#1790 <https://github.com/ros-controls/ros2_control/pull/1790>`_).
* ``ros2_control_node`` can now handle the sim time used by different simulators, when ``use_sim_time`` is set to true (`#1810 <https://github.com/ros-controls/ros2_control/pull/1810>`_).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ struct ControllerInfo

/// List of fallback controller names to be activated if this controller fails.
std::vector<std::string> fallback_controllers_names;

/// Controller node options arguments
std::vector<std::string> node_options_args;
};

} // namespace hardware_interface
Expand Down

0 comments on commit 7bd97e2

Please sign in to comment.