Skip to content

Commit 33b1df0

Browse files
author
bpwilcox
committed
use unordered map with string pair, add test for different nodes same parameter, address feedback
Signed-off-by: bpwilcox <bpwilcox@eng.ucsd.edu>
1 parent 2f5de07 commit 33b1df0

File tree

3 files changed

+68
-15
lines changed

3 files changed

+68
-15
lines changed

rclcpp/include/rclcpp/parameter_events_subscriber.hpp

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
#ifndef RCLCPP__PARAMETER_EVENTS_SUBSCRIBER_HPP_
1616
#define RCLCPP__PARAMETER_EVENTS_SUBSCRIBER_HPP_
1717

18-
#include <map>
1918
#include <string>
2019
#include <utility>
20+
#include <unordered_map>
2121
#include <vector>
2222

2323
#include "rclcpp/rclcpp.hpp"
@@ -140,9 +140,33 @@ class ParameterEventsSubscriber
140140

141141
rclcpp::QoS qos_;
142142

143-
// Map containers for registered parameters
144-
std::map<std::string, std::string> parameter_node_map_;
145-
std::map<std::string, std::function<void(const rclcpp::Parameter &)>> parameter_callbacks_;
143+
// *INDENT-OFF* Uncrustify doesn't handle indented public/private labels
144+
// Hash function for string pair required in std::unordered_map
145+
class stringPairHash
146+
{
147+
public:
148+
template<typename T>
149+
inline void hash_combine(std::size_t & seed, const T & v) const
150+
{
151+
std::hash<T> hasher;
152+
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
153+
}
154+
155+
inline size_t operator()(const std::pair<std::string, std::string> & s) const
156+
{
157+
size_t seed = 0;
158+
hash_combine(seed, s.first);
159+
hash_combine(seed, s.second);
160+
return seed;
161+
}
162+
};
163+
// *INDENT-ON*
164+
165+
// Map container for registered parameters
166+
std::unordered_map<
167+
std::pair<std::string, std::string>,
168+
std::function<void(const rclcpp::Parameter &)>,
169+
stringPairHash> parameter_callbacks_;
146170

147171
// Vector of unique namespaces added
148172
std::vector<std::string> node_namespaces_;

rclcpp/src/rclcpp/parameter_events_subscriber.cpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
#include <map>
1615
#include <memory>
1716
#include <string>
17+
#include <unordered_map>
1818
#include <utility>
1919

