@@ -554,6 +554,95 @@ TEST_F(JointSaturationLimiterTest, check_desired_jerk_only_cases)
554554 test_limit_enforcing (-1.5 , -0.5 , true );
555555}
556556
557+ TEST_F (JointSaturationLimiterTest, check_all_desired_references_limiting)
558+ {
559+ SetupNode (" joint_saturation_limiter" );
560+ ASSERT_TRUE (Load ());
561+
562+ joint_limits::JointLimits limits;
563+ limits.has_position_limits = true ;
564+ limits.min_position = -5.0 ;
565+ limits.max_position = 5.0 ;
566+ limits.has_velocity_limits = true ;
567+ limits.max_velocity = 1.0 ;
568+ limits.has_acceleration_limits = true ;
569+ limits.max_acceleration = 0.5 ;
570+ limits.has_deceleration_limits = true ;
571+ limits.max_deceleration = 0.25 ;
572+ limits.has_jerk_limits = true ;
573+ limits.max_jerk = 2.0 ;
574+ ASSERT_TRUE (Init (limits));
575+ ASSERT_TRUE (joint_limiter_->configure (last_commanded_state_));
576+
577+ rclcpp::Duration period (1 , 0 ); // 1 second
578+ auto test_limit_enforcing =
579+ [&](
580+ const std::optional<double > & actual_position, const std::optional<double > & actual_velocity,
581+ double desired_position, double desired_velocity, double desired_acceleration,
582+ double desired_jerk, double expected_position, double expected_velocity,
583+ double expected_acceleration, double expected_jerk, bool is_clamped)
584+ {
585+ // Reset the desired and actual states
586+ desired_state_ = {};
587+ actual_state_ = {};
588+ const double act_pos = actual_position.has_value () ? actual_position.value ()
589+ : std::numeric_limits<double >::quiet_NaN ();
590+ const double act_vel = actual_velocity.has_value () ? actual_velocity.value ()
591+ : std::numeric_limits<double >::quiet_NaN ();
592+ SCOPED_TRACE (
593+ " Testing for actual position: " + std::to_string (act_pos) + " , actual velocity: " +
594+ std::to_string (act_vel) + " , desired position: " + std::to_string (desired_position) +
595+ " , desired velocity: " + std::to_string (desired_velocity) + " , desired acceleration: " +
596+ std::to_string (desired_acceleration) + " , desired jerk: " + std::to_string (desired_jerk) +
597+ " , expected position: " + std::to_string (expected_position) +
598+ " , expected velocity: " + std::to_string (expected_velocity) + " , expected acceleration: " +
599+ std::to_string (expected_acceleration) + " , expected jerk: " + std::to_string (expected_jerk) +
600+ " , is clamped: " + std::to_string (is_clamped) +
601+ " for the joint limits : " + limits.to_string ());
602+ if (actual_position.has_value ())
603+ {
604+ actual_state_.position = actual_position.value ();
605+ }
606+ if (actual_velocity.has_value ())
607+ {
608+ actual_state_.velocity = actual_velocity.value ();
609+ }
610+ desired_state_.position = desired_position;
611+ desired_state_.velocity = desired_velocity;
612+ desired_state_.acceleration = desired_acceleration;
613+ desired_state_.jerk = desired_jerk;
614+ ASSERT_EQ (is_clamped, joint_limiter_->enforce (actual_state_, desired_state_, period));
615+ EXPECT_NEAR (desired_state_.position .value (), expected_position, COMMON_THRESHOLD);
616+ EXPECT_NEAR (desired_state_.velocity .value (), expected_velocity, COMMON_THRESHOLD);
617+ EXPECT_NEAR (desired_state_.acceleration .value (), expected_acceleration, COMMON_THRESHOLD);
618+ EXPECT_NEAR (desired_state_.jerk .value (), expected_jerk, COMMON_THRESHOLD);
619+ };
620+
621+ // Test cases when there is no actual position and velocity
622+ // Desired position and velocity affected due to the acceleration limits
623+ test_limit_enforcing (std::nullopt , std::nullopt , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , false );
624+ test_limit_enforcing (std::nullopt , std::nullopt , 6.0 , 2.0 , 1.0 , 0.5 , 0.5 , 0.5 , 0.5 , 0.5 , true );
625+ test_limit_enforcing (std::nullopt , std::nullopt , 6.0 , 2.0 , 1.0 , 0.5 , 1.0 , 1.0 , 0.5 , 0.5 , true );
626+ test_limit_enforcing (std::nullopt , std::nullopt , 6.0 , 2.0 , 1.0 , 0.5 , 1.5 , 1.0 , 0.5 , 0.5 , true );
627+ test_limit_enforcing (std::nullopt , std::nullopt , 6.0 , 2.0 , 1.0 , 0.5 , 2.0 , 1.0 , 0.5 , 0.5 , true );
628+ test_limit_enforcing (std::nullopt , std::nullopt , 3.0 , 2.0 , 1.0 , 0.5 , 2.5 , 1.0 , 0.5 , 0.5 , true );
629+ test_limit_enforcing (std::nullopt , std::nullopt , 3.0 , 2.0 , 1.0 , 0.5 , 3.0 , 1.0 , 0.5 , 0.5 , true );
630+ test_limit_enforcing (std::nullopt , std::nullopt , 3.0 , 1.0 , 0.5 , 0.5 , 3.0 , 1.0 , 0.5 , 0.5 , false );
631+
632+ // Now enforce the limits with actual position and velocity
633+ ASSERT_TRUE (Init (limits));
634+ // Desired position and velocity affected due to the acceleration limits
635+ test_limit_enforcing (0.5 , 0.0 , 6.0 , 0.0 , 0.0 , 0.0 , 1.0 , 0.0 , 0.0 , 0.0 , true );
636+ test_limit_enforcing (1.0 , 0.0 , 6.0 , 0.0 , 0.0 , 0.0 , 1.5 , 0.0 , 0.0 , 0.0 , true );
637+ test_limit_enforcing (1.0 , 0.0 , 6.0 , 0.0 , 0.0 , 0.0 , 2.0 , 0.0 , 0.0 , 0.0 , true );
638+ test_limit_enforcing (1.0 , 0.0 , -6.0 , 0.0 , 0.0 , 0.0 , 1.5 , 0.0 , 0.0 , 0.0 , true );
639+ test_limit_enforcing (2.0 , 0.0 , 6.0 , 2.0 , 1.0 , 0.5 , 2.0 , 0.5 , 0.5 , 0.5 , true );
640+ test_limit_enforcing (2.0 , 0.5 , 6.0 , 2.0 , 1.0 , 0.5 , 3.0 , 1.0 , 0.5 , 0.5 , true );
641+ test_limit_enforcing (3.0 , 0.5 , 6.0 , 2.0 , 1.0 , 0.5 , 4.0 , 1.0 , 0.5 , 0.5 , true );
642+ test_limit_enforcing (4.0 , 0.5 , 6.0 , 2.0 , 1.0 , 0.5 , 5.0 , 1.0 , 0.5 , 0.5 , true );
643+ test_limit_enforcing (5.0 , 0.5 , 6.0 , 2.0 , 1.0 , 0.5 , 5.0 , 0.0 , 0.5 , 0.5 , true );
644+ }
645+
557646int main (int argc, char ** argv)
558647{
559648 ::testing::InitGoogleTest (&argc, argv);
0 commit comments