Skip to content

Commit 741ba8f

Browse files
committed
Add test case for the async with different read/write rate
1 parent c6176b5 commit 741ba8f

File tree

6 files changed

+196
-21
lines changed

6 files changed

+196
-21
lines changed

hardware_interface/include/hardware_interface/actuator_interface.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -568,9 +568,9 @@ class ActuatorInterface : public rclcpp_lifecycle::node_interfaces::LifecycleNod
568568
// interface names to Handle accessed through getters/setters
569569
std::unordered_map<std::string, StateInterface::SharedPtr> actuator_states_;
570570
std::unordered_map<std::string, CommandInterface::SharedPtr> actuator_commands_;
571-
std::atomic<return_type> read_return_info_;
571+
std::atomic<return_type> read_return_info_ = return_type::OK;
572572
std::atomic<std::chrono::nanoseconds> read_execution_time_ = std::chrono::nanoseconds::zero();
573-
std::atomic<return_type> write_return_info_;
573+
std::atomic<return_type> write_return_info_ = return_type::OK;
574574
std::atomic<std::chrono::nanoseconds> write_execution_time_ = std::chrono::nanoseconds::zero();
575575

576576
protected:

hardware_interface/include/hardware_interface/system_interface.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -607,9 +607,9 @@ class SystemInterface : public rclcpp_lifecycle::node_interfaces::LifecycleNodeI
607607
// interface names to Handle accessed through getters/setters
608608
std::unordered_map<std::string, StateInterface::SharedPtr> system_states_;
609609
std::unordered_map<std::string, CommandInterface::SharedPtr> system_commands_;
610-
std::atomic<return_type> read_return_info_;
610+
std::atomic<return_type> read_return_info_ = return_type::OK;
611611
std::atomic<std::chrono::nanoseconds> read_execution_time_ = std::chrono::nanoseconds::zero();
612-
std::atomic<return_type> write_return_info_;
612+
std::atomic<return_type> write_return_info_ = return_type::OK;
613613
std::atomic<std::chrono::nanoseconds> write_execution_time_ = std::chrono::nanoseconds::zero();
614614

615615
protected:

