@@ -2169,3 +2169,102 @@ TEST_F(
2169
2169
EXPECT_EQ (controller_interface::return_type::ERROR, switch_future.get ());
2170
2170
}
2171
2171
}
2172
+
2173
+ class TestControllerManagerChainableControllerFailedActivation
2174
+ : public ControllerManagerFixture<controller_manager::ControllerManager>
2175
+ {
2176
+ };
2177
+
2178
+ TEST_F (
2179
+ TestControllerManagerChainableControllerFailedActivation,
2180
+ test_chainable_controllers_failed_activation_and_then_reconfiguring_it)
2181
+ {
2182
+ const std::string test_controller_name = " test_chainable_controller_2" ;
2183
+
2184
+ const auto strictness = controller_manager_msgs::srv::SwitchController::Request::STRICT;
2185
+ controller_interface::InterfaceConfiguration cmd_itfs_cfg;
2186
+ controller_interface::InterfaceConfiguration itfs_cfg;
2187
+ cmd_itfs_cfg.type = controller_interface::interface_configuration_type::INDIVIDUAL;
2188
+ itfs_cfg.type = controller_interface::interface_configuration_type::INDIVIDUAL;
2189
+
2190
+ // controller 4
2191
+ auto test_chainable_controller =
2192
+ std::make_shared<test_chainable_controller::TestChainableController>();
2193
+ cmd_itfs_cfg.names = {" joint1/position" };
2194
+ itfs_cfg.names = {" joint2/velocity" };
2195
+ test_chainable_controller->set_command_interface_configuration (cmd_itfs_cfg);
2196
+ test_chainable_controller->set_state_interface_configuration (itfs_cfg);
2197
+ test_chainable_controller->set_reference_interface_names ({" modified_joint1/position" });
2198
+ test_chainable_controller->set_exported_state_interface_names ({" modified_joint2/velocity" });
2199
+ test_chainable_controller->fail_on_activate = true ;
2200
+
2201
+ cm_->add_controller (
2202
+ test_chainable_controller, test_chainable_controller::TEST_CONTROLLER_NAME,
2203
+ test_chainable_controller::TEST_CONTROLLER_CLASS_NAME);
2204
+
2205
+ EXPECT_EQ (1u , cm_->get_loaded_controllers ().size ());
2206
+ EXPECT_EQ (2 , test_chainable_controller.use_count ());
2207
+ EXPECT_EQ (
2208
+ controller_interface::return_type::OK,
2209
+ cm_->update (time_, rclcpp::Duration::from_seconds (0.01 )));
2210
+
2211
+ EXPECT_EQ (
2212
+ lifecycle_msgs::msg::State::PRIMARY_STATE_UNCONFIGURED,
2213
+ test_chainable_controller->get_lifecycle_state ().id ());
2214
+
2215
+ // configure controllers
2216
+ {
2217
+ ControllerManagerRunner cm_runner (this );
2218
+ EXPECT_EQ (
2219
+ controller_interface::return_type::OK,
2220
+ cm_->configure_controller (test_chainable_controller::TEST_CONTROLLER_NAME));
2221
+ }
2222
+
2223
+ EXPECT_EQ (
2224
+ lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE,
2225
+ test_chainable_controller->get_lifecycle_state ().id ());
2226
+
2227
+ std::vector<std::string> start_controllers = {test_chainable_controller::TEST_CONTROLLER_NAME};
2228
+ std::vector<std::string> stop_controllers = {};
2229
+ {
2230
+ auto switch_future = std::async (
2231
+ std::launch::async, &controller_manager::ControllerManager::switch_controller, cm_,
2232
+ start_controllers, stop_controllers, strictness, true , rclcpp::Duration (0 , 0 ));
2233
+
2234
+ ASSERT_EQ (std::future_status::timeout, switch_future.wait_for (std::chrono::milliseconds (100 )))
2235
+ << " switch_controller should be blocking until next update cycle" ;
2236
+ EXPECT_EQ (
2237
+ controller_interface::return_type::OK,
2238
+ cm_->update (time_, rclcpp::Duration::from_seconds (0.01 )));
2239
+ {
2240
+ ControllerManagerRunner cm_runner (this );
2241
+ EXPECT_EQ (controller_interface::return_type::ERROR, switch_future.get ());
2242
+ }
2243
+ }
2244
+
2245
+ EXPECT_EQ (
2246
+ lifecycle_msgs::msg::State::PRIMARY_STATE_UNCONFIGURED,
2247
+ test_chainable_controller->get_lifecycle_state ().id ());
2248
+ // Now, after reconfiguring it, it should work
2249
+ test_chainable_controller->fail_on_activate = false ;
2250
+
2251
+ {
2252
+ ControllerManagerRunner cm_runner (this );
2253
+ EXPECT_EQ (
2254
+ controller_interface::return_type::OK,
2255
+ cm_->configure_controller (test_chainable_controller::TEST_CONTROLLER_NAME));
2256
+ EXPECT_EQ (
2257
+ lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE,
2258
+ test_chainable_controller->get_lifecycle_state ().id ());
2259
+
2260
+ auto switch_future = std::async (
2261
+ std::launch::async, &controller_manager::ControllerManager::switch_controller, cm_,
2262
+ start_controllers, stop_controllers, strictness, true , rclcpp::Duration (0 , 0 ));
2263
+ ASSERT_EQ (std::future_status::ready, switch_future.wait_for (std::chrono::milliseconds (100 )))
2264
+ << " switch_controller should be blocking until next update cycle" ;
2265
+ EXPECT_EQ (controller_interface::return_type::OK, switch_future.get ());
2266
+ EXPECT_EQ (
2267
+ lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE,
2268
+ test_chainable_controller->get_lifecycle_state ().id ());
2269
+ }
2270
+ }
0 commit comments