Bug in ros::NodeHandle::searchParam()?
Hi all,
according to my understanding of searchParam(), the second if
condition in the following code snippet should never be true
(probably except for some rare race condition cases which shouldn't happen in my case):
std::string full_param_name, param_name = "a/b";
if (nh.searchParam(param_name, full_param_name)) {
if (!nh.getParam(full_param_name, result)) {
// this should never be reached (but it is reached) ... ?!
}
}
In particular, see also this ROS tutorial (wiki).
However, in my case I have /a/b
on the parameter server (note the leading /
-> global) and param_name
is a/b
(note the /
in between: is this allowed?). searchParam()
returns true
in that case but getParam()
returns false
. The ros::NodeHandle nh
is initialized with ~
(and, thus, points the node's private namespace). Interesstingly, full_param_name
is (erroneously) set to $fully_qualified_namespace_of_my_node/a/b
(which doesn't exist).
Is this a bug or am I doing something wrong? Even if "nested keys" (= the /
in between a
and b
) are not allowed (are they?), I would assume that searchParam()
returns false
... ?
Thanks!
EDIT: here is a minimum working example that demonstrates the issue:
#include <ros/ros.h>
int main(int argc, char **argv)
{
ros::init(argc, argv, "test_node");
std::string full_param_name, param_name = "a/b", result;
ros::NodeHandle nh("~");
ros::spinOnce(); // (probably not needed)
if (nh.searchParam(param_name, full_param_name)) {
if (!nh.getParam(full_param_name, result)) {
ROS_FATAL("THIS SHOULD NEVER BE PRINTED ... ?! (%s)", full_param_name.c_str());
} else {
ROS_INFO("Okay, parameter found: '%s' = '%s'.", param_name.c_str(), result.c_str());
}
} else {
ROS_INFO("Okay, parameter '%s' not found on the ROS parameter server.", param_name.c_str());
}
ros::shutdown(); // (probably not needed)
return 0;
}
Output:
[FATAL] [1507900407.659972647] [/my_namespace/my_node | 7f61d64c4780]: THIS SHOULD NEVER BE PRINTED ... ?! (/my_namespace/my_node/a/b)
Note that rosparam list | grep "a/b"
returns /a/b
.
EDIT2: since I am successfully using "nested keys" in my code (at other locations/contexts), I assume that they are allowed.
EDIT3 (@Dirk Thomas): thanks for your assistance / thoughts! I think that I've tracked down the problem correctly now. Your link was somewhat helpful. For instance, assume the following is stored on the parameter server
/a/b: 42
/a/c: 'cannot be found with searchParam using private ns'
/node_namespace/node_name/a/b: 41
and I ask for searchParam(nh_private, "a/b", x)
then x=/node_namespace/node_name/a/b
(with value 41) and true
is returned (all fine). However, if I ask for searchParam(nh_private, "a/c", x)
then x=/node_namespace/node_name/a/c
and true
(sic!) is returned but that parameter does not exist (and I don't understand why the docblock states "[...] (yet)"). IMHO, this behavior of searchParam()
makes absolutely no sense and I would consider this to be a bug.
More specifically, my concerns are:
- searchParam() returns true although nothing was found (
/node_namespace/node_name/a/c
). - searchParam() is said "to search up the tree for a parameter" but it returns an invalid key although there is a (here: global) parameter (
/a/c
) matching the given partial key (a/c
).
What do you think? ;-)
If you feel this is a bug (and you already have a MWE), then I believe it would be better to report this over at ros/ros_comm/issues.
Edit: ah. I see you already did that: ros/ros_comm/issues/1187.
Yes. ;-) Thanks for referencing the issue, forgot that.
Well, the actual behavior seems to match what is written in the docblock ( https://github.com/ros/ros_comm/blob/... ). So I assume the behavior is intentionally this way and I don't think this is a bug.
Hm, I disagree since you are referring to the Python docs but I am using roscpp where it is stated that it "returns true if the parameter was found, false otherwise". Clearly, this isn't true. Anyway, I'll write my own version of
searchParam()
.If you think the implementation in both languages is different from each other then please consider to provide a PR which makes them consistent rather than "writing your own".
At least the docs are not consistent, don't you think so?
I would interpret it that the Python doc is just more precise where the C++ doc is not clear about the (partial) match.
Just noting that I've recently come across the same problem:
ros::param::search
returns true and gives aresult
path to a parameter that doesn't exist. For example, if I have a param at/a/b/c/d
, and I callros::param::search("a","c/d", res)
, the return value istrue
andres
isa/c/d
.