hardware_interface/src/actuator.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -299,12 +299,12 @@ const rclcpp::Time & Actuator::get_last_write_time() const { return last_write_c
299299

300300
const HardwareComponentStatisticsCollector & Actuator::get_read_statistics() const
301301
{
302-
return !impl_->get_hardware_info().is_async ? read_statistics_ : write_statistics_;
302+
return read_statistics_;
303303
}
304304

305305
const HardwareComponentStatisticsCollector & Actuator::get_write_statistics() const
306306
{
307-
return !impl_->get_hardware_info().is_async ? write_statistics_ : read_statistics_;
307+
return write_statistics_;
308308
}
309309

310310
return_type Actuator::read(const rclcpp::Time & time, const rclcpp::Duration & period)

hardware_interface/src/system.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,12 +297,12 @@ const rclcpp::Time & System::get_last_write_time() const { return last_write_cyc
297297

298298
const HardwareComponentStatisticsCollector & System::get_read_statistics() const
299299
{
300-
return !impl_->get_hardware_info().is_async ? read_statistics_ : write_statistics_;
300+
return read_statistics_;
301301
}
302302

303303
const HardwareComponentStatisticsCollector & System::get_write_statistics() const
304304
{
305-
return !impl_->get_hardware_info().is_async ? write_statistics_ : read_statistics_;
305+
return write_statistics_;
306306
}
307307

308308
return_type System::read(const rclcpp::Time & time, const rclcpp::Duration & period)

hardware_interface_testing/test/test_resource_manager.cpp

Lines changed: 139 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1739,10 +1739,16 @@ TEST_F(ResourceManagerTest, test_caching_of_controllers_to_hardware)
17391739
class ResourceManagerTestReadWriteDifferentReadWriteRate : public ResourceManagerTest
17401740
{
17411741
public:
1742-
void setup_resource_manager_and_do_initial_checks()
1742+
void setup_resource_manager_and_do_initial_checks(bool async_components)
17431743
{
1744-
rm = std::make_shared<TestableResourceManager>(
1745-
node_, ros2_control_test_assets::minimal_robot_urdf_with_different_hw_rw_rate, false);
1744+
const auto minimal_robot_urdf_with_different_hw_rw_rate_with_async =
1745+
std::string(ros2_control_test_assets::urdf_head) +
1746+
std::string(ros2_control_test_assets::hardware_resources_with_different_rw_rates_with_async) +
1747+
std::string(ros2_control_test_assets::urdf_tail);
1748+
const std::string urdf =
1749+
async_components ? minimal_robot_urdf_with_different_hw_rw_rate_with_async
1750+
: ros2_control_test_assets::minimal_robot_urdf_with_different_hw_rw_rate;
1751+
rm = std::make_shared<TestableResourceManager>(node_, urdf, false);
17461752
activate_components(*rm);
17471753

17481754
cm_update_rate_ = 100u; // The default value inside
@@ -1767,6 +1773,9 @@ class ResourceManagerTestReadWriteDifferentReadWriteRate : public ResourceManage
17671773
actuator_rw_rate_ = status_map[TEST_ACTUATOR_HARDWARE_NAME].rw_rate;
17681774
system_rw_rate_ = status_map[TEST_SYSTEM_HARDWARE_NAME].rw_rate;
17691775

1776+
actuator_is_async_ = status_map[TEST_ACTUATOR_HARDWARE_NAME].is_async;
1777+
system_is_async_ = status_map[TEST_SYSTEM_HARDWARE_NAME].is_async;
1778+
17701779
claimed_itfs.push_back(
17711780
rm->claim_command_interface(TEST_ACTUATOR_HARDWARE_COMMAND_INTERFACES[0]));
17721781
claimed_itfs.push_back(rm->claim_command_interface(TEST_SYSTEM_HARDWARE_COMMAND_INTERFACES[0]));
@@ -1841,8 +1850,30 @@ class ResourceManagerTestReadWriteDifferentReadWriteRate : public ResourceManage
18411850
}
18421851
// Even though we skip some read and write iterations, the state interfaces should be the same
18431852
// as previous updated one until the next cycle
1844-
ASSERT_EQ(state_itfs[0].get_optional().value(), prev_act_state_value);
1845-
ASSERT_EQ(state_itfs[1].get_optional().value(), prev_system_state_value);
1853+
if (actuator_is_async_)
1854+
{
1855+
// check it is either the previous value or the new one
1856+
EXPECT_THAT(
1857+
state_itfs[0].get_optional(), testing::AnyOf(
1858+
testing::DoubleEq(prev_act_state_value),
1859+
testing::DoubleEq(prev_act_state_value + 5.0)));
1860+
}
1861+
else
1862+
{
1863+
ASSERT_EQ(state_itfs[0].get_optional(), prev_act_state_value);
1864+
}
1865+
if (system_is_async_)
1866+
{
1867+
// check it is either the previous value or the new one
1868+
EXPECT_THAT(
1869+
state_itfs[1].get_optional(), testing::AnyOf(
1870+
testing::DoubleEq(prev_system_state_value),
1871+
testing::DoubleEq(prev_system_state_value + 10.0)));
1872+
}
1873+
else
1874+
{
1875+
ASSERT_EQ(state_itfs[1].get_optional(), prev_system_state_value);
1876+
}
18461877
auto [ok_write, failed_hardware_names_write] = rm->write(time, duration);
18471878
EXPECT_TRUE(ok_write);
18481879
EXPECT_TRUE(failed_hardware_names_write.empty());
@@ -1854,9 +1885,10 @@ class ResourceManagerTestReadWriteDifferentReadWriteRate : public ResourceManage
18541885
{
18551886
if (i > (cm_update_rate_ / rate))
18561887
{
1888+
const double expec_execution_time = (1.e6 / (3 * rate)) + 200.0;
18571889
EXPECT_LT(
18581890
status_map[component_name].read_statistics->execution_time.get_statistics().average,
1859-
100);
1891+
expec_execution_time);
18601892
EXPECT_LT(
18611893
status_map[component_name].read_statistics->periodicity.get_statistics().average,
18621894
1.2 * rate);
@@ -1869,7 +1901,7 @@ class ResourceManagerTestReadWriteDifferentReadWriteRate : public ResourceManage
18691901

18701902
EXPECT_LT(
18711903
status_map[component_name].write_statistics->execution_time.get_statistics().average,
1872-
100);
1904+
expec_execution_time);
18731905
EXPECT_LT(
18741906
status_map[component_name].write_statistics->periodicity.get_statistics().average,
18751907
1.2 * rate);
@@ -1893,6 +1925,7 @@ class ResourceManagerTestReadWriteDifferentReadWriteRate : public ResourceManage
18931925
public:
18941926
std::shared_ptr<TestableResourceManager> rm;
18951927
unsigned int actuator_rw_rate_, system_rw_rate_, cm_update_rate_;
1928+
bool actuator_is_async_, system_is_async_;
18961929
std::vector<hardware_interface::LoanedCommandInterface> claimed_itfs;
18971930
std::vector<hardware_interface::LoanedStateInterface> state_itfs;
18981931

@@ -1906,7 +1939,16 @@ TEST_F(
19061939
ResourceManagerTestReadWriteDifferentReadWriteRate,
19071940
test_components_with_different_read_write_freq_on_activate)
19081941
{
1909-
setup_resource_manager_and_do_initial_checks();
1942+
setup_resource_manager_and_do_initial_checks(false);
1943+
1944+
check_read_and_write_cycles(true);
1945+
}
1946+
1947+
TEST_F(
1948+
ResourceManagerTestReadWriteDifferentReadWriteRate,
1949+
test_components_with_different_read_write_freq_on_activate_with_async)
1950+
{
1951+
setup_resource_manager_and_do_initial_checks(true);
19101952

19111953
check_read_and_write_cycles(true);
19121954
}
@@ -1915,7 +1957,35 @@ TEST_F(
19151957
ResourceManagerTestReadWriteDifferentReadWriteRate,
19161958
test_components_with_different_read_write_freq_on_deactivate)
19171959
{
1918-
setup_resource_manager_and_do_initial_checks();
1960+
setup_resource_manager_and_do_initial_checks(false);
1961+
1962+
// Now deactivate all the components and test the same as above
1963+
rclcpp_lifecycle::State state_inactive(
1964+
lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE,
1965+
hardware_interface::lifecycle_state_names::INACTIVE);
1966+
rm->set_component_state(TEST_SYSTEM_HARDWARE_NAME, state_inactive);
1967+
rm->set_component_state(TEST_ACTUATOR_HARDWARE_NAME, state_inactive);
1968+
rm->set_component_state(TEST_SENSOR_HARDWARE_NAME, state_inactive);
1969+
1970+
auto status_map = rm->get_components_status();
1971+
EXPECT_EQ(
1972+
status_map[TEST_ACTUATOR_HARDWARE_NAME].state.id(),
1973+
lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE);
1974+
EXPECT_EQ(
1975+
status_map[TEST_SYSTEM_HARDWARE_NAME].state.id(),
1976+
lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE);
1977+
EXPECT_EQ(
1978+
status_map[TEST_SENSOR_HARDWARE_NAME].state.id(),
1979+
lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE);
1980+
1981+
check_read_and_write_cycles(true);
1982+
}
1983+
1984+
TEST_F(
1985+
ResourceManagerTestReadWriteDifferentReadWriteRate,
1986+
test_components_with_different_read_write_freq_on_deactivate_with_async)
1987+
{
1988+
setup_resource_manager_and_do_initial_checks(true);
19191989

19201990
// Now deactivate all the components and test the same as above
19211991
rclcpp_lifecycle::State state_inactive(
@@ -1943,7 +2013,35 @@ TEST_F(
19432013
ResourceManagerTestReadWriteDifferentReadWriteRate,
19442014
test_components_with_different_read_write_freq_on_unconfigured)
19452015
{
1946-
setup_resource_manager_and_do_initial_checks();
2016+
setup_resource_manager_and_do_initial_checks(false);
2017+
2018+
// Now deactivate all the components and test the same as above
2019+
rclcpp_lifecycle::State state_unconfigured(
2020+
lifecycle_msgs::msg::State::PRIMARY_STATE_UNCONFIGURED,
2021+
hardware_interface::lifecycle_state_names::UNCONFIGURED);
2022+
rm->set_component_state(TEST_SYSTEM_HARDWARE_NAME, state_unconfigured);
2023+
rm->set_component_state(TEST_ACTUATOR_HARDWARE_NAME, state_unconfigured);
2024+
rm->set_component_state(TEST_SENSOR_HARDWARE_NAME, state_unconfigured);
2025+
2026+
auto status_map = rm->get_components_status();
2027+
EXPECT_EQ(
2028+
status_map[TEST_ACTUATOR_HARDWARE_NAME].state.id(),
2029+
lifecycle_msgs::msg::State::PRIMARY_STATE_UNCONFIGURED);
2030+
EXPECT_EQ(
2031+
status_map[TEST_SYSTEM_HARDWARE_NAME].state.id(),
2032+
lifecycle_msgs::msg::State::PRIMARY_STATE_UNCONFIGURED);
2033+
EXPECT_EQ(
2034+
status_map[TEST_SENSOR_HARDWARE_NAME].state.id(),
2035+
lifecycle_msgs::msg::State::PRIMARY_STATE_UNCONFIGURED);
2036+
2037+
check_read_and_write_cycles(false);
2038+
}
2039+
2040+
TEST_F(
2041+
ResourceManagerTestReadWriteDifferentReadWriteRate,
2042+
test_components_with_different_read_write_freq_on_unconfigured_with_async)
2043+
{
2044+
setup_resource_manager_and_do_initial_checks(true);
19472045

19482046
// Now deactivate all the components and test the same as above
19492047
rclcpp_lifecycle::State state_unconfigured(
@@ -1971,7 +2069,35 @@ TEST_F(
19712069
ResourceManagerTestReadWriteDifferentReadWriteRate,
19722070
test_components_with_different_read_write_freq_on_finalized)
19732071
{
1974-
setup_resource_manager_and_do_initial_checks();
2072+
setup_resource_manager_and_do_initial_checks(false);
2073+
2074+
// Now deactivate all the components and test the same as above
2075+
rclcpp_lifecycle::State state_finalized(
2076+
lifecycle_msgs::msg::State::PRIMARY_STATE_FINALIZED,
2077+
hardware_interface::lifecycle_state_names::FINALIZED);
2078+
rm->set_component_state(TEST_SYSTEM_HARDWARE_NAME, state_finalized);
2079+
rm->set_component_state(TEST_ACTUATOR_HARDWARE_NAME, state_finalized);
2080+
rm->set_component_state(TEST_SENSOR_HARDWARE_NAME, state_finalized);
2081+
2082+
auto status_map = rm->get_components_status();
2083+
EXPECT_EQ(
2084+
status_map[TEST_ACTUATOR_HARDWARE_NAME].state.id(),
2085+
lifecycle_msgs::msg::State::PRIMARY_STATE_FINALIZED);
2086+
EXPECT_EQ(
2087+
status_map[TEST_SYSTEM_HARDWARE_NAME].state.id(),
2088+
lifecycle_msgs::msg::State::PRIMARY_STATE_FINALIZED);
2089+
EXPECT_EQ(
2090+
status_map[TEST_SENSOR_HARDWARE_NAME].state.id(),
2091+
lifecycle_msgs::msg::State::PRIMARY_STATE_FINALIZED);
2092+
2093+
check_read_and_write_cycles(false);
2094+
}
2095+
2096+
TEST_F(
2097+
ResourceManagerTestReadWriteDifferentReadWriteRate,
2098+
test_components_with_different_read_write_freq_on_finalized_with_async)
2099+
{
2100+
setup_resource_manager_and_do_initial_checks(true);
19752101

19762102
// Now deactivate all the components and test the same as above
19772103
rclcpp_lifecycle::State state_finalized(
@@ -2072,14 +2198,14 @@ class ResourceManagerTestAsyncReadWrite : public ResourceManagerTest
20722198
{
20732199
auto [ok, failed_hardware_names] = rm->read(time, duration);
20742200
EXPECT_TRUE(ok);
2075-
EXPECT_TRUE(failed_hardware_names.empty());
2201+
EXPECT_THAT(failed_hardware_names, testing::IsEmpty());
20762202
}
20772203
{
20782204
// claimed_itfs[0].set_value(10.0);
20792205
// claimed_itfs[1].set_value(20.0);
20802206
auto [ok, failed_hardware_names] = rm->write(time, duration);
20812207
EXPECT_TRUE(ok);
2082-
EXPECT_TRUE(failed_hardware_names.empty());
2208+
EXPECT_THAT(failed_hardware_names, testing::IsEmpty());
20832209
}
20842210
node_.get_clock()->sleep_until(time + duration);
20852211
time = node_.get_clock()->now();

ros2_control_test_assets/include/ros2_control_test_assets/descriptions.hpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,55 @@ const auto hardware_resources_with_different_rw_rates =
758758
</ros2_control>
759759
)";
760760

761+
const auto hardware_resources_with_different_rw_rates_with_async =
762+
R"(
763+
<ros2_control name="TestActuatorHardware" type="actuator" rw_rate="50" is_async="true">
764+
<hardware>
765+
<plugin>test_actuator</plugin>
766+
</hardware>
767+
<joint name="joint1">
768+
<command_interface name="position"/>
769+
<state_interface name="position"/>
770+
<state_interface name="velocity"/>
771+
<command_interface name="max_velocity" />
772+
</joint>
773+
</ros2_control>
774+
<ros2_control name="TestSensorHardware" type="sensor" rw_rate="20" is_async="true">
775+
<hardware>
776+
<plugin>test_sensor</plugin>
777+
<param name="example_param_write_for_sec">2</param>
778+
<param name="example_param_read_for_sec">2</param>
779+
</hardware>
780+
<sensor name="sensor1">
781+
<state_interface name="velocity"/>
782+
</sensor>
783+
</ros2_control>
784+
<ros2_control name="TestSystemHardware" type="system" rw_rate="25" is_async="true">
785+
<hardware>
786+
<plugin>test_system</plugin>
787+
<param name="example_param_write_for_sec">2</param>
788+
<param name="example_param_read_for_sec">2</param>
789+
</hardware>
790+
<joint name="joint2">
791+
<command_interface name="velocity"/>
792+
<state_interface name="position"/>
793+
<state_interface name="velocity"/>
794+
<state_interface name="acceleration"/>
795+
<command_interface name="max_acceleration" />
796+
</joint>
797+
<joint name="joint3">
798+
<command_interface name="velocity"/>
799+
<state_interface name="position"/>
800+
<state_interface name="velocity"/>
801+
<state_interface name="acceleration"/>
802+
</joint>
803+
<gpio name="configuration">
804+
<command_interface name="max_tcp_jerk"/>
805+
<state_interface name="max_tcp_jerk"/>
806+
</gpio>
807+
</ros2_control>
808+
)";
809+
761810
const auto hardware_resources_with_negative_rw_rates =
762811
R"(
763812
<ros2_control name="TestActuatorHardware" type="actuator" rw_rate="-50">

0 commit comments

Comments
 (0)