2020
#include "rclcpp/parameter_events_subscriber.hpp"
@@ -57,9 +57,9 @@ void ParameterEventsSubscriber::set_event_callback(
5757
std::string full_namespace;
5858
if (node_namespace == "") {
5959
full_namespace = node_base_->get_namespace();
60+
} else {
61+
full_namespace = resolve_path(full_namespace);
6062
}
61-
62-
full_namespace = resolve_path(full_namespace);
6363
add_namespace_event_subscriber(full_namespace);
6464
user_callback_ = callback;
6565
}
@@ -71,8 +71,7 @@ void ParameterEventsSubscriber::register_parameter_callback(
7171
{
7272
auto full_node_name = resolve_path(node_name);
7373
add_namespace_event_subscriber(split_path(full_node_name).first);
74-
parameter_node_map_[parameter_name] = full_node_name;
75-
parameter_callbacks_[parameter_name] = callback;
74+
parameter_callbacks_[{parameter_name, full_node_name}] = callback;
7675
}
7776

7877
bool ParameterEventsSubscriber::get_parameter_from_event(
@@ -86,7 +85,8 @@ bool ParameterEventsSubscriber::get_parameter_from_event(
8685
{rclcpp::ParameterEventsFilter::EventType::NEW,
8786
rclcpp::ParameterEventsFilter::EventType::CHANGED});
8887
if (!filter.get_events().empty()) {
89-
auto param_msg = filter.get_events()[0].second;
88+
const auto & events = filter.get_events();
89+
auto param_msg = events[events.size() - 1].second;
9090
parameter = rclcpp::Parameter::from_parameter_msg(*param_msg);
9191
return true;
9292
}
@@ -101,12 +101,15 @@ void ParameterEventsSubscriber::event_callback(
101101
RCLCPP_DEBUG(node_logging_->get_logger(), "Parameter event received for node: %s",
102102
node_name.c_str());
103103

104-
for (std::map<std::string, std::string>::iterator it = parameter_node_map_.begin();
105-
it != parameter_node_map_.end(); ++it)
106-
{
104+
std::unordered_map<
105+
std::pair<std::string, std::string>,
106+
std::function<void(const rclcpp::Parameter &)>,
107+
stringPairHash>::iterator it;
108+
109+
for (it = parameter_callbacks_.begin(); it != parameter_callbacks_.end(); ++it) {
107110
rclcpp::Parameter p;
108-
if (get_parameter_from_event(event, p, it->first, it->second)) {
109-
parameter_callbacks_[it->first](p);
111+
if (get_parameter_from_event(event, p, it->first.first, it->first.second)) {
112+
it->second(p);
110113
}
111114
}
112115

rclcpp/test/test_parameter_events_subscriber.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,21 @@ class TestNode : public ::testing::Test
5858
multiple = std::make_shared<rcl_interfaces::msg::ParameterEvent>();
5959
remote_node_string = std::make_shared<rcl_interfaces::msg::ParameterEvent>();
6060
diff_ns_bool = std::make_shared<rcl_interfaces::msg::ParameterEvent>();
61+
diff_node_int = std::make_shared<rcl_interfaces::msg::ParameterEvent>();
6162

6263
same_node_int->node = node->get_fully_qualified_name();
6364
same_node_double->node = node->get_fully_qualified_name();
6465
multiple->node = node->get_fully_qualified_name();
6566
remote_node_string->node = remote_node_name;
6667
diff_ns_bool->node = diff_ns_name;
68+
diff_node_int->node = remote_node_name;
6769

6870
rcl_interfaces::msg::Parameter p;
6971
p.name = "my_int";
7072
p.value.type = rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER;
7173
p.value.integer_value = 1;
7274
same_node_int->changed_parameters.push_back(p);
75+
diff_node_int->changed_parameters.push_back(p);
7376
multiple->changed_parameters.push_back(p);
7477

7578
p.name = "my_double";
@@ -97,6 +100,7 @@ class TestNode : public ::testing::Test
97100

98101
rcl_interfaces::msg::ParameterEvent::SharedPtr same_node_int;
99102
rcl_interfaces::msg::ParameterEvent::SharedPtr same_node_double;
103+
rcl_interfaces::msg::ParameterEvent::SharedPtr diff_node_int;
100104
rcl_interfaces::msg::ParameterEvent::SharedPtr remote_node_string;
101105
rcl_interfaces::msg::ParameterEvent::SharedPtr multiple;
102106
rcl_interfaces::msg::ParameterEvent::SharedPtr diff_ns_bool;
@@ -166,6 +170,28 @@ TEST_F(TestNode, RegisterParameterUpdate)
166170
EXPECT_EQ(int_param, 1);
167171
}
168172

173+
TEST_F(TestNode, SameParameterDifferentNode)
174+
{
175+
int int_param_node1;
176+
int int_param_node2;
177+
178+
179+
// Set individual parameters
180+
ParamSubscriber->register_parameter_update("my_int", int_param_node1);
181+
ParamSubscriber->register_parameter_update("my_int", int_param_node2, remote_node_name);
182+
183+
ParamSubscriber->test_event(same_node_int);
184+
EXPECT_EQ(int_param_node1, 1);
185+
EXPECT_NE(int_param_node2, 1);
186+
187+
int_param_node1 = 0;
188+
int_param_node2 = 0;
189+
190+
ParamSubscriber->test_event(diff_node_int);
191+
EXPECT_NE(int_param_node1, 1);
192+
EXPECT_EQ(int_param_node2, 1);
193+
}
194+
169195
TEST_F(TestNode, UserCallback)
170196
{
171197
double double_param = 0.0;

0 commit comments

Comments
 (0)