@@ -1216,8 +1216,12 @@ TEST_F(TestComponentParser, successfully_parse_valid_urdf_system_and_disabled_in
12161216 EXPECT_FALSE (hardware_info.limits .at (" joint2" ).has_acceleration_limits );
12171217 EXPECT_FALSE (hardware_info.limits .at (" joint2" ).has_deceleration_limits );
12181218 EXPECT_FALSE (hardware_info.limits .at (" joint2" ).has_jerk_limits );
1219- EXPECT_THAT (hardware_info.limits .at (" joint2" ).max_velocity , DoubleNear (0.2 , 1e-5 ));
1220- EXPECT_THAT (hardware_info.limits .at (" joint2" ).max_effort , DoubleNear (0.1 , 1e-5 ));
1219+ EXPECT_THAT (
1220+ hardware_info.limits .at (" joint2" ).max_velocity ,
1221+ DoubleNear (std::numeric_limits<double >::max (), 1e-5 ));
1222+ EXPECT_THAT (
1223+ hardware_info.limits .at (" joint2" ).max_effort ,
1224+ DoubleNear (std::numeric_limits<double >::max (), 1e-5 ));
12211225 EXPECT_THAT (hardware_info.soft_limits .at (" joint2" ).max_position , DoubleNear (0.5 , 1e-5 ));
12221226 EXPECT_THAT (hardware_info.soft_limits .at (" joint2" ).min_position , DoubleNear (-1.5 , 1e-5 ));
12231227 EXPECT_THAT (hardware_info.soft_limits .at (" joint2" ).k_position , DoubleNear (10.0 , 1e-5 ));
@@ -1339,8 +1343,12 @@ TEST_F(TestComponentParser, successfully_parse_valid_urdf_system_and_unavailable
13391343 EXPECT_FALSE (hardware_info.limits .at (" joint2" ).has_acceleration_limits );
13401344 EXPECT_FALSE (hardware_info.limits .at (" joint2" ).has_deceleration_limits );
13411345 EXPECT_FALSE (hardware_info.limits .at (" joint2" ).has_jerk_limits );
1342- EXPECT_THAT (hardware_info.limits .at (" joint2" ).max_velocity , DoubleNear (0.2 , 1e-5 ));
1343- EXPECT_THAT (hardware_info.limits .at (" joint2" ).max_effort , DoubleNear (0.1 , 1e-5 ));
1346+ EXPECT_THAT (
1347+ hardware_info.limits .at (" joint2" ).max_velocity ,
1348+ DoubleNear (std::numeric_limits<double >::max (), 1e-5 ));
1349+ EXPECT_THAT (
1350+ hardware_info.limits .at (" joint2" ).max_effort ,
1351+ DoubleNear (std::numeric_limits<double >::max (), 1e-5 ));
13441352
13451353 EXPECT_TRUE (hardware_info.limits .at (" joint3" ).has_position_limits );
13461354 EXPECT_THAT (hardware_info.limits .at (" joint3" ).min_position , DoubleNear (-M_PI, 1e-5 ));
@@ -1925,6 +1933,152 @@ TEST_F(TestComponentParser, parse_gpio_command_interface_descriptions_from_hardw
19251933 EXPECT_EQ (gpio_state_descriptions[1 ].get_name (), " flange_vacuum/vacuum" );
19261934}
19271935
1936+ TEST_F (TestComponentParser, successfully_parse_urdf_with_disabled_limits)
1937+ {
1938+ const auto urdf_to_test =
1939+ std::string (ros2_control_test_assets::urdf_head) +
1940+ std::string (ros2_control_test_assets::hardware_resources_with_disabled_limits) +
1941+ std::string (ros2_control_test_assets::urdf_tail);
1942+
1943+ std::vector<hardware_interface::HardwareInfo> hw_info;
1944+ ASSERT_NO_THROW (hw_info = parse_control_resources_from_urdf (urdf_to_test));
1945+ ASSERT_THAT (hw_info, SizeIs (3 ));
1946+
1947+ // First hardware: TestActuatorHardware with joint1
1948+ // joint1 has <limits enable="false"/> at the joint level, so all interfaces should have
1949+ // enable_limits=false
1950+ EXPECT_EQ (hw_info[0 ].name , " TestActuatorHardware" );
1951+ EXPECT_EQ (hw_info[0 ].type , " actuator" );
1952+ ASSERT_THAT (hw_info[0 ].joints , SizeIs (1 ));
1953+ EXPECT_EQ (hw_info[0 ].joints [0 ].name , " joint1" );
1954+
1955+ // All command interfaces on joint1 should have enable_limits=false
1956+ ASSERT_THAT (hw_info[0 ].joints [0 ].command_interfaces , SizeIs (4 ));
1957+ EXPECT_EQ (hw_info[0 ].joints [0 ].command_interfaces [0 ].name , HW_IF_POSITION);
1958+ EXPECT_FALSE (hw_info[0 ].joints [0 ].command_interfaces [0 ].enable_limits );
1959+ EXPECT_EQ (hw_info[0 ].joints [0 ].command_interfaces [1 ].name , HW_IF_VELOCITY);
1960+ EXPECT_FALSE (hw_info[0 ].joints [0 ].command_interfaces [1 ].enable_limits );
1961+ EXPECT_EQ (hw_info[0 ].joints [0 ].command_interfaces [2 ].name , HW_IF_EFFORT);
1962+ EXPECT_FALSE (hw_info[0 ].joints [0 ].command_interfaces [2 ].enable_limits );
1963+ EXPECT_EQ (hw_info[0 ].joints [0 ].command_interfaces [3 ].name , " max_velocity" );
1964+ EXPECT_FALSE (hw_info[0 ].joints [0 ].command_interfaces [3 ].enable_limits );
1965+
1966+ // All state interfaces on joint1 should have enable_limits=false
1967+ ASSERT_THAT (hw_info[0 ].joints [0 ].state_interfaces , SizeIs (2 ));
1968+ EXPECT_EQ (hw_info[0 ].joints [0 ].state_interfaces [0 ].name , HW_IF_POSITION);
1969+ EXPECT_FALSE (hw_info[0 ].joints [0 ].state_interfaces [0 ].enable_limits );
1970+ EXPECT_EQ (hw_info[0 ].joints [0 ].state_interfaces [1 ].name , HW_IF_VELOCITY);
1971+ EXPECT_FALSE (hw_info[0 ].joints [0 ].state_interfaces [1 ].enable_limits );
1972+
1973+ // Verify that joint1 limits are disabled (has_*_limits should be false)
1974+ ASSERT_THAT (hw_info[0 ].limits , SizeIs (1 ));
1975+ EXPECT_FALSE (hw_info[0 ].limits .at (" joint1" ).has_position_limits );
1976+ EXPECT_FALSE (hw_info[0 ].limits .at (" joint1" ).has_velocity_limits );
1977+ EXPECT_FALSE (hw_info[0 ].limits .at (" joint1" ).has_effort_limits );
1978+ EXPECT_FALSE (hw_info[0 ].limits .at (" joint1" ).has_acceleration_limits );
1979+ EXPECT_FALSE (hw_info[0 ].limits .at (" joint1" ).has_deceleration_limits );
1980+ EXPECT_FALSE (hw_info[0 ].limits .at (" joint1" ).has_jerk_limits );
1981+
1982+ // Second hardware: TestSensorHardware - no limits element, so enable_limits should be true
1983+ // (default)
1984+ EXPECT_EQ (hw_info[1 ].name , " TestSensorHardware" );
1985+ EXPECT_EQ (hw_info[1 ].type , " sensor" );
1986+ ASSERT_THAT (hw_info[1 ].sensors , SizeIs (1 ));
1987+ EXPECT_EQ (hw_info[1 ].sensors [0 ].name , " sensor1" );
1988+ ASSERT_THAT (hw_info[1 ].sensors [0 ].state_interfaces , SizeIs (1 ));
1989+ EXPECT_EQ (hw_info[1 ].sensors [0 ].state_interfaces [0 ].name , HW_IF_VELOCITY);
1990+ EXPECT_TRUE (hw_info[1 ].sensors [0 ].state_interfaces [0 ].enable_limits );
1991+
1992+ // Third hardware: TestSystemHardware with joint2 and joint3
1993+ EXPECT_EQ (hw_info[2 ].name , " TestSystemHardware" );
1994+ EXPECT_EQ (hw_info[2 ].type , " system" );
1995+ ASSERT_THAT (hw_info[2 ].joints , SizeIs (2 ));
1996+
1997+ // joint2 has <limits enable="false"/> at the joint level, so all interfaces should have
1998+ // enable_limits=false
1999+ EXPECT_EQ (hw_info[2 ].joints [0 ].name , " joint2" );
2000+ ASSERT_THAT (hw_info[2 ].joints [0 ].command_interfaces , SizeIs (2 ));
2001+ EXPECT_EQ (hw_info[2 ].joints [0 ].command_interfaces [0 ].name , HW_IF_VELOCITY);
2002+ EXPECT_FALSE (hw_info[2 ].joints [0 ].command_interfaces [0 ].enable_limits );
2003+ EXPECT_EQ (hw_info[2 ].joints [0 ].command_interfaces [1 ].name , " max_acceleration" );
2004+ EXPECT_FALSE (hw_info[2 ].joints [0 ].command_interfaces [1 ].enable_limits );
2005+
2006+ ASSERT_THAT (hw_info[2 ].joints [0 ].state_interfaces , SizeIs (3 ));
2007+ EXPECT_EQ (hw_info[2 ].joints [0 ].state_interfaces [0 ].name , HW_IF_POSITION);
2008+ EXPECT_FALSE (hw_info[2 ].joints [0 ].state_interfaces [0 ].enable_limits );
2009+ EXPECT_EQ (hw_info[2 ].joints [0 ].state_interfaces [1 ].name , HW_IF_VELOCITY);
2010+ EXPECT_FALSE (hw_info[2 ].joints [0 ].state_interfaces [1 ].enable_limits );
2011+ EXPECT_EQ (hw_info[2 ].joints [0 ].state_interfaces [2 ].name , HW_IF_ACCELERATION);
2012+ EXPECT_FALSE (hw_info[2 ].joints [0 ].state_interfaces [2 ].enable_limits );
2013+
2014+ // joint3 has <limits enable="false"/> only on the position command interface
2015+ // Other interfaces should have enable_limits=true (default)
2016+ EXPECT_EQ (hw_info[2 ].joints [1 ].name , " joint3" );
2017+ ASSERT_THAT (hw_info[2 ].joints [1 ].command_interfaces , SizeIs (2 ));
2018+ // Position command interface should have enable_limits=false (explicitly set)
2019+ EXPECT_EQ (hw_info[2 ].joints [1 ].command_interfaces [0 ].name , HW_IF_POSITION);
2020+ EXPECT_FALSE (hw_info[2 ].joints [1 ].command_interfaces [0 ].enable_limits );
2021+ // Velocity command interface should have enable_limits=true (default, no limits element)
2022+ EXPECT_EQ (hw_info[2 ].joints [1 ].command_interfaces [1 ].name , HW_IF_VELOCITY);
2023+ EXPECT_TRUE (hw_info[2 ].joints [1 ].command_interfaces [1 ].enable_limits );
2024+
2025+ // All state interfaces on joint3 should have enable_limits=true (default)
2026+ ASSERT_THAT (hw_info[2 ].joints [1 ].state_interfaces , SizeIs (3 ));
2027+ EXPECT_EQ (hw_info[2 ].joints [1 ].state_interfaces [0 ].name , HW_IF_POSITION);
2028+ EXPECT_TRUE (hw_info[2 ].joints [1 ].state_interfaces [0 ].enable_limits );
2029+ EXPECT_EQ (hw_info[2 ].joints [1 ].state_interfaces [1 ].name , HW_IF_VELOCITY);
2030+ EXPECT_TRUE (hw_info[2 ].joints [1 ].state_interfaces [1 ].enable_limits );
2031+ EXPECT_EQ (hw_info[2 ].joints [1 ].state_interfaces [2 ].name , HW_IF_ACCELERATION);
2032+ EXPECT_TRUE (hw_info[2 ].joints [1 ].state_interfaces [2 ].enable_limits );
2033+
2034+ // Verify limits for TestSystemHardware joints
2035+ ASSERT_THAT (hw_info[2 ].limits , SizeIs (2 ));
2036+ // joint2 has limits disabled at the joint level, but only has velocity command interface, even
2037+ // then all the limits should be disabled by default
2038+ EXPECT_FALSE (hw_info[2 ].limits .at (" joint2" ).has_position_limits );
2039+ EXPECT_THAT (
2040+ hw_info[2 ].limits .at (" joint2" ).max_position ,
2041+ DoubleNear (std::numeric_limits<double >::max (), 1e-5 ));
2042+ EXPECT_THAT (
2043+ hw_info[2 ].limits .at (" joint2" ).min_position ,
2044+ DoubleNear (-std::numeric_limits<double >::max (), 1e-5 ));
2045+ EXPECT_FALSE (hw_info[2 ].limits .at (" joint2" ).has_velocity_limits );
2046+ EXPECT_FALSE (hw_info[2 ].limits .at (" joint2" ).has_effort_limits );
2047+ EXPECT_FALSE (hw_info[2 ].limits .at (" joint2" ).has_acceleration_limits );
2048+ EXPECT_FALSE (hw_info[2 ].limits .at (" joint2" ).has_deceleration_limits );
2049+ EXPECT_FALSE (hw_info[2 ].limits .at (" joint2" ).has_jerk_limits );
2050+
2051+ // joint3 has only position command interface limits disabled
2052+ // position limits should be disabled (has position cmd_if with enable_limits=false)
2053+ // velocity limits remain enabled (from URDF, velocity cmd_if has enable_limits=true)
2054+ EXPECT_FALSE (hw_info[2 ].limits .at (" joint3" ).has_position_limits );
2055+ EXPECT_TRUE (hw_info[2 ].limits .at (" joint3" ).has_velocity_limits );
2056+ EXPECT_THAT (hw_info[2 ].limits .at (" joint3" ).max_velocity , DoubleNear (0.2 , 1e-5 ));
2057+ EXPECT_TRUE (hw_info[2 ].limits .at (" joint3" ).has_effort_limits );
2058+ EXPECT_THAT (hw_info[2 ].limits .at (" joint3" ).max_effort , DoubleNear (0.1 , 1e-5 ));
2059+ EXPECT_FALSE (hw_info[2 ].limits .at (" joint3" ).has_acceleration_limits );
2060+ EXPECT_FALSE (hw_info[2 ].limits .at (" joint3" ).has_deceleration_limits );
2061+ EXPECT_FALSE (hw_info[2 ].limits .at (" joint3" ).has_jerk_limits );
2062+
2063+ // Verify soft_limits - joint2 has a safety_controller in the URDF but since joint2's
2064+ // limits are disabled, we should still have soft_limits parsed from the URDF
2065+ ASSERT_THAT (hw_info[2 ].soft_limits , SizeIs (1 ));
2066+ EXPECT_THAT (hw_info[2 ].soft_limits .at (" joint2" ).max_position , DoubleNear (0.5 , 1e-5 ));
2067+ EXPECT_THAT (hw_info[2 ].soft_limits .at (" joint2" ).min_position , DoubleNear (-1.5 , 1e-5 ));
2068+ EXPECT_THAT (hw_info[2 ].soft_limits .at (" joint2" ).k_position , DoubleNear (10.0 , 1e-5 ));
2069+ EXPECT_THAT (hw_info[2 ].soft_limits .at (" joint2" ).k_velocity , DoubleNear (20.0 , 1e-5 ));
2070+
2071+ // GPIO interfaces - no limits element, so enable_limits should be true (default)
2072+ ASSERT_THAT (hw_info[2 ].gpios , SizeIs (1 ));
2073+ EXPECT_EQ (hw_info[2 ].gpios [0 ].name , " configuration" );
2074+ ASSERT_THAT (hw_info[2 ].gpios [0 ].command_interfaces , SizeIs (1 ));
2075+ EXPECT_EQ (hw_info[2 ].gpios [0 ].command_interfaces [0 ].name , " max_tcp_jerk" );
2076+ EXPECT_TRUE (hw_info[2 ].gpios [0 ].command_interfaces [0 ].enable_limits );
2077+ ASSERT_THAT (hw_info[2 ].gpios [0 ].state_interfaces , SizeIs (1 ));
2078+ EXPECT_EQ (hw_info[2 ].gpios [0 ].state_interfaces [0 ].name , " max_tcp_jerk" );
2079+ EXPECT_TRUE (hw_info[2 ].gpios [0 ].state_interfaces [0 ].enable_limits );
2080+ }
2081+
19282082TEST_F (TestComponentParser, successfully_parse_valid_sdf)
19292083{
19302084 std::string sdf_to_test = ros2_control_test_assets::diff_drive_robot_sdf;
0 commit comments