Ask Your Question
2

read yaml parameter in C++

asked 2014-11-25 13:04:25 -0500

courrier gravatar image

updated 2014-11-26 06:06:36 -0500

Hi all,

I'm experiencing an issue in using the parameter server:

1) I start a roscore so that I get only one master on this machine. 2) I set a global param manually, say:

rosparam set /test/m '{"id0": 0, "id1": 1}'

3) I start one of my launchfile whose short version is:

<launch>
    <node pkg="mypckg" name="mynode" type="mynode" output="screen"/>
</launch>

I get:

roslaunch mypckg mylaunch.launch
... logging to /home/flowers/.ros/log/08d803da-74d2-11e4-9a51-a01d480daef0/roslaunch-zbook-4127.log
Checking log directory for disk usage. This may take awhile.
Press Ctrl-C to interrupt
Done checking log file disk usage. Usage is <1GB.

started roslaunch server http://zbook:55760/

SUMMARY
========

PARAMETERS
 * /rosdistro
 * /rosversion

4) In the code of "mynode" I read this param:

                string m;
                if(!nh.getParam("/test/map", m))
                    ROS_ERROR("Failed to read 'map' on param server");

5) The above error is triggered, while rosparam get /thr/before still returns an existing value. It looks like I'm not reading params in the same namespace but I'm reading global parameters so I don't understand...

What are the PARAMETERS listed in the SUMMARY? Only parameters defined in the launch file or all available parameters on the server?

What am I missing? Thanks

edit retag flag offensive close merge delete

Comments

1

What is the output of rosparam list? You can try that at various points to see what the parameters are or how they're changing (using rosparam get)...

kramer gravatar imagekramer ( 2014-11-25 15:08:27 -0500 )edit

2 Answers

Sort by ยป oldest newest most voted
2

answered 2014-11-26 06:11:01 -0500

courrier gravatar image

updated 2014-11-26 06:15:17 -0500

I've modified my question to match the real problem and answer to it. Reading a yamlis quite heavy in C++, here's a way to read a map of arrays for instance:

                XmlRpc::XmlRpcValue symbols;

                if(!ros::param::get("/thr/symbols", symbols))
                    ROS_ERROR("Failed to read symbols on param server");

                ROS_ASSERT(symbols.getType()==XmlRpc::XmlRpcValue::TypeStruct);
                for (XmlRpc::XmlRpcValue::iterator i=symbols.begin(); i!=symbols.end(); ++i) {
                    ROS_ASSERT(i->second.getType()==XmlRpc::XmlRpcValue::TypeArray);
                    for(int j=0; j<i->second.size(); ++j) {
                        ROS_ASSERT(i->second[j].getType()==XmlRpc::XmlRpcValue::TypeDouble);
                    }
                }

With YAML being:

object0: [0.1280805148444952, -0.2574350304851667]
table: [-0.019239830108468144]
object1: [-0.12373553201812965, -0.2581443366277866, 0.12297468008504482, 0.0405834453536516, 0.9474896873206372, -0.026972527372781926]
arm: [0.9303491449393159]
eye: [0.12397546355498722 -0.37202872219628474]

Sorry for editing 1000 times :)

edit flag offensive delete link more

Comments

1

Mmm, yaml-cpp makes yaml in C++ soooo much easier and less ugly!

Lorenzo Riano gravatar imageLorenzo Riano ( 2014-11-26 12:11:30 -0500 )edit

Would it be really easier? This is not longer than the minimal code to iterate on two nested datastructures... the assert are for safety but obviously optional

courrier gravatar imagecourrier ( 2014-11-26 12:40:50 -0500 )edit

That code looks terrible.

Tommi gravatar imageTommi ( 2015-09-07 00:27:24 -0500 )edit

yaml-cpp is nice, but they've made horrible things with their versioning, so now we have ROS packages depending on 0.3, while other packages depend on 0.5, which can't be easily installed alongside... this is hell... guys from ETH tried to make it easier: https://github.com/ethz-asl/yaml_cpp_...

peci1 gravatar imagepeci1 ( 2017-05-26 08:31:58 -0500 )edit
2

answered 2014-11-25 14:32:34 -0500

updated 2014-11-26 16:42:45 -0500

How did you create nh in your code? If you declare it with

   ros:: NodeHandle nh("~")

then it'll be in the private namespace of your node. Honestly that's the only source of this problem that I can think of. Also make sure you're spelling the names correctly :)

To test the namespaces, you can use the NodeHandle method resolveName (see http://docs.ros.org/indigo/api/roscpp... ).

EDIT

Editing since the original question changed. I tried the following:

>> rosparam set /test/m '{"id0":0, "id1":1}'    
>> rosparam get /          
     test:   
      m: {id0: 0, id1: 1}
>> rosparam get /test/m
     {id0: 0, id1: 1}
>> rosparam get /test/m/id0
     0
>> rosparam get /test/m/id1
     1

This is explained in http://wiki.ros.org/rosparam#rosparam... , and it basically means that when you give a YAML string to rosparam set, it gets converted in a dictionary of parameters. You can see this behaviour if you do:

>> rosparam set -v /test/m '{"id0":0, "id1":1}'
set parameter [/test/m/id0] to [0]
set parameter [/test/m/id1] to [1]

Therefore the parameter you are looking for in your code (/test//m) doesn't exist as a string, but it's a dictionary! If you want to set a parameter to a string representing a YAML line, you can do something like:

>> rosparam set -v /test/m "\"{'id0':0, 'id1':1}\""
set parameter [/test/m] to [{'id0':0, 'id1':1}]

Even though it looks ugly :)

edit flag offensive delete link more

Comments

Yes I see. Well actually this is very useful to be able to read this as a dictionary. In my case I intended to ive the string to yaml-cpp so using the xml-rpc datastructures is also good, though heavy (as any C++ code :)

courrier gravatar imagecourrier ( 2014-11-26 12:38:22 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

2 followers

Stats

Asked: 2014-11-25 13:04:25 -0500

Seen: 8,182 times

Last updated: Nov 26 '14