ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question

Real OO in ROS/C++?

asked 2016-09-06 12:58:32 -0500

Borob gravatar image

updated 2016-09-07 00:52:10 -0500


What is your best practice when designing OO architectures?

  1. Are you designing real C++ classes and serialize to messages and let class functions call messages?

  2. Or are you just writing the nodes while offering services/topics? So that the node is the object and the services its functions?

One important point for me is how different class instances communicate over ros' messaging system.

Suppose this problem in OO world:

Two classes: Rover, World Three objects: Rover1, Rover2, World1

So lets say World holds information about the world, and offers a functions that would simply give me the world's state. Lets say the rovers have several fields as parameters like size, model, weight, current_position, etc. and functions such as go_to, pick_up, etc. Functions that act like those would call services in ros.

If each object would maintain a node and I initialized the three objects, how would one node know what their affiliated object's fields are?

E.g. lets say two rovers are supposed to interact, so Rover1 wants to tell Rover2 "go_to(...)". Rover1 calls the service of Rover2, but at this point we do not arrive at a initialized instance of a class, but at the class code. So from this, I can't infer what weight or model of a rover this is.

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted

answered 2016-09-06 18:54:03 -0500

Mark Rose gravatar image

ROS message types do not have behavior associated with them; they are containers of the message header and payload. I've found it useful to design most of my nodes using message-passing rather than services, unless synchronous execution is required.

Generally the main node code extracts the message parameters and delegates to real classes for the work. The main node code, which may also be a class, handles the ROS communication. I've found it useful to leave ROS out of the classes that do the work, making them easier to unit test.

The ROS C++ style guide does not give specific guidance, but the Python style guide agrees with my comments above.

In response to your specific questions:

  1. I am designing real C++ classes to implement the behaviors. Generally I'm using message passing in the main node code to communicate with other nodes, rather than exposing services. The messages have no behavior, so code cannot "call messages".

  2. The node is the object exposed to the outside world. You can think of messages as method invocations, but they have specific semantics different from normal member functions: subscriber callbacks operate in their own thread, and they get a single parameter, the message received.

edit flag offensive delete link more


Thank you very much! I updated my origininal question to reflect more of what my big problem with this is.

Borob gravatar image Borob  ( 2016-09-07 00:52:52 -0500 )edit

Even in traditional OO I think your example is flawed. Generally you want to decouple objects as much as possible, not letting them access each other's fields. The message passing in ROS is a way to enforce encapsulation and decoupling, while increasing the flexibility of node implementation.

Mark Rose gravatar image Mark Rose  ( 2016-09-07 17:55:37 -0500 )edit

For example, it's fine for Robot 1 to publish a goal state for robot 2, but robot 1 shouldn't be planning for robot 2. Either let the robots plan for themselves, or encapsulate into a planner node like move_base. The planner may need additional info about robot characteristics.

Mark Rose gravatar image Mark Rose  ( 2016-09-07 17:57:17 -0500 )edit

In a typical ROS setup, your "world" object would be handled by several nodes: a map server, a planner like move_base that updates and uses the map, a publisher of robot state, a robot controller, and something that publishes obstacle distances (scan or point cloud), among others.

Mark Rose gravatar image Mark Rose  ( 2016-09-07 17:59:18 -0500 )edit

Some of your robot characteristics would probably be encoded in URDF and published by robot_state_publisher and joint_state_publisher. Many of these interactions would be asynchronous, via message passing, rather than using services.

Mark Rose gravatar image Mark Rose  ( 2016-09-07 18:01:12 -0500 )edit

You can use OOD all you want within a node, but the relationship between nodes is more like communicating processes than pure OOP. Interactions using messages are more like Web programming with node.js than RPCs. It's a different communication paradigm, but a highly useful one.

Mark Rose gravatar image Mark Rose  ( 2016-09-07 18:05:21 -0500 )edit

Awesome thank you!

Borob gravatar image Borob  ( 2016-09-07 23:57:15 -0500 )edit

Question Tools



Asked: 2016-09-06 12:58:32 -0500

Seen: 485 times

Last updated: Sep 07 '16