@@ -466,6 +466,195 @@ TEST_P(TrajectoryControllerTestParameterized, hold_on_startup)
466466
467467// Floating-point value comparison threshold
468468const double EPS = 1e-6 ;
469+
470+ /* *
471+ * @brief check if calculated trajectory error is correct with angle wraparound=true
472+ */
473+ TEST_P (TrajectoryControllerTestParameterized, compute_error_angle_wraparound_true)
474+ {
475+ rclcpp::executors::MultiThreadedExecutor executor;
476+ std::vector<rclcpp::Parameter> params = {};
477+ SetUpAndActivateTrajectoryController (
478+ executor, params, true , 0.0 , 1.0 , true /* angle_wraparound */ );
479+
480+ size_t n_joints = joint_names_.size ();
481+
482+ // send msg
483+ constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds (250 );
484+ builtin_interfaces::msg::Duration time_from_start{rclcpp::Duration (FIRST_POINT_TIME)};
485+ // *INDENT-OFF*
486+ std::vector<std::vector<double >> points{
487+ {{3.3 , 4.4 , 6.6 }}, {{7.7 , 8.8 , 9.9 }}, {{10.10 , 11.11 , 12.12 }}};
488+ std::vector<std::vector<double >> points_velocities{
489+ {{0.01 , 0.01 , 0.01 }}, {{0.05 , 0.05 , 0.05 }}, {{0.06 , 0.06 , 0.06 }}};
490+ std::vector<std::vector<double >> points_accelerations{
491+ {{0.1 , 0.1 , 0.1 }}, {{0.5 , 0.5 , 0.5 }}, {{0.6 , 0.6 , 0.6 }}};
492+ // *INDENT-ON*
493+
494+ trajectory_msgs::msg::JointTrajectoryPoint error, current, desired;
495+ current.positions = {points[0 ].begin (), points[0 ].end ()};
496+ current.velocities = {points_velocities[0 ].begin (), points_velocities[0 ].end ()};
497+ current.accelerations = {points_accelerations[0 ].begin (), points_accelerations[0 ].end ()};
498+ traj_controller_->resize_joint_trajectory_point (error, n_joints);
499+
500+ // zero error
501+ desired = current;
502+ for (size_t i = 0 ; i < n_joints; ++i)
503+ {
504+ traj_controller_->testable_compute_error_for_joint (error, i, current, desired);
505+ }
506+ EXPECT_NEAR (error.positions [0 ], 0 ., EPS);
507+ EXPECT_NEAR (error.positions [1 ], 0 ., EPS);
508+ EXPECT_NEAR (error.positions [2 ], 0 ., EPS);
509+ if (
510+ traj_controller_->has_velocity_state_interface () &&
511+ (traj_controller_->has_velocity_command_interface () ||
512+ traj_controller_->has_effort_command_interface ()))
513+ {
514+ // error.velocities[index] = desired.velocities[index] - current.velocities[index];
515+ EXPECT_NEAR (error.velocities [0 ], 0 ., EPS);
516+ EXPECT_NEAR (error.velocities [1 ], 0 ., EPS);
517+ EXPECT_NEAR (error.velocities [2 ], 0 ., EPS);
518+ }
519+ if (
520+ traj_controller_->has_acceleration_state_interface () &&
521+ traj_controller_->has_acceleration_command_interface ())
522+ {
523+ // error.accelerations[index] = desired.accelerations[index] - current.accelerations[index];
524+ EXPECT_NEAR (error.accelerations [0 ], 0 ., EPS);
525+ EXPECT_NEAR (error.accelerations [1 ], 0 ., EPS);
526+ EXPECT_NEAR (error.accelerations [2 ], 0 ., EPS);
527+ }
528+
529+ // angle wraparound of position error
530+ desired.positions [0 ] += 3.0 * M_PI_2;
531+ desired.velocities [0 ] += 1.0 ;
532+ desired.accelerations [0 ] += 1.0 ;
533+ traj_controller_->resize_joint_trajectory_point (error, n_joints);
534+ for (size_t i = 0 ; i < n_joints; ++i)
535+ {
536+ traj_controller_->testable_compute_error_for_joint (error, i, current, desired);
537+ }
538+ EXPECT_NEAR (error.positions [0 ], desired.positions [0 ] - current.positions [0 ] - 2.0 * M_PI, EPS);
539+ EXPECT_NEAR (error.positions [1 ], desired.positions [1 ] - current.positions [1 ], EPS);
540+ EXPECT_NEAR (error.positions [2 ], desired.positions [2 ] - current.positions [2 ], EPS);
541+ if (
542+ traj_controller_->has_velocity_state_interface () &&
543+ (traj_controller_->has_velocity_command_interface () ||
544+ traj_controller_->has_effort_command_interface ()))
545+ {
546+ // error.velocities[index] = desired.velocities[index] - current.velocities[index];
547+ EXPECT_NEAR (error.velocities [0 ], desired.velocities [0 ] - current.velocities [0 ], EPS);
548+ EXPECT_NEAR (error.velocities [1 ], desired.velocities [1 ] - current.velocities [1 ], EPS);
549+ EXPECT_NEAR (error.velocities [2 ], desired.velocities [2 ] - current.velocities [2 ], EPS);
550+ }
551+ if (
552+ traj_controller_->has_acceleration_state_interface () &&
553+ traj_controller_->has_acceleration_command_interface ())
554+ {
555+ // error.accelerations[index] = desired.accelerations[index] - current.accelerations[index];
556+ EXPECT_NEAR (error.accelerations [0 ], desired.accelerations [0 ] - current.accelerations [0 ], EPS);
557+ EXPECT_NEAR (error.accelerations [1 ], desired.accelerations [1 ] - current.accelerations [1 ], EPS);
558+ EXPECT_NEAR (error.accelerations [2 ], desired.accelerations [2 ] - current.accelerations [2 ], EPS);
559+ }
560+
561+ executor.cancel ();
562+ }
563+
564+ /* *
565+ * @brief check if calculated trajectory error is correct with angle wraparound=false
566+ */
567+ TEST_P (TrajectoryControllerTestParameterized, compute_error_angle_wraparound_false)
568+ {
569+ rclcpp::executors::MultiThreadedExecutor executor;
570+ std::vector<rclcpp::Parameter> params = {};
571+ SetUpAndActivateTrajectoryController (
572+ executor, params, true , 0.0 , 1.0 , false /* angle_wraparound */ );
573+
574+ size_t n_joints = joint_names_.size ();
575+
576+ // send msg
577+ constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds (250 );
578+ builtin_interfaces::msg::Duration time_from_start{rclcpp::Duration (FIRST_POINT_TIME)};
579+ // *INDENT-OFF*
580+ std::vector<std::vector<double >> points{
581+ {{3.3 , 4.4 , 6.6 }}, {{7.7 , 8.8 , 9.9 }}, {{10.10 , 11.11 , 12.12 }}};
582+ std::vector<std::vector<double >> points_velocities{
583+ {{0.01 , 0.01 , 0.01 }}, {{0.05 , 0.05 , 0.05 }}, {{0.06 , 0.06 , 0.06 }}};
584+ std::vector<std::vector<double >> points_accelerations{
585+ {{0.1 , 0.1 , 0.1 }}, {{0.5 , 0.5 , 0.5 }}, {{0.6 , 0.6 , 0.6 }}};
586+ // *INDENT-ON*
587+
588+ trajectory_msgs::msg::JointTrajectoryPoint error, current, desired;
589+ current.positions = {points[0 ].begin (), points[0 ].end ()};
590+ current.velocities = {points_velocities[0 ].begin (), points_velocities[0 ].end ()};
591+ current.accelerations = {points_accelerations[0 ].begin (), points_accelerations[0 ].end ()};
592+ traj_controller_->resize_joint_trajectory_point (error, n_joints);
593+
594+ // zero error
595+ desired = current;
596+ for (size_t i = 0 ; i < n_joints; ++i)
597+ {
598+ traj_controller_->testable_compute_error_for_joint (error, i, current, desired);
599+ }
600+ EXPECT_NEAR (error.positions [0 ], 0 ., EPS);
601+ EXPECT_NEAR (error.positions [1 ], 0 ., EPS);
602+ EXPECT_NEAR (error.positions [2 ], 0 ., EPS);
603+ if (
604+ traj_controller_->has_velocity_state_interface () &&
605+ (traj_controller_->has_velocity_command_interface () ||
606+ traj_controller_->has_effort_command_interface ()))
607+ {
608+ // error.velocities[index] = desired.velocities[index] - current.velocities[index];
609+ EXPECT_NEAR (error.velocities [0 ], 0 ., EPS);
610+ EXPECT_NEAR (error.velocities [1 ], 0 ., EPS);
611+ EXPECT_NEAR (error.velocities [2 ], 0 ., EPS);
612+ }
613+ if (
614+ traj_controller_->has_acceleration_state_interface () &&
615+ traj_controller_->has_acceleration_command_interface ())
616+ {
617+ // error.accelerations[index] = desired.accelerations[index] - current.accelerations[index];
618+ EXPECT_NEAR (error.accelerations [0 ], 0 ., EPS);
619+ EXPECT_NEAR (error.accelerations [1 ], 0 ., EPS);
620+ EXPECT_NEAR (error.accelerations [2 ], 0 ., EPS);
621+ }
622+
623+ // no normalization of position error
624+ desired.positions [0 ] += 3.0 * M_PI_4;
625+ desired.velocities [0 ] += 1.0 ;
626+ desired.accelerations [0 ] += 1.0 ;
627+ traj_controller_->resize_joint_trajectory_point (error, n_joints);
628+ for (size_t i = 0 ; i < n_joints; ++i)
629+ {
630+ traj_controller_->testable_compute_error_for_joint (error, i, current, desired);
631+ }
632+ EXPECT_NEAR (error.positions [0 ], desired.positions [0 ] - current.positions [0 ], EPS);
633+ EXPECT_NEAR (error.positions [1 ], desired.positions [1 ] - current.positions [1 ], EPS);
634+ EXPECT_NEAR (error.positions [2 ], desired.positions [2 ] - current.positions [2 ], EPS);
635+ if (
636+ traj_controller_->has_velocity_state_interface () &&
637+ (traj_controller_->has_velocity_command_interface () ||
638+ traj_controller_->has_effort_command_interface ()))
639+ {
640+ // error.velocities[index] = desired.velocities[index] - current.velocities[index];
641+ EXPECT_NEAR (error.velocities [0 ], desired.velocities [0 ] - current.velocities [0 ], EPS);
642+ EXPECT_NEAR (error.velocities [1 ], desired.velocities [1 ] - current.velocities [1 ], EPS);
643+ EXPECT_NEAR (error.velocities [2 ], desired.velocities [2 ] - current.velocities [2 ], EPS);
644+ }
645+ if (
646+ traj_controller_->has_acceleration_state_interface () &&
647+ traj_controller_->has_acceleration_command_interface ())
648+ {
649+ // error.accelerations[index] = desired.accelerations[index] - current.accelerations[index];
650+ EXPECT_NEAR (error.accelerations [0 ], desired.accelerations [0 ] - current.accelerations [0 ], EPS);
651+ EXPECT_NEAR (error.accelerations [1 ], desired.accelerations [1 ] - current.accelerations [1 ], EPS);
652+ EXPECT_NEAR (error.accelerations [2 ], desired.accelerations [2 ] - current.accelerations [2 ], EPS);
653+ }
654+
655+ executor.cancel ();
656+ }
657+
469658/* *
470659 * @brief check if position error of revolute joints are angle_wraparound if not configured so
471660 */
0 commit comments