Skip to content

Commit 8e890fc

Browse files
authored
Merge branch 'master' into add/statistics/hardware_components
2 parents 0faca71 + d5c2c99 commit 8e890fc

17 files changed

+301
-211
lines changed

doc/introspection.rst

+12-5
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,19 @@ Data Visualization
7070

7171
Data can be visualized with any tools that display ROS topics, but we recommend `PlotJuggler <https://plotjuggler.io/>`_ for viewing high resolution live data, or data in bags.
7272

73-
1. Open ``PlotJuggler`` running ``ros2 run plotjuggler plotjuggler``.
73+
1. Open ``PlotJuggler`` by running ``ros2 run plotjuggler plotjuggler`` from the command line.
74+
7475
.. image:: images/plotjuggler.png
75-
2. Visualize the data:
76-
- Importing from the ros2bag
77-
- Subscribing to the ROS2 topics live with the ``ROS2 Topic Subscriber`` option under ``Streaming`` header.
76+
:alt: PlotJuggler
77+
78+
2. Visualize the data by importing from the ros2bag file or subscribing to the ROS2 topics live with the ``ROS2 Topic Subscriber`` option under ``Streaming`` header.
79+
7880
3. Choose the topics ``~/introspection_data/names`` and ``~/introspection_data/values`` from the popup window.
81+
7982
.. image:: images/plotjuggler_select_topics.png
80-
4. Now, select the variables that are of your interest and drag them to the plot.
83+
:alt: PlotJuggler Select Topics
84+
85+
4. Then, select the variables that are of your interest and drag them to the plot.
86+
8187
.. image:: images/plotjuggler_visualizing_data.png
88+
:alt: PlotJuggler Visualizing Data

hardware_interface/include/hardware_interface/handle.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ class Handle
319319
// END
320320
}
321321

322-
std::shared_mutex & get_mutex() { return handle_mutex_; }
322+
std::shared_mutex & get_mutex() const { return handle_mutex_; }
323323

324324
HandleDataType get_data_type() const { return data_type_; }
325325

hardware_interface/include/hardware_interface/resource_manager.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,7 @@ class ResourceManager
527527
mutable std::recursive_mutex resource_interfaces_lock_;
528528
mutable std::recursive_mutex claimed_command_interfaces_lock_;
529529
mutable std::recursive_mutex resources_lock_;
530+
mutable std::recursive_mutex joint_limiters_lock_;
530531

531532
private:
532533
bool validate_storage(const std::vector<hardware_interface::HardwareInfo> & hardware_info) const;

hardware_interface/src/resource_manager.cpp

