@@ -969,6 +969,91 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_allow_nonzero_velocity_at_tr
969
969
EXPECT_TRUE (gh_future.get ());
970
970
}
971
971
972
+ TEST_P (TestTrajectoryActionsTestParameterized, deactivate_controller_aborts_action)
973
+ {
974
+ // deactivate velocity tolerance
975
+ std::vector<rclcpp::Parameter> params = {
976
+ rclcpp::Parameter (" constraints.stopped_velocity_tolerance" , 0.0 )};
977
+ SetUpExecutor (params, false , 1.0 , 0.0 );
978
+
979
+ // We use our own hardware thread here, as we want to make sure the controller is deactivated
980
+ auto controller_thread = std::thread (
981
+ [&]()
982
+ {
983
+ // controller hardware cycle update loop
984
+ auto clock = rclcpp::Clock (RCL_STEADY_TIME);
985
+ auto now_time = clock.now ();
986
+ auto last_time = now_time;
987
+ rclcpp::Duration wait = rclcpp::Duration::from_seconds (0.5 );
988
+ auto end_time = last_time + wait;
989
+ while (now_time < end_time)
990
+ {
991
+ now_time = now_time + rclcpp::Duration::from_seconds (0.01 );
992
+ traj_controller_->update (now_time, now_time - last_time);
993
+ last_time = now_time;
994
+ std::this_thread::sleep_for (std::chrono::milliseconds (10 ));
995
+ }
996
+ RCLCPP_INFO (node_->get_logger (), " Controller hardware thread finished" );
997
+ traj_controller_->get_node ()->deactivate ();
998
+ std::this_thread::sleep_for (std::chrono::milliseconds (100 ));
999
+ });
1000
+
1001
+ std::shared_future<typename GoalHandle::SharedPtr> gh_future;
1002
+ // send goal
1003
+ std::vector<double > point_positions{1.0 , 2.0 , 3.0 };
1004
+ {
1005
+ std::vector<JointTrajectoryPoint> points;
1006
+ JointTrajectoryPoint point;
1007
+ point.time_from_start = rclcpp::Duration::from_seconds (2.5 );
1008
+ point.positions = point_positions;
1009
+
1010
+ points.push_back (point);
1011
+
1012
+ gh_future = sendActionGoal (points, 1.0 , goal_options_);
1013
+ }
1014
+
1015
+ controller_thread.join ();
1016
+
1017
+ EXPECT_TRUE (gh_future.get ());
1018
+ EXPECT_EQ (rclcpp_action::ResultCode::ABORTED, common_resultcode_);
1019
+
1020
+ auto state_ref = traj_controller_->get_state_reference ();
1021
+ auto state = traj_controller_->get_state_feedback ();
1022
+
1023
+ // run an update
1024
+ updateControllerAsync (rclcpp::Duration::from_seconds (0.01 ));
1025
+
1026
+ // There will be no active trajectory upon deactivation, so we can't use the expectCommandPoint
1027
+ // method.
1028
+ if (traj_controller_->has_position_command_interface ())
1029
+ {
1030
+ EXPECT_NEAR (state_ref.positions .at (0 ), joint_pos_[0 ], COMMON_THRESHOLD);
1031
+ EXPECT_NEAR (state_ref.positions .at (1 ), joint_pos_[1 ], COMMON_THRESHOLD);
1032
+ EXPECT_NEAR (state_ref.positions .at (2 ), joint_pos_[2 ], COMMON_THRESHOLD);
1033
+ }
1034
+
1035
+ if (traj_controller_->has_velocity_command_interface ())
1036
+ {
1037
+ EXPECT_EQ (0.0 , joint_vel_[0 ]);
1038
+ EXPECT_EQ (0.0 , joint_vel_[1 ]);
1039
+ EXPECT_EQ (0.0 , joint_vel_[2 ]);
1040
+ }
1041
+
1042
+ if (traj_controller_->has_acceleration_command_interface ())
1043
+ {
1044
+ EXPECT_EQ (0.0 , joint_acc_[0 ]);
1045
+ EXPECT_EQ (0.0 , joint_acc_[1 ]);
1046
+ EXPECT_EQ (0.0 , joint_acc_[2 ]);
1047
+ }
1048
+
1049
+ if (traj_controller_->has_effort_command_interface ())
1050
+ {
1051
+ EXPECT_EQ (0.0 , joint_eff_[0 ]);
1052
+ EXPECT_EQ (0.0 , joint_eff_[1 ]);
1053
+ EXPECT_EQ (0.0 , joint_eff_[2 ]);
1054
+ }
1055
+ }
1056
+
972
1057
// position controllers
973
1058
INSTANTIATE_TEST_SUITE_P (
974
1059
PositionTrajectoryControllersActions, TestTrajectoryActionsTestParameterized,
0 commit comments