@@ -1729,3 +1729,200 @@ TEST_F(TestControllerManagerSrvs, list_hardware_interfaces_srv)
17291729 }
17301730 }
17311731}
1732+
1733+ TEST_F (TestControllerManagerSrvs, activate_chained_controllers_one_by_one)
1734+ {
1735+ // / The simulated controller chaining is:
1736+ // / test_controller_name -> chain_ctrl_2 -> chain_ctrl_1
1737+ // /
1738+ // / NOTE: A -> B signifies that the controller A is utilizing the reference interfaces exported
1739+ // / from the controller B (or) the controller B is utilizing the expected interfaces exported from
1740+ // / the controller A
1741+
1742+ // create server client and request
1743+ rclcpp::executors::SingleThreadedExecutor srv_executor;
1744+ rclcpp::Node::SharedPtr srv_node = std::make_shared<rclcpp::Node>(" srv_client" );
1745+ srv_executor.add_node (srv_node);
1746+ rclcpp::Client<ListControllers>::SharedPtr client =
1747+ srv_node->create_client <ListControllers>(" test_controller_manager/list_controllers" );
1748+ auto request = std::make_shared<ListControllers::Request>();
1749+
1750+ // create set of chained controllers
1751+ static constexpr char TEST_CHAINED_CONTROLLER_1[] = " test_chainable_controller_name_1" ;
1752+ static constexpr char TEST_CHAINED_CONTROLLER_2[] = " test_chainable_controller_name_2" ;
1753+ auto test_chained_controller_1 = std::make_shared<TestChainableController>();
1754+ controller_interface::InterfaceConfiguration chained_cmd_cfg = {
1755+ controller_interface::interface_configuration_type::INDIVIDUAL, {" joint1/position" }};
1756+ controller_interface::InterfaceConfiguration chained_state_cfg = {
1757+ controller_interface::interface_configuration_type::INDIVIDUAL,
1758+ {" joint1/position" , " joint1/velocity" }};
1759+ test_chained_controller_1->set_command_interface_configuration (chained_cmd_cfg);
1760+ test_chained_controller_1->set_state_interface_configuration (chained_state_cfg);
1761+ test_chained_controller_1->set_reference_interface_names ({" joint1/position" , " joint1/velocity" });
1762+
1763+ auto test_chained_controller_2 = std::make_shared<TestChainableController>();
1764+ chained_cmd_cfg = {
1765+ controller_interface::interface_configuration_type::INDIVIDUAL,
1766+ {std::string (TEST_CHAINED_CONTROLLER_1) + " /joint1/position" }};
1767+ test_chained_controller_2->set_command_interface_configuration (chained_cmd_cfg);
1768+ test_chained_controller_2->set_state_interface_configuration (chained_state_cfg);
1769+ test_chained_controller_2->set_reference_interface_names ({" joint1/position" , " joint1/velocity" });
1770+
1771+ // create non-chained controller
1772+ auto test_controller = std::make_shared<TestController>();
1773+ controller_interface::InterfaceConfiguration cmd_cfg = {
1774+ controller_interface::interface_configuration_type::INDIVIDUAL,
1775+ {std::string (TEST_CHAINED_CONTROLLER_2) + " /joint1/position" ,
1776+ std::string (TEST_CHAINED_CONTROLLER_2) + " /joint1/velocity" , " joint2/velocity" }};
1777+ controller_interface::InterfaceConfiguration state_cfg = {
1778+ controller_interface::interface_configuration_type::INDIVIDUAL,
1779+ {" joint1/position" , " joint1/velocity" }};
1780+ test_controller->set_command_interface_configuration (cmd_cfg);
1781+ test_controller->set_state_interface_configuration (state_cfg);
1782+ // add controllers
1783+ cm_->add_controller (
1784+ test_chained_controller_1, TEST_CHAINED_CONTROLLER_1,
1785+ test_chainable_controller::TEST_CONTROLLER_CLASS_NAME);
1786+ cm_->add_controller (
1787+ test_controller, test_controller::TEST_CONTROLLER_NAME,
1788+ test_controller::TEST_CONTROLLER_CLASS_NAME);
1789+ cm_->add_controller (
1790+ test_chained_controller_2, TEST_CHAINED_CONTROLLER_2,
1791+ test_chainable_controller::TEST_CONTROLLER_CLASS_NAME);
1792+ // get controller list before configure
1793+ auto result = call_service_and_wait (*client, request, srv_executor);
1794+ // check chainable controller
1795+ ASSERT_EQ (3u , result->controller .size ());
1796+ ASSERT_EQ (result->controller [0 ].name , TEST_CHAINED_CONTROLLER_1);
1797+ ASSERT_EQ (result->controller [2 ].name , TEST_CHAINED_CONTROLLER_2);
1798+ // check test controller
1799+ ASSERT_EQ (result->controller [1 ].name , " test_controller_name" );
1800+
1801+ // configure controllers
1802+ for (const auto & controller :
1803+ {TEST_CHAINED_CONTROLLER_1, test_controller::TEST_CONTROLLER_NAME,
1804+ TEST_CHAINED_CONTROLLER_2})
1805+ {
1806+ cm_->configure_controller (controller);
1807+ }
1808+
1809+ // get controller list after configure
1810+ result = call_service_and_wait (*client, request, srv_executor);
1811+ ASSERT_EQ (3u , result->controller .size ());
1812+
1813+ // reordered controllers
1814+ ASSERT_EQ (result->controller [0 ].name , " test_controller_name" );
1815+ ASSERT_EQ (result->controller [1 ].name , TEST_CHAINED_CONTROLLER_2);
1816+ ASSERT_EQ (result->controller [2 ].name , TEST_CHAINED_CONTROLLER_1);
1817+
1818+ // activate controllers one by one
1819+ auto res1 = cm_->switch_controller (
1820+ {TEST_CHAINED_CONTROLLER_1}, {},
1821+ controller_manager_msgs::srv::SwitchController::Request::STRICT, true , rclcpp::Duration (0 , 0 ));
1822+ ASSERT_EQ (res1, controller_interface::return_type::OK);
1823+ auto res2 = cm_->switch_controller (
1824+ {TEST_CHAINED_CONTROLLER_2}, {},
1825+ controller_manager_msgs::srv::SwitchController::Request::STRICT, true , rclcpp::Duration (0 , 0 ));
1826+ ASSERT_EQ (res2, controller_interface::return_type::OK);
1827+ auto res3 = cm_->switch_controller (
1828+ {test_controller::TEST_CONTROLLER_NAME}, {},
1829+ controller_manager_msgs::srv::SwitchController::Request::STRICT, true , rclcpp::Duration (0 , 0 ));
1830+ ASSERT_EQ (res3, controller_interface::return_type::OK);
1831+
1832+ RCLCPP_ERROR (srv_node->get_logger (), " Check successful!" );
1833+ }
1834+
1835+ TEST_F (TestControllerManagerSrvs, activate_chained_controllers_all_at_once)
1836+ {
1837+ // / The simulated controller chaining is:
1838+ // / test_controller_name -> chain_ctrl_2 -> chain_ctrl_1
1839+ // /
1840+ // / NOTE: A -> B signifies that the controller A is utilizing the reference interfaces exported
1841+ // / from the controller B (or) the controller B is utilizing the expected interfaces exported from
1842+ // / the controller A
1843+
1844+ // create server client and request
1845+ rclcpp::executors::SingleThreadedExecutor srv_executor;
1846+ rclcpp::Node::SharedPtr srv_node = std::make_shared<rclcpp::Node>(" srv_client" );
1847+ srv_executor.add_node (srv_node);
1848+ rclcpp::Client<ListControllers>::SharedPtr client =
1849+ srv_node->create_client <ListControllers>(" test_controller_manager/list_controllers" );
1850+ auto request = std::make_shared<ListControllers::Request>();
1851+
1852+ // create set of chained controllers
1853+ static constexpr char TEST_CHAINED_CONTROLLER_1[] = " test_chainable_controller_name_1" ;
1854+ static constexpr char TEST_CHAINED_CONTROLLER_2[] = " test_chainable_controller_name_2" ;
1855+ auto test_chained_controller_1 = std::make_shared<TestChainableController>();
1856+ controller_interface::InterfaceConfiguration chained_cmd_cfg = {
1857+ controller_interface::interface_configuration_type::INDIVIDUAL, {" joint1/position" }};
1858+ controller_interface::InterfaceConfiguration chained_state_cfg = {
1859+ controller_interface::interface_configuration_type::INDIVIDUAL,
1860+ {" joint1/position" , " joint1/velocity" }};
1861+ test_chained_controller_1->set_command_interface_configuration (chained_cmd_cfg);
1862+ test_chained_controller_1->set_state_interface_configuration (chained_state_cfg);
1863+ test_chained_controller_1->set_reference_interface_names ({" joint1/position" , " joint1/velocity" });
1864+
1865+ auto test_chained_controller_2 = std::make_shared<TestChainableController>();
1866+ chained_cmd_cfg = {
1867+ controller_interface::interface_configuration_type::INDIVIDUAL,
1868+ {std::string (TEST_CHAINED_CONTROLLER_1) + " /joint1/position" }};
1869+ test_chained_controller_2->set_command_interface_configuration (chained_cmd_cfg);
1870+ test_chained_controller_2->set_state_interface_configuration (chained_state_cfg);
1871+ test_chained_controller_2->set_reference_interface_names ({" joint1/position" , " joint1/velocity" });
1872+
1873+ // create non-chained controller
1874+ auto test_controller = std::make_shared<TestController>();
1875+ controller_interface::InterfaceConfiguration cmd_cfg = {
1876+ controller_interface::interface_configuration_type::INDIVIDUAL,
1877+ {std::string (TEST_CHAINED_CONTROLLER_2) + " /joint1/position" ,
1878+ std::string (TEST_CHAINED_CONTROLLER_2) + " /joint1/velocity" , " joint2/velocity" }};
1879+ controller_interface::InterfaceConfiguration state_cfg = {
1880+ controller_interface::interface_configuration_type::INDIVIDUAL,
1881+ {" joint1/position" , " joint1/velocity" }};
1882+ test_controller->set_command_interface_configuration (cmd_cfg);
1883+ test_controller->set_state_interface_configuration (state_cfg);
1884+ // add controllers
1885+ cm_->add_controller (
1886+ test_chained_controller_1, TEST_CHAINED_CONTROLLER_1,
1887+ test_chainable_controller::TEST_CONTROLLER_CLASS_NAME);
1888+ cm_->add_controller (
1889+ test_controller, test_controller::TEST_CONTROLLER_NAME,
1890+ test_controller::TEST_CONTROLLER_CLASS_NAME);
1891+ cm_->add_controller (
1892+ test_chained_controller_2, TEST_CHAINED_CONTROLLER_2,
1893+ test_chainable_controller::TEST_CONTROLLER_CLASS_NAME);
1894+ // get controller list before configure
1895+ auto result = call_service_and_wait (*client, request, srv_executor);
1896+ // check chainable controller
1897+ ASSERT_EQ (3u , result->controller .size ());
1898+ ASSERT_EQ (result->controller [0 ].name , TEST_CHAINED_CONTROLLER_1);
1899+ ASSERT_EQ (result->controller [2 ].name , TEST_CHAINED_CONTROLLER_2);
1900+ // check test controller
1901+ ASSERT_EQ (result->controller [1 ].name , " test_controller_name" );
1902+
1903+ // configure controllers
1904+ for (const auto & controller :
1905+ {TEST_CHAINED_CONTROLLER_1, test_controller::TEST_CONTROLLER_NAME,
1906+ TEST_CHAINED_CONTROLLER_2})
1907+ {
1908+ cm_->configure_controller (controller);
1909+ }
1910+
1911+ // get controller list after configure
1912+ result = call_service_and_wait (*client, request, srv_executor);
1913+ ASSERT_EQ (3u , result->controller .size ());
1914+
1915+ // reordered controllers
1916+ ASSERT_EQ (result->controller [0 ].name , " test_controller_name" );
1917+ ASSERT_EQ (result->controller [1 ].name , TEST_CHAINED_CONTROLLER_2);
1918+ ASSERT_EQ (result->controller [2 ].name , TEST_CHAINED_CONTROLLER_1);
1919+
1920+ // activate controllers all at once
1921+ auto res = cm_->switch_controller (
1922+ {TEST_CHAINED_CONTROLLER_1, TEST_CHAINED_CONTROLLER_2, test_controller::TEST_CONTROLLER_NAME},
1923+ {}, controller_manager_msgs::srv::SwitchController::Request::STRICT, true ,
1924+ rclcpp::Duration (0 , 0 ));
1925+ ASSERT_EQ (res, controller_interface::return_type::OK);
1926+
1927+ RCLCPP_ERROR (srv_node->get_logger (), " Check successful!" );
1928+ }
0 commit comments