Get and Set ROS Params with rospy and roscpp

In this tutorial you’ll learn how to set and get ROS params with code, inside your nodes. You’ll see how to handle params with both rospy and roscpp.

ROS parameters are quite useful to set global settings for your application. All your nodes can get access to those settings. And the best thing is: you don’t need to change your code or recompile anything if you want to modify a ROS parameter. If you’re new to ROS params, make sure to check what is a ROS parameter.

Get a param

For demonstration purposes, we’ll just set 3 ROS params with the “rosparam” command line tool (very useful if you need to debug your application).

$ rosparam set my_integer 7
$ rosparam set my_float 3.14
$ rosparam set my_string "hello"
$ rosparam list 
/my_float
/my_integer
/my_string
...

You can also start all your parameters and your node from a single launch file (it’s also possible to set all your parameters in a YAML file).

<launch>
    <param name="my_integer" type="int" value="7" />
    <param name="my_float" type="double" value="3.14" />
    <param name="my_string" type="str" value="hello" />

    <node name="node_name" pkg="your_package" type="test_params.py" output="screen"/>
</launch>

Now, let’s get those parameters directly from a node.

Get a param with rospy

Getting a param with rospy is really straightforward:

int_var = rospy.get_param("/my_integer")
float_var = rospy.get_param("/my_float")
string_var = rospy.get_param("/my_string")
rospy.loginfo("Int: %s, Float: %s, String: %s", int_var, float_var, string_var)

The rospy.get_param() function will return the corresponding value from the Parameter Server, that you can directly use or assign to a variable.

If a parameter is not available on the Parameter Server (for example you misspelled it or forgot to launch it), you’ll get a KeyError exception.

You can check if a parameter exists before accessing it:

if rospy.has_param('/my_integer'):
    rospy.get_param('/my_integer')

You can also use a default value if the parameter doesn’t exist:

str_var = rospy.get_param('/my_string', 'this is a default value')

Get a param with roscpp

There are several ways to get a param with roscpp. Let’s keep things simple:

int int_var;
double double_var;
std::string string_var;

ros::param::get("/my_integer", int_var);
ros::param::get("/my_float", double_var);
ros::param::get("/my_string", string_var);

ROS_INFO("Int: %d, Float: %lf, String: %s", int_var, double_var, string_var.c_str());

With roscpp, first you have to declare a variable with the same type as the parameter you want to get. Then, you pass this variable to the ros::param::get() function. This will save the parameter value directly in the variable.

Contrary to rospy, roscpp will not throw an exception if the parameter doesn’t exist. It will simply not set the value inside the variable.

You can check if a parameter exists before accessing it:

if (ros::param::has("/my_string")) {
    ros::param::get("/my_string", string_var);
}

And to use a default value in case the parameter doesn’t exist, simply do that:

std::string default_param;
ros::param::param<std::string>("/my_string", default_param, "default_value");

Set a param

Parameters are usually set before you execute your nodes. But you have to know it’s possible to set a parameter also directly from your code.

Set a param with rospy

rospy.set_param('/another_integer', 12)

Set a param with roscpp

ros::param::set("/another_integer", 5);

Parameter scope

Your parameters can be started in different namespaces. If you looked well, you saw that when you created a parameter with rosparam set my_integer 7, the parameter name on the Parameter Server was in fact “/my_integer”. A slash was automatically added. The slash is the root namespace for parameters.

If you are familiar with the Unix file system, you know that starting a file name with a slash means you’re giving an absolute path. This is the same concept with ROS params.

When you start a node, the node can be running on a given namespace. Depending on the namespaces, there are several ways to get a parameter.

The scope will apply whether you want to get or set a parameter.

Global parameters

Whatever the namespace of your node, you can give an “absolute path” to get any parameter you want. That’s what I used before in this tutorial.

rospy.get_param("/robot1/camera/brightness")
double brightness;
ros::param::get("/robot1/camera/brightness", brightness);

Private parameters

Let’s say you are running your node from the “/robot1/camera” namespace, using this launch file to start all parameters and the node:

<launch>
    <group ns="/robot1/camera">
        <param name="brightness" type="double" value="0.5" />
        <node name="camera_node" pkg="your_package" type="your_executable" output="screen" /> 
    </group>
</launch>

Your parameter global name is now “/robot1/camera/brightness”, which means: the parameter “brightness” is in the “camera” namespace, which is itself in the “robot1” namespace.

You also start your camera_node from the “/robot1/camera” namespace. So, you can directly get the “brightness” parameter without having to give the absolute namespace path.

# Global
rospy.get_param("/robot1/camera/brightness")

# Private 
rospy.get_param("~brightness")
double brightness;

// Global
ros::param::get("/robot1/camera/brightness", brightness);

// Private
ros::param::get("~brightness", brightness);

This is very handy for creating nodes that you use as modules. You can put those nodes in whatever namespace you want. With private parameters you’ll always be sure that you get the right parameters with the right values.

1 thought on “Get and Set ROS Params with rospy and roscpp”

Leave a Comment