+47-6
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,15 @@ class ResourceStorage
700700
if (hw_info.soft_limits.find(joint_name) != hw_info.soft_limits.end())
701701
{
702702
soft_limits = {hw_info.soft_limits.at(joint_name)};
703+
RCLCPP_INFO(
704+
get_logger(), "Using SoftJointLimiter for joint '%s' in hardware '%s' : '%s'",
705+
joint_name.c_str(), hw_info.name.c_str(), soft_limits[0].to_string().c_str());
706+
}
707+
else
708+
{
709+
RCLCPP_INFO(
710+
get_logger(), "Using JointLimiter for joint '%s' in hardware '%s' : '%s'",
711+
joint_name.c_str(), hw_info.name.c_str(), limits.to_string().c_str());
703712
}
704713
std::unique_ptr<
705714
joint_limits::JointLimiterInterface<joint_limits::JointControlInterfacesData>>
@@ -738,14 +747,19 @@ class ResourceStorage
738747
const std::string interface_name = joint_name + "/" + interface_type;
739748
if (interface_map.find(interface_name) != interface_map.end())
740749
{
741-
// If the command interface is not claimed, then the value is not set
742-
if (is_command_itf && !claimed_command_interface_map_.at(interface_name))
750+
// If the command interface is not claimed, then the value is not set (or) if the
751+
// interface doesn't exist, then value is not set
752+
if (
753+
is_command_itf && (claimed_command_interface_map_.count(interface_name) == 0 ||
754+
!claimed_command_interface_map_.at(interface_name)))
743755
{
744756
value = std::nullopt;
745757
}
746758
else
747759
{
748-
value = interface_map.at(interface_name)->get_value();
760+
auto itf_handle = interface_map.at(interface_name);
761+
std::shared_lock<std::shared_mutex> lock(itf_handle->get_mutex());
762+
value = itf_handle->get_optional(lock).value();
749763
}
750764
}
751765
};
@@ -767,7 +781,9 @@ class ResourceStorage
767781
const std::string interface_name = limited_command.joint_name + "/" + interface_type;
768782
if (data.has_value() && interface_map.find(interface_name) != interface_map.end())
769783
{
770-
interface_map.at(interface_name)->set_value(data.value());
784+
auto itf_handle = interface_map.at(interface_name);
785+
std::unique_lock<std::shared_mutex> lock(itf_handle->get_mutex());
786+
std::ignore = itf_handle->set_value(lock, data.value());
771787
}
772788
};
773789
// update the command data of the limiters
@@ -955,7 +971,8 @@ class ResourceStorage
955971
interface_name.c_str());
956972
continue;
957973
}
958-
const auto limiter_fn = [&, interface_name](double value, bool & is_limited) -> double
974+
const auto limiter_fn = [this, joint_name, interface_name, desired_period, &limiters](
975+
double value, bool & is_limited) -> double
959976
{
960977
is_limited = false;
961978
joint_limits::JointInterfacesCommandLimiterData data;
@@ -987,7 +1004,9 @@ class ResourceStorage
9871004
{
9881005
RCLCPP_ERROR_THROTTLE(
9891006
get_logger(), *rm_clock_, 1000,
990-
"Command of at least one joint is out of limits (throttled log).");
1007+
"Command of at least one joint is out of limits (throttled log). %s with desired "
1008+
"period : %f sec.",
1009+
data.to_string().c_str(), desired_period.seconds());
9911010
}
9921011
if (
9931012
interface_name == hardware_interface::HW_IF_POSITION &&
@@ -1437,6 +1456,7 @@ bool ResourceManager::load_and_initialize_components(
14371456

14381457
void ResourceManager::import_joint_limiters(const std::string & urdf)
14391458
{
1459+
std::lock_guard<std::recursive_mutex> guard(joint_limiters_lock_);
14401460
const auto hardware_info = hardware_interface::parse_control_resources_from_urdf(urdf);
14411461
resource_storage_->import_joint_limiters(hardware_info);
14421462
}
@@ -1958,6 +1978,21 @@ bool ResourceManager::perform_command_mode_switch(
19581978
const bool actuators_result = call_perform_mode_switch(resource_storage_->actuators_);
19591979
const bool systems_result = call_perform_mode_switch(resource_storage_->systems_);
19601980

1981+
if (actuators_result && systems_result)
1982+
{
1983+
// Reset the internals of the joint limiters
1984+
for (auto & [hw_name, limiters] : resource_storage_->joint_limiters_interface_)
1985+
{
1986+
for (const auto & [joint_name, limiter] : limiters)
1987+
{
1988+
limiter->reset_internals();
1989+
RCLCPP_DEBUG(
1990+
get_logger(), "Resetting internals of joint limiter for joint '%s' in hardware '%s'",
1991+
joint_name.c_str(), hw_name.c_str());
1992+
}
1993+
}
1994+
}
1995+
19611996
return actuators_result && systems_result;
19621997
}
19631998

@@ -2048,6 +2083,12 @@ return_type ResourceManager::set_component_state(
20482083
// CM API: Called in "update"-thread
20492084
bool ResourceManager::enforce_command_limits(const rclcpp::Duration & period)
20502085
{
2086+
std::unique_lock<std::recursive_mutex> limiters_guard(joint_limiters_lock_, std::try_to_lock);
2087+
if (!limiters_guard.owns_lock())
2088+
{
2089+
return false;
2090+
}
2091+
20512092
bool enforce_result = false;
20522093
// Joint Limiters operations
20532094
for (auto & [hw_name, limiters] : resource_storage_->joint_limiters_interface_)

hardware_interface_testing/test/test_components/test_actuator.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -102,15 +102,15 @@ class TestActuator : public ActuatorInterface
102102
const std::vector<std::string> & /*start_interfaces*/,
103103
const std::vector<std::string> & /*stop_interfaces*/) override
104104
{
105-
position_state_ += 1.0;
105+
position_state_ += 0.001;
106106
return hardware_interface::return_type::OK;
107107
}
108108

109109
hardware_interface::return_type perform_command_mode_switch(
110110
const std::vector<std::string> & /*start_interfaces*/,
111111
const std::vector<std::string> & /*stop_interfaces*/) override
112112
{
113-
position_state_ += 100.0;
113+
position_state_ += 0.1;
114114
return hardware_interface::return_type::OK;
115115
}
116116

hardware_interface_testing/test/test_resource_manager.cpp

+23-22
Original file line numberDiff line numberDiff line change
@@ -2562,8 +2562,8 @@ class ResourceManagerTestCommandLimitEnforcement : public ResourceManagerTest
25622562
EXPECT_TRUE(ok);
25632563
EXPECT_TRUE(failed_hardware_names.empty());
25642564

2565-
claimed_itfs[0].set_value(10.0);
2566-
claimed_itfs[1].set_value(-20.0);
2565+
claimed_itfs[0].set_value(2.0);
2566+
claimed_itfs[1].set_value(-4.0);
25672567

25682568
auto [ok_write, failed_hardware_names_write] = rm->write(time, duration);
25692569
EXPECT_TRUE(ok_write);
@@ -2579,8 +2579,8 @@ class ResourceManagerTestCommandLimitEnforcement : public ResourceManagerTest
25792579
EXPECT_TRUE(ok);
25802580
EXPECT_TRUE(failed_hardware_names.empty());
25812581

2582-
EXPECT_EQ(state_itfs[0].get_value(), 5.0);
2583-
EXPECT_EQ(state_itfs[1].get_value(), -10.0);
2582+
EXPECT_EQ(state_itfs[0].get_value(), 1.0);
2583+
EXPECT_EQ(state_itfs[1].get_value(), -2.0);
25842584
auto [ok_write, failed_hardware_names_write] = rm->write(time, duration);
25852585
EXPECT_TRUE(ok_write);
25862586
EXPECT_TRUE(failed_hardware_names_write.empty());
@@ -2595,9 +2595,11 @@ class ResourceManagerTestCommandLimitEnforcement : public ResourceManagerTest
25952595
EXPECT_TRUE(ok);
25962596
EXPECT_TRUE(failed_hardware_names.empty());
25972597

2598-
EXPECT_EQ(state_itfs[0].get_value(), 5.0);
2599-
EXPECT_EQ(state_itfs[1].get_value(), -10.0);
2598+
EXPECT_EQ(state_itfs[0].get_value(), 1.0);
2599+
EXPECT_EQ(state_itfs[1].get_value(), -2.0);
26002600

2601+
EXPECT_EQ(claimed_itfs[0].get_value(), 2.0);
2602+
EXPECT_EQ(claimed_itfs[1].get_value(), -4.0);
26012603
claimed_itfs[0].set_value(0.0);
26022604
claimed_itfs[1].set_value(0.0);
26032605
EXPECT_EQ(claimed_itfs[0].get_value(), 0.0);
@@ -2606,9 +2608,9 @@ class ResourceManagerTestCommandLimitEnforcement : public ResourceManagerTest
26062608
// enforcing limits
26072609
rm->enforce_command_limits(duration);
26082610

2609-
ASSERT_NEAR(state_itfs[2].get_value(), 5.05, 0.00001);
2610-
// it is limited to the M_PI as the actual position is outside the range
2611-
EXPECT_NEAR(claimed_itfs[0].get_value(), M_PI, 0.00001);
2611+
ASSERT_NEAR(state_itfs[2].get_value(), 1.05, 0.00001);
2612+
// It is using the actual velocity 1.05 to limit the claimed_itf
2613+
EXPECT_NEAR(claimed_itfs[0].get_value(), 1.048, 0.00001);
26122614
EXPECT_EQ(claimed_itfs[1].get_value(), 0.0);
26132615

26142616
auto [ok_write, failed_hardware_names_write] = rm->write(time, duration);
@@ -2621,33 +2623,30 @@ class ResourceManagerTestCommandLimitEnforcement : public ResourceManagerTest
26212623
EXPECT_TRUE(read_ok);
26222624
EXPECT_TRUE(failed_hardware_names_read.empty());
26232625

2624-
ASSERT_NEAR(state_itfs[0].get_value(), M_PI_2, 0.00001);
2626+
ASSERT_NEAR(state_itfs[0].get_value(), claimed_itfs[0].get_value() / 2.0, 0.00001);
26252627
ASSERT_EQ(state_itfs[1].get_value(), 0.0);
26262628
}
26272629

26282630
// Reset the position state interface of actuator to zero
26292631
{
2630-
ASSERT_GT(state_itfs[2].get_value(), 5.05);
2632+
ASSERT_GT(state_itfs[2].get_value(), 1.05);
26312633
claimed_itfs[0].set_value(test_constants::RESET_STATE_INTERFACES_VALUE);
26322634
auto [read_ok, failed_hardware_names_read] = rm->read(time, duration);
26332635
EXPECT_TRUE(read_ok);
26342636
EXPECT_TRUE(failed_hardware_names_read.empty());
26352637
ASSERT_EQ(state_itfs[2].get_value(), 0.0);
26362638
claimed_itfs[0].set_value(0.0);
26372639
claimed_itfs[1].set_value(0.0);
2640+
ASSERT_EQ(claimed_itfs[0].get_value(), 0.0);
2641+
ASSERT_EQ(claimed_itfs[1].get_value(), 0.0);
26382642
}
26392643

26402644
double new_state_value_1 = state_itfs[0].get_value();
26412645
double new_state_value_2 = state_itfs[1].get_value();
26422646
// Now loop and see that the joint limits are being enforced progressively
2643-
for (size_t i = 1; i < 2000; i++)
2647+
for (size_t i = 1; i < 300; i++)
26442648
{
2645-
// let's amplify the limit enforce period, to test more rapidly. It would work with 0.01s as
2646-
// well
2647-
const rclcpp::Duration enforce_period =
2648-
rclcpp::Duration::from_seconds(duration.seconds() * 10.0);
2649-
2650-
auto [ok, failed_hardware_names] = rm->read(time, enforce_period);
2649+
auto [ok, failed_hardware_names] = rm->read(time, duration);
26512650
EXPECT_TRUE(ok);
26522651
EXPECT_TRUE(failed_hardware_names.empty());
26532652

@@ -2660,13 +2659,15 @@ class ResourceManagerTestCommandLimitEnforcement : public ResourceManagerTest
26602659
EXPECT_EQ(claimed_itfs[1].get_value(), -20.0);
26612660

26622661
// enforcing limits
2663-
rm->enforce_command_limits(enforce_period);
2662+
rm->enforce_command_limits(duration);
26642663

26652664
// the joint limits value is same as in the parsed URDF
26662665
const double velocity_joint_1 = 0.2;
2666+
const double prev_command_val = 1.048;
26672667
ASSERT_NEAR(
26682668
claimed_itfs[0].get_value(),
2669-
std::min(state_itfs[2].get_value() + (velocity_joint_1 * enforce_period.seconds()), M_PI),
2669+
prev_command_val +
2670+
std::min((velocity_joint_1 * (duration.seconds() * static_cast<double>(i))), M_PI),
26702671
1.0e-8)
26712672
<< "This should be progressively increasing as it is a position limit for iteration : "
26722673
<< i;
@@ -2677,7 +2678,7 @@ class ResourceManagerTestCommandLimitEnforcement : public ResourceManagerTest
26772678
new_state_value_1 = claimed_itfs[0].get_value() / 2.0;
26782679
new_state_value_2 = claimed_itfs[1].get_value() / 2.0;
26792680

2680-
auto [ok_write, failed_hardware_names_write] = rm->write(time, enforce_period);
2681+
auto [ok_write, failed_hardware_names_write] = rm->write(time, duration);
26812682
EXPECT_TRUE(ok_write);
26822683
EXPECT_TRUE(failed_hardware_names_write.empty());
26832684
node_.get_clock()->sleep_until(time + duration);
@@ -2688,7 +2689,7 @@ class ResourceManagerTestCommandLimitEnforcement : public ResourceManagerTest
26882689
EXPECT_TRUE(ok);
26892690
EXPECT_TRUE(failed_hardware_names.empty());
26902691

2691-
EXPECT_NEAR(state_itfs[0].get_value(), M_PI_2, 0.00001);
2692+
EXPECT_NEAR(state_itfs[0].get_value(), 0.823, 0.00001);
26922693
EXPECT_NEAR(state_itfs[1].get_value(), -0.1, 0.00001);
26932694
}
26942695
}

0 commit comments

Comments
 (0)