Skip to content

Commit 9bf2969

Browse files
committed
Fix open-loop timeout behavior and add test coverage
- Reset last_linear_velocity_ and last_angular_velocity_ to 0.0 when reference interfaces are NaN (indicating a timeout) in update_and_write_commands. - Previously, the controller persisted the last valid velocity during a timeout in open-loop mode, causing unsafe behavior. - Added test_open_loop_update_timeout to verify that velocities reset to zero upon timeout. - Added necessary FRIEND_TEST macro to test_steering_controllers_library.hpp to enable the test case.
1 parent c1b2281 commit 9bf2969

File tree

3 files changed

+39
-13
lines changed

3 files changed

+39
-13
lines changed

steering_controllers_library/src/steering_controllers_library.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,10 +524,16 @@ controller_interface::return_type SteeringControllersLibrary::update_and_write_c
524524
{
525525
last_linear_velocity_ = reference_interfaces_[0];
526526
}
527+
else{
528+
last_linear_velocity_ = 0.0;
529+
}
527530
if (std::isfinite(reference_interfaces_[1]))
528531
{
529532
last_angular_velocity_ = reference_interfaces_[1];
530533
}
534+
else{
535+
last_angular_velocity_ = 0.0;
536+
}
531537
update_odometry(period);
532538

533539
// MOVE ROBOT

steering_controllers_library/test/test_steering_controllers_library.cpp

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ TEST_F(SteeringControllersLibraryTest, test_velocity_feedback_ref_timeout)
388388

389389
TEST_F(SteeringControllersLibraryTest, test_open_loop_update_ignore_nan_vals)
390390
{
391-
// 1. Setup Options
391+
// Setup Options
392392
auto node_options = controller_->define_custom_node_options();
393393
node_options.append_parameter_override("open_loop", true);
394394
node_options.append_parameter_override(
@@ -397,61 +397,80 @@ TEST_F(SteeringControllersLibraryTest, test_open_loop_update_ignore_nan_vals)
397397
"steering_joints_names", std::vector<std::string>{"steer_left", "steer_right"});
398398
SetUpController("test_steering_controllers_library", node_options);
399399

400-
// 2. Lifecycle
401400
ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS);
402401
controller_->set_chained_mode(false);
403402
ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS);
404403

405-
// 3. The Publicist Hack (Unlock Input AND Output)
406404
struct Publicist : public TestableSteeringControllersLibrary
407405
{
408-
// Unlock input buffer
409406
using steering_controllers_library::SteeringControllersLibrary::input_ref_;
410-
// Unlock the wheels (Output)
411407
using controller_interface::ControllerInterfaceBase::command_interfaces_;
412408
};
413409
auto * pub_controller = static_cast<Publicist *>(controller_.get());
414410

415-
// 4. Send Valid Command (1.5 m/s)
416411
auto command_msg = ControllerReferenceMsg();
417412
command_msg.header.stamp = controller_->get_node()->now();
418413
command_msg.twist.linear.x = 1.5;
419414
command_msg.twist.angular.z = 0.0;
420415

421416
pub_controller->input_ref_.set(command_msg);
422417

423-
// 5. Force Update
424418
controller_->update_reference_from_subscribers(
425419
controller_->get_node()->now(), rclcpp::Duration::from_seconds(0.01));
426420
controller_->update_and_write_commands(
427421
controller_->get_node()->now(), rclcpp::Duration::from_seconds(0.01));
428422

429-
// 6. CHECK THE WHEELS
430-
// FIX: Use .get_optional().value() (This is how ROS 2 reads values back)
431423
double wheel_speed_1 = pub_controller->command_interfaces_[0].get_optional().value();
432424

433-
// It should be moving
434425
ASSERT_GT(wheel_speed_1, 0.1);
435426

436-
// 7. Send NaN Command
437427
auto nan_msg = ControllerReferenceMsg();
438428
nan_msg.header.stamp = controller_->get_node()->now();
439429
nan_msg.twist.linear.x = std::numeric_limits<double>::quiet_NaN();
440430
nan_msg.twist.angular.z = std::numeric_limits<double>::quiet_NaN();
441431

442432
pub_controller->input_ref_.set(nan_msg);
443433

444-
// 8. Force Update Again
445434
controller_->update_reference_from_subscribers(
446435
controller_->get_node()->now(), rclcpp::Duration::from_seconds(0.01));
447436
controller_->update_and_write_commands(
448437
controller_->get_node()->now(), rclcpp::Duration::from_seconds(0.01));
449438

450-
// 9. THE PROOF
451439
// The wheel speed should stay exactly the same
452440
EXPECT_DOUBLE_EQ(pub_controller->command_interfaces_[0].get_optional().value(), 0.0);
453441
}
454442

443+
TEST_F(SteeringControllersLibraryTest, test_open_loop_update_timeout)
444+
{
445+
// 1. SETUP WITH OPTIONS
446+
auto node_options = controller_->define_custom_node_options();
447+
node_options.append_parameter_override("open_loop", true);
448+
node_options.append_parameter_override("reference_timeout", 1.0);
449+
450+
SetUpController("test_steering_controllers_library", node_options);
451+
452+
ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS);
453+
controller_->set_chained_mode(false); // We are testing standalone mode
454+
ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS);
455+
456+
ControllerReferenceMsg msg;
457+
msg.header.stamp = controller_->get_node()->now();
458+
msg.twist.linear.x = 5.0;
459+
msg.twist.angular.z = 0.0;
460+
controller_->input_ref_.set(msg);
461+
462+
463+
controller_->update(controller_->get_node()->now(), rclcpp::Duration::from_seconds(0.1));
464+
465+
EXPECT_DOUBLE_EQ(controller_->last_linear_velocity_, 5.0);
466+
467+
rclcpp::Time future_time = controller_->get_node()->now() + rclcpp::Duration::from_seconds(2.0);
468+
469+
controller_->update(future_time, rclcpp::Duration::from_seconds(0.1));
470+
471+
EXPECT_DOUBLE_EQ(controller_->last_linear_velocity_, 0.0);
472+
}
473+
455474
int main(int argc, char ** argv)
456475
{
457476
::testing::InitGoogleTest(&argc, argv);

steering_controllers_library/test/test_steering_controllers_library.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ class TestableSteeringControllersLibrary
7676
FRIEND_TEST(SteeringControllersLibraryTest, configure_succeeds_tf_tilde_prefix_set_namespace);
7777
FRIEND_TEST(SteeringControllersLibraryTest, test_position_feedback_ref_timeout);
7878
FRIEND_TEST(SteeringControllersLibraryTest, test_velocity_feedback_ref_timeout);
79+
FRIEND_TEST(SteeringControllersLibraryTest, test_open_loop_update_timeout);
7980

8081
public:
8182
controller_interface::CallbackReturn on_configure(

0 commit comments

Comments
 (0)