@@ -565,6 +565,147 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_not_normalized)
565
565
executor.cancel ();
566
566
}
567
567
568
+ /* *
569
+ * @brief cmd_timeout must be greater than constraints.goal_time
570
+ */
571
+ TEST_P (TrajectoryControllerTestParameterized, accept_correct_cmd_timeout)
572
+ {
573
+ rclcpp::executors::MultiThreadedExecutor executor;
574
+ // zero is default value, just for demonstration
575
+ double cmd_timeout = 3.0 ;
576
+ rclcpp::Parameter cmd_timeout_parameter (" cmd_timeout" , cmd_timeout);
577
+ rclcpp::Parameter goal_time_parameter (" constraints.goal_time" , 2.0 );
578
+ SetUpAndActivateTrajectoryController (
579
+ executor, {cmd_timeout_parameter, goal_time_parameter}, false );
580
+
581
+ EXPECT_DOUBLE_EQ (cmd_timeout, traj_controller_->get_cmd_timeout ());
582
+ }
583
+
584
+ /* *
585
+ * @brief cmd_timeout must be greater than constraints.goal_time
586
+ */
587
+ TEST_P (TrajectoryControllerTestParameterized, decline_false_cmd_timeout)
588
+ {
589
+ rclcpp::executors::MultiThreadedExecutor executor;
590
+ // zero is default value, just for demonstration
591
+ rclcpp::Parameter cmd_timeout_parameter (" cmd_timeout" , 1.0 );
592
+ rclcpp::Parameter goal_time_parameter (" constraints.goal_time" , 2.0 );
593
+ SetUpAndActivateTrajectoryController (
594
+ executor, {cmd_timeout_parameter, goal_time_parameter}, false );
595
+
596
+ EXPECT_DOUBLE_EQ (0.0 , traj_controller_->get_cmd_timeout ());
597
+ }
598
+
599
+ /* *
600
+ * @brief check if no timeout is triggered
601
+ */
602
+ TEST_P (TrajectoryControllerTestParameterized, no_timeout)
603
+ {
604
+ rclcpp::executors::MultiThreadedExecutor executor;
605
+ // zero is default value, just for demonstration
606
+ rclcpp::Parameter cmd_timeout_parameter (" cmd_timeout" , 0.0 );
607
+ SetUpAndActivateTrajectoryController (executor, {cmd_timeout_parameter}, false );
608
+ subscribeToState ();
609
+
610
+ size_t n_joints = joint_names_.size ();
611
+
612
+ // send msg
613
+ constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds (250 );
614
+ builtin_interfaces::msg::Duration time_from_start{rclcpp::Duration (FIRST_POINT_TIME)};
615
+ // *INDENT-OFF*
616
+ std::vector<std::vector<double >> points{
617
+ {{3.3 , 4.4 , 6.6 }}, {{7.7 , 8.8 , 9.9 }}, {{10.10 , 11.11 , 12.12 }}};
618
+ std::vector<std::vector<double >> points_velocities{
619
+ {{0.01 , 0.01 , 0.01 }}, {{0.05 , 0.05 , 0.05 }}, {{0.06 , 0.06 , 0.06 }}};
620
+ // *INDENT-ON*
621
+ publish (time_from_start, points, rclcpp::Time (0 , 0 , RCL_STEADY_TIME), {}, points_velocities);
622
+ traj_controller_->wait_for_trajectory (executor);
623
+
624
+ // first update
625
+ updateController (rclcpp::Duration (FIRST_POINT_TIME) * 4 );
626
+
627
+ // Spin to receive latest state
628
+ executor.spin_some ();
629
+ auto state_msg = getState ();
630
+ ASSERT_TRUE (state_msg);
631
+
632
+ // has the msg the correct vector sizes?
633
+ EXPECT_EQ (n_joints, state_msg->reference .positions .size ());
634
+
635
+ // is the trajectory still active?
636
+ EXPECT_TRUE (traj_controller_->has_active_traj ());
637
+ // should still hold the points from above
638
+ EXPECT_TRUE (traj_controller_->has_nontrivial_traj ());
639
+ EXPECT_NEAR (state_msg->reference .positions [0 ], points.at (2 ).at (0 ), 1e-2 );
640
+ EXPECT_NEAR (state_msg->reference .positions [1 ], points.at (2 ).at (1 ), 1e-2 );
641
+ EXPECT_NEAR (state_msg->reference .positions [2 ], points.at (2 ).at (2 ), 1e-2 );
642
+ // value of velocities is different from above due to spline interpolation
643
+ EXPECT_GT (state_msg->reference .velocities [0 ], 0.0 );
644
+ EXPECT_GT (state_msg->reference .velocities [1 ], 0.0 );
645
+ EXPECT_GT (state_msg->reference .velocities [2 ], 0.0 );
646
+
647
+ executor.cancel ();
648
+ }
649
+
650
+ /* *
651
+ * @brief check if timeout is triggered
652
+ */
653
+ TEST_P (TrajectoryControllerTestParameterized, timeout)
654
+ {
655
+ rclcpp::executors::MultiThreadedExecutor executor;
656
+ constexpr double cmd_timeout = 0.1 ;
657
+ rclcpp::Parameter cmd_timeout_parameter (" cmd_timeout" , cmd_timeout);
658
+ double kp = 1.0 ; // activate feedback control for testing velocity/effort PID
659
+ SetUpAndActivateTrajectoryController (executor, {cmd_timeout_parameter}, false , kp);
660
+ subscribeToState ();
661
+
662
+ // send msg
663
+ constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds (250 );
664
+ builtin_interfaces::msg::Duration time_from_start{rclcpp::Duration (FIRST_POINT_TIME)};
665
+ // *INDENT-OFF*
666
+ std::vector<std::vector<double >> points{
667
+ {{3.3 , 4.4 , 6.6 }}, {{7.7 , 8.8 , 9.9 }}, {{10.10 , 11.11 , 12.12 }}};
668
+ std::vector<std::vector<double >> points_velocities{
669
+ {{0.01 , 0.01 , 0.01 }}, {{0.05 , 0.05 , 0.05 }}, {{0.06 , 0.06 , 0.06 }}};
670
+ // *INDENT-ON*
671
+
672
+ publish (time_from_start, points, rclcpp::Time (0 , 0 , RCL_STEADY_TIME), {}, points_velocities);
673
+ traj_controller_->wait_for_trajectory (executor);
674
+
675
+ // update until end of trajectory -> no timeout should have occurred
676
+ updateController (rclcpp::Duration (FIRST_POINT_TIME) * 3 );
677
+ // is a trajectory active?
678
+ EXPECT_TRUE (traj_controller_->has_active_traj ());
679
+ // should have the trajectory with three points
680
+ EXPECT_TRUE (traj_controller_->has_nontrivial_traj ());
681
+
682
+ // update until timeout should have happened
683
+ updateController (rclcpp::Duration (FIRST_POINT_TIME));
684
+
685
+ // Spin to receive latest state
686
+ executor.spin_some ();
687
+ auto state_msg = getState ();
688
+ ASSERT_TRUE (state_msg);
689
+
690
+ // after timeout, set_hold_position adds a new trajectory
691
+ // is a trajectory active?
692
+ EXPECT_TRUE (traj_controller_->has_active_traj ());
693
+ // should be not more than one point now (from hold position)
694
+ EXPECT_FALSE (traj_controller_->has_nontrivial_traj ());
695
+ // should hold last position with zero velocity
696
+ if (traj_controller_->has_position_command_interface ())
697
+ {
698
+ expectHoldingPoint (points.at (2 ));
699
+ }
700
+ else
701
+ {
702
+ // no integration to position state interface from velocity/acceleration
703
+ expectHoldingPoint (INITIAL_POS_JOINTS);
704
+ }
705
+
706
+ executor.cancel ();
707
+ }
708
+
568
709
/* *
569
710
* @brief check if position error of revolute joints are normalized if configured so
570
711
*/
0 commit comments