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

Best practices for dynamically changing topic name

Hi everyone,

while developing new robots/features there’s often the need to override some data in the system for testing purposes.

Let’s consider the following examples:

  • You add a new sensor to your robot and the output of this sensor are N distinct values. You may want to force one or more of these N values to be something else from what is actually reported.
  • You have an estimator that periodically returns a boolean value and you may want to force it to a specific value.
  • You have a component that takes N different inputs and you want to fake/override a subset of them.

This is straight-forward to do with functional APIs.
You can add your “override” public function in the components:

void override_data(bool enable, bool fake_data)
{
    m_should_override = enable;
    m_fake_data = fake_data;
}

bool get_data()
{
      if (m_should_override) {
          return m_fake_data;
      } else {
          return m_real_data;
      }
}

Despite being very straight-forward to implement, this approach has several drawbacks.
In particular it does not scale well if you want to be able to override a lot of features and it mixes together the production code with the test code.

ROS and pub-sub mechanisms should allow for a better way for doing that.
Using pub-sub, the example above would have a publisher that will periodically send the boolean data on a topic /my_data.
The rest of the system will be subscribing to /my_data.

The same approach as above could be implemented using a ROS service to handle the override_data() function logic. However, this would not solve any of the drawbacks (and it would add overhead to the system).

Another solution could be to create alternative node implementations that are used only for testing.
However this would be very difficult to maintain, especially if you only want to override a subset of functionalities (e.g. 1 publisher in a node, or 1 field inside a message publication).

A better approach could consists in “remapping” and “intercepting” existing topics.
If that node would publish on /my_data_tmp rather than on /my_data we could create a new node (that can also live on a separate machine) that subscribes to /my_data_tmp and republishes the overridden values into /my_data.
The code on the robot would have no idea that something is being overridden.
All the override logic could also be owned by a separate team from who owns the actual robot code.

What do you think?
Lately we have been looking at how to implement such remapping approach and we came across some challenges.
We considered various approaches:

  • Use command line remapping arguments. This approach requires the whole node where the overridden topic leaves to be destroyed and reconstructed. This may not be possible in some situations and moreover you would lose the internal state of the node.
  • Use node parameters with topic names. Although these are not the standard way for remapping topics, they currently provide more flexibility than remapping arguments.

However, even with node parameters, there’s still the problem of how to use the updated topic name?

If the node that owns the topic we want to override is a lifecycle node, we could transition it back to the unconfigured state and then re-configure it again. This is definitely easier to do than destroying and reconstructing the node, however you would still lose the internal state of the node.

An alternative may be to have a parameter callback that will take care of destroying and reconstructing only the specific entity (e.g. publisher) whose topic we want to remap.
This operation would preserve the state of the node, but it’s definitely more error-prone.

Considering a lifecycle node, we should make sure that the node is not in the active state while this operation happens.
Moreover, even if we are currently inactive (and so there is no risk of the node trying to use the publisher while we destroy it) the lifecycle nodes guidelines suggest that entities should be allocated/deallocated in the on_configure step.

Has any of you had similar problems?
What do you think is the best way for remapping topic names dynamically?
Do you think that new remapping APIs should be added to ROS ?

3 Likes