Skip to content

Commit 29190b4

Browse files
progtologistbmagyar
authored andcommitted
Fix namespace collision and parameter_callback problems in PidROS
1 parent 62ad792 commit 29190b4

File tree

3 files changed

+81
-34
lines changed

3 files changed

+81
-34
lines changed

include/control_toolbox/pid_ros.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ class CONTROL_TOOLBOX_PUBLIC PidROS
225225

226226
Pid pid_;
227227
std::string topic_prefix_;
228+
std::string param_prefix_;
228229
};
229230

230231
} // namespace control_toolbox

src/pid_ros.cpp

+57-34
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,33 @@ namespace control_toolbox
4444

4545
void PidROS::initialize(std::string topic_prefix)
4646
{
47-
if (topic_prefix.back() != '.' && !topic_prefix.empty()) {
48-
topic_prefix_ = topic_prefix + ".";
49-
} else {
50-
topic_prefix_ = topic_prefix;
47+
param_prefix_ = topic_prefix;
48+
// If it starts with a "~", remove it
49+
if (param_prefix_.compare(0, 1, "~") == 0) {
50+
param_prefix_.erase(0, 1);
51+
}
52+
// If it starts with a "/" or a "~/", remove those as well
53+
if (param_prefix_.compare(0, 1, "/") == 0) {
54+
param_prefix_.erase(0, 1);
55+
}
56+
// Replace namespacing separator from "/" to "." in parameters
57+
std::replace(param_prefix_.begin(), param_prefix_.end(), '/', '.');
58+
// Add a trailing "."
59+
if (!param_prefix_.empty() && param_prefix_.back() != '.') {
60+
param_prefix_.append(".");
61+
}
62+
63+
topic_prefix_ = topic_prefix;
64+
// Replace parameter separator from "." to "/" in topics
65+
std::replace(topic_prefix_.begin(), topic_prefix_.end(), '.', '/');
66+
// Add a trailing "/"
67+
if (!topic_prefix_.empty() && topic_prefix_.back() != '/') {
68+
topic_prefix_.append("/");
5169
}
5270

5371
state_pub_ = rclcpp::create_publisher<control_msgs::msg::PidState>(
5472
topics_interface_,
55-
topic_prefix + "/pid_state",
73+
topic_prefix_ + "pid_state",
5674
rclcpp::SensorDataQoS());
5775
rt_state_pub_.reset(
5876
new realtime_tools::RealtimePublisher<control_msgs::msg::PidState>(state_pub_));
@@ -111,13 +129,13 @@ PidROS::initPid()
111129
double p, i, d, i_min, i_max;
112130
bool antiwindup = false;
113131
bool all_params_available = true;
114-
all_params_available &= getDoubleParam(topic_prefix_ + "p", p);
115-
all_params_available &= getDoubleParam(topic_prefix_ + "i", i);
116-
all_params_available &= getDoubleParam(topic_prefix_ + "d", d);
117-
all_params_available &= getDoubleParam(topic_prefix_ + "i_clamp_max", i_max);
118-
all_params_available &= getDoubleParam(topic_prefix_ + "i_clamp_min", i_min);
132+
all_params_available &= getDoubleParam(param_prefix_ + "p", p);
133+
all_params_available &= getDoubleParam(param_prefix_ + "i", i);
134+
all_params_available &= getDoubleParam(param_prefix_ + "d", d);
135+
all_params_available &= getDoubleParam(param_prefix_ + "i_clamp_max", i_max);
136+
all_params_available &= getDoubleParam(param_prefix_ + "i_clamp_min", i_min);
119137

120-
getBooleanParam(topic_prefix_ + "antiwindup", antiwindup);
138+
getBooleanParam(param_prefix_ + "antiwindup", antiwindup);
121139

122140
if (all_params_available) {
123141
setParameterEventCallback();
@@ -141,12 +159,12 @@ PidROS::initPid(double p, double i, double d, double i_max, double i_min, bool a
141159
{
142160
pid_.initPid(p, i, d, i_max, i_min, antiwindup);
143161

144-
declareParam(topic_prefix_ + "p", rclcpp::ParameterValue(p));
145-
declareParam(topic_prefix_ + "i", rclcpp::ParameterValue(i));
146-
declareParam(topic_prefix_ + "d", rclcpp::ParameterValue(d));
147-
declareParam(topic_prefix_ + "i_clamp_max", rclcpp::ParameterValue(i_max));
148-
declareParam(topic_prefix_ + "i_clamp_min", rclcpp::ParameterValue(i_min));
149-
declareParam(topic_prefix_ + "antiwindup", rclcpp::ParameterValue(antiwindup));
162+
declareParam(param_prefix_ + "p", rclcpp::ParameterValue(p));
163+
declareParam(param_prefix_ + "i", rclcpp::ParameterValue(i));
164+
declareParam(param_prefix_ + "d", rclcpp::ParameterValue(d));
165+
declareParam(param_prefix_ + "i_clamp_max", rclcpp::ParameterValue(i_max));
166+
declareParam(param_prefix_ + "i_clamp_min", rclcpp::ParameterValue(i_min));
167+
declareParam(param_prefix_ + "antiwindup", rclcpp::ParameterValue(antiwindup));
150168

151169
setParameterEventCallback();
152170
}
@@ -192,12 +210,12 @@ PidROS::setGains(double p, double i, double d, double i_max, double i_min, bool
192210
{
193211
node_params_->set_parameters(
194212
{
195-
rclcpp::Parameter(topic_prefix_ + "p", p),
196-
rclcpp::Parameter(topic_prefix_ + "i", i),
197-
rclcpp::Parameter(topic_prefix_ + "d", d),
198-
rclcpp::Parameter(topic_prefix_ + "i_clamp_max", i_max),
199-
rclcpp::Parameter(topic_prefix_ + "i_clamp_min", i_min),
200-
rclcpp::Parameter(topic_prefix_ + "antiwindup", antiwindup)
213+
rclcpp::Parameter(param_prefix_ + "p", p),
214+
rclcpp::Parameter(param_prefix_ + "i", i),
215+
rclcpp::Parameter(param_prefix_ + "d", d),
216+
rclcpp::Parameter(param_prefix_ + "i_clamp_max", i_max),
217+
rclcpp::Parameter(param_prefix_ + "i_clamp_min", i_min),
218+
rclcpp::Parameter(param_prefix_ + "antiwindup", antiwindup)
201219
}
202220
);
203221

@@ -294,40 +312,45 @@ PidROS::setParameterEventCallback()
294312

295313
/// @note don't use getGains, it's rt
296314
Pid::Gains gains = pid_.getGains();
315+
bool changed = false;
297316

298317
for (auto & parameter : parameters) {
299318
const std::string param_name = parameter.get_name();
300319
try {
301-
if (param_name == topic_prefix_ + "p") {
320+
if (param_name == param_prefix_ + "p") {
302321
gains.p_gain_ = parameter.get_value<double>();
303-
} else if (param_name == topic_prefix_ + "i") {
322+
changed = true;
323+
} else if (param_name == param_prefix_ + "i") {
304324
gains.i_gain_ = parameter.get_value<double>();
305-
} else if (param_name == topic_prefix_ + "d") {
325+
changed = true;
326+
} else if (param_name == param_prefix_ + "d") {
306327
gains.d_gain_ = parameter.get_value<double>();
307-
} else if (param_name == topic_prefix_ + "i_clamp_max") {
328+
changed = true;
329+
} else if (param_name == param_prefix_ + "i_clamp_max") {
308330
gains.i_max_ = parameter.get_value<double>();
309-
} else if (param_name == topic_prefix_ + "i_clamp_min") {
331+
changed = true;
332+
} else if (param_name == param_prefix_ + "i_clamp_min") {
310333
gains.i_min_ = parameter.get_value<double>();
311-
} else if (param_name == topic_prefix_ + "antiwindup") {
334+
changed = true;
335+
} else if (param_name == param_prefix_ + "antiwindup") {
312336
gains.antiwindup_ = parameter.get_value<bool>();
313-
} else {
314-
result.successful = false;
315-
result.reason = "Invalid parameter";
337+
changed = true;
316338
}
317339
} catch (const rclcpp::exceptions::InvalidParameterTypeException & e) {
318340
RCLCPP_INFO_STREAM(
319341
node_logging_->get_logger(), "Please use the right type: " << e.what());
320342
}
321343
}
322344

323-
if (result.successful) {
345+
if (changed) {
324346
/// @note don't call setGains() from inside a callback
325347
pid_.setGains(gains);
326348
}
327349

328350
return result;
329351
};
330-
352+
/// @note this gets called whenever a parameter changes.
353+
/// Any parameter under that node. Not just PidROS.
331354
parameter_callback_ =
332355
node_params_->add_on_set_parameters_callback(
333356
on_parameter_event_callback);

test/pid_parameters_tests.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,29 @@ TEST(PidParametersTest, GetParametersFromParams)
227227
ASSERT_EQ(param.get_value<double>(), P);
228228
}
229229

230+
TEST(PidParametersTest, MultiplePidInstances)
231+
{
232+
rclcpp::Node::SharedPtr node = std::make_shared<rclcpp::Node>("multiple_pid_instances");
233+
234+
control_toolbox::PidROS pid_1(node, "PID_1");
235+
control_toolbox::PidROS pid_2(node, "PID_2");
236+
237+
const double P = 1.0;
238+
const double I = 2.0;
239+
const double D = 3.0;
240+
const double I_MAX = 10.0;
241+
const double I_MIN = -10.0;
242+
243+
ASSERT_NO_THROW(pid_1.initPid(P, I, D, I_MAX, I_MIN, false));
244+
ASSERT_NO_THROW(pid_2.initPid(P, I, D, I_MAX, I_MIN, true));
245+
246+
rclcpp::Parameter param_1, param_2;
247+
ASSERT_TRUE(node->get_parameter("PID_1.p", param_1));
248+
ASSERT_EQ(param_1.get_value<double>(), P);
249+
ASSERT_TRUE(node->get_parameter("PID_2.p", param_2));
250+
ASSERT_EQ(param_2.get_value<double>(), P);
251+
}
252+
230253
int main(int argc, char ** argv)
231254
{
232255
testing::InitGoogleTest(&argc, argv);

0 commit comments

Comments
 (0)