Parameters, namespaces, and remapping
The runtime configuration system that keeps your code portable across robots. Declare a parameter once; set it from launch, CLI, YAML, or dynamic reconfigure. Remap topics to fit any neighbor.
A ROS 2 node hardcoding its config is a node that runs on exactly one robot. Parameters and remapping are how you write a node once and deploy it across robots, simulators, and generations of hardware. Understanding them turns "I have to fork this code" into "I'll change a YAML file."
Parameters: the configuration system
A parameter is a named, typed value owned by a node, settable at launch and (mostly) at runtime. Unlike topic data, parameters change rarely — wheel radius, control gains, sensor topic name. The framework gives you discoverability, type checking, and changeability for free.
Declare it in the node
class MyNode(Node):
def __init__(self):
super().__init__('my_node')
self.declare_parameter('wheel_radius', 0.06)
self.declare_parameter('cmd_topic', '/cmd_vel')
self.declare_parameter('use_imu', True)
self.r = self.get_parameter('wheel_radius').value
self.cmd_topic = self.get_parameter('cmd_topic').value
Three parameters declared with default values. ROS 2 enforces declaration — undeclared get_parameter calls fail. (Unless you set allow_undeclared_parameters=True, which you should not.)
Set it at launch
Three options, in order of how they're used:
1. YAML file (preferred for production):
# config/my_robot.yaml
my_node:
ros__parameters:
wheel_radius: 0.058
cmd_topic: /cmd_vel_safe
use_imu: true
Node(
package='my_robot', executable='my_node',
parameters=[PathJoinSubstitution([FindPackageShare('my_robot'), 'config', 'my_robot.yaml'])],
)
2. Inline in launch (for one-offs):
Node(
package='my_robot', executable='my_node',
parameters=[{'wheel_radius': 0.058, 'use_imu': False}],
)
3. Command-line (for testing):
ros2 run my_robot my_node --ros-args -p wheel_radius:=0.058
Read or change at runtime
ros2 param list /my_node
ros2 param get /my_node wheel_radius
ros2 param set /my_node wheel_radius 0.062
ros2 param dump /my_node # snapshot current values
Whether the change takes effect depends on whether the node has registered a parameter callback. By default, parameters can be set but the node won't re-read them. Add a callback for dynamic reconfigure:
self.add_on_set_parameters_callback(self.on_param_change)
def on_param_change(self, params):
for p in params:
if p.name == 'wheel_radius' and p.value > 0:
self.r = p.value
self.get_logger().info(f'wheel_radius updated to {self.r}')
return SetParametersResult(successful=True)
Namespaces: organizing nodes by group
A namespace prefixes a node's name and all its topics, services, parameters. Useful when running multiple instances of the same node (e.g., one camera node per camera).
Node(
package='cam_driver', executable='cam_node',
namespace='left_cam',
)
Node(
package='cam_driver', executable='cam_node',
namespace='right_cam',
)
The two camera nodes now expose /left_cam/image_raw and /right_cam/image_raw instead of clashing on /image_raw. Their parameters are /left_cam/cam_node and /right_cam/cam_node.
Inside a node, topics declared with relative names (image_raw, no leading /) automatically pick up the namespace. Topics declared with absolute names (/image_raw) ignore it. The default-relative behavior is what makes namespaces work without the node code knowing.
Remapping: rewiring topics without code changes
You have a node that publishes to /cmd_vel. Your robot's base driver listens on /diff_drive_controller/cmd_vel_unstamped. Two options: change the node, or remap.
Node(
package='nav2_controller', executable='controller_server',
remappings=[('cmd_vel', '/diff_drive_controller/cmd_vel_unstamped')],
)
The node's internal name cmd_vel now resolves externally to /diff_drive_controller/cmd_vel_unstamped. The node code doesn't change.
Remapping syntax: internal_name:=external_name. Works on topics, services, and actions.
From the command line:
ros2 run nav2_controller controller_server --ros-args -r cmd_vel:=/diff_drive_controller/cmd_vel_unstamped
The four-way table for "where do I configure this?"
| Concern | Tool |
|---|---|
| Numeric / typed value | Parameter |
| Topic name doesn't match | Remapping |
| Multiple instances of same node | Namespace |
| Need to change at runtime | Parameter + callback |
Common gotchas
- Re-declaring causes errors.
declare_parametertwice on the same name throws. Usehas_parameterif conditional. - YAML namespace mismatch. The YAML file's top key must match the fully-qualified node name.
my_nodevs/left_cam/my_nodematters. - Topic remapping doesn't follow into wrappers. If your node spawns sub-nodes, they don't inherit remappings unless you set them up.
- Wildcard YAML:
"/**":as the top key applies to every node — useful for shared params likeuse_sim_time. - Param names use slashes:
"controller.gains.kp"is a flat name with dots; only namespaces use slashes.
Patterns that scale
- One YAML per role:
config/sim.yaml,config/real.yaml,config/calib.yaml. Pick at launch time. - Inherit common values: import a common YAML, override specific nodes.
YamlIncludeFilein launch files. - Validate at startup: range-check critical parameters in the constructor; fail loudly if invalid.
- Log loaded values: print every parameter you read on startup. Saves "is the YAML even being read?" debugging later.
Why the discipline pays off
Ninety percent of "this works on my machine" robotics bugs are unconfigured parameters or wrong topic names. Force every node to declare every parameter; load every parameter from a YAML; remap topics rather than rename them in code. Once this is the habit, integrating someone else's node into your robot becomes a 30-minute YAML exercise instead of a fork.
Exercise
Take any small ROS 2 node from a tutorial. Replace every hardcoded value with a parameter. Replace every hardcoded topic name with a relative name. Write a YAML file. Launch with the YAML; verify it works. Now copy the launch file, change the YAML to a different config, launch a second instance with a different namespace. Two configurations of the same node, no code change.
Next
Nav2 — the mobile-navigation stack that uses every parameter and remapping idiom in this lesson.
Comments
Sign in to post a comment.