ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | Q&A answers.ros.org

# 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 nhis 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? ;-)

edit retag close merge delete

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.

( 2017-10-13 08:40:37 -0600 )edit

Yes. ;-) Thanks for referencing the issue, forgot that.

( 2017-10-13 08:41:49 -0600 )edit

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.

( 2017-10-17 11:19:01 -0600 )edit

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().

( 2017-10-18 08:38:35 -0600 )edit

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".

( 2017-10-18 10:02:51 -0600 )edit

At least the docs are not consistent, don't you think so?

( 2017-10-18 10:04:39 -0600 )edit

I would interpret it that the Python doc is just more precise where the C++ doc is not clear about the (partial) match.

( 2017-10-18 10:07:55 -0600 )edit

Just noting that I've recently come across the same problem: ros::param::search returns true and gives a result path to a parameter that doesn't exist. For example, if I have a param at /a/b/c/d, and I call ros::param::search("a","c/d", res), the return value is true and res is a/c/d.

( 2018-03-06 19:04:53 -0600 )edit

Sort by » oldest newest most voted

You might want to print the value of full_param_name after getting it with searchParam before calling getParam.

The API docs describe the second argument of searchParam with:

[out] result the found value (if any)

Update:

The docblock is kind of misleading. The result is actually a parameter key and not a value.

When I run your code snippet as-is I get:

• no parameter set: Okay, parameter 'a/b' not found on the ROS parameter server.
• after rosparam set /a/b global_value: Okay, parameter found: 'a/b' = 'global_value'.
• after rosparam set /test_node/a/b node_value: Okay, parameter found: 'a/b' = 'node_value'.

After calling rosparam delete /test_node/a/b I do get THIS SHOULD NEVER BE PRINTED ... ?! (/test_node/a/b).

Maybe you can post the exact steps you are performing when running into the problem.

May this docblock clarifies the behavior of searchParam which seems to be the rational for the case above: https://github.com/ros/ros_comm/blob/...

more

Thank you very much! That did the trick, sorry for the noise!

Minor follow-up question: it is possible to use searchParam() with types other than std::string? There just seems to be a string version of that method.

( 2017-10-14 17:34:42 -0600 )edit

@Dirk Thomas: For some reason, I am unable to reproduce this on my primary dev machine: if I print the value of full_param_name, I get 'a/b' = '/a/b' (the value is 'test_value'). Also, the ROS wiki exactly states that searchParam() + getParam() is the way to go. Is that an error in the wiki?

( 2017-10-16 06:27:48 -0600 )edit

With what other parameter type do you want to call searchParam()? char* should work too using implicit conversion.

( 2017-10-16 12:56:43 -0600 )edit

To your last comment: before you edited your answer, you've written that searchParam() returns the actual ROS parameter server value in its (last) parameter result which obviously isn't the case (see also wiki link in my initial post). My comment just referred to that statement and ...

( 2017-10-17 05:00:02 -0600 )edit

... doesn't make any sense after your edit/update. With respect to your edit, I've updated my initial post.

( 2017-10-17 05:00:10 -0600 )edit