How to use nodelets in ROS

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

How to use nodelets in ROS

Megacephalo
Hi,

I've been reading RTABMap_ros ROSWiki about the nodelets, and the official tutorials on nodelet, but still left some qustions unanswered. Would you kindly clear my doubts?

1. How do you use Rtabmap nodelets in Launch files? Why some of these nodelets depend on a manager and others are simply "standalone nodelets"? What are the differences between these two kinds?

2. On ROS documentation, it says that nodelets are C++ nodes which are designed to provide a way to run multiple algorithms on a single machine, in a single process, without incurring copy costs when passing messages intraprocess. If that is the case, ROS' very own framework should have resolved copy cost issue in the first place, left me wondering what true role nodelets play here?

3. What is/are the reason(s) that you developped certain functionalities as nodelets and others as nodes? Is it because you can implememt several functiomalities within a single nodelet for effective maintanence?

These are my questions on nodelets. Your answers mean so much to me. Thank you in advance!
Reply | Threaded
Open this post in threaded view
|

Re: How to use nodelets in ROS

matlabbe
Administrator
Hi,

1. A nodelet always requires a manager. We can see the manager as a node, in which we can put nodelets that will run in the same process. When you use a nodelet in a launch file, you have the choice to attach it to a manager or create it as a standalone nodelet (it will create its own manager). A standalone nodelet works exactly like a node and can be used in a launch file like that (note the "standalone" argument):
<node pkg="nodelet" type="nodelet" name="points_xyzrgb" args="standalone rtabmap_ros/point_cloud_xyzrgb"/>
For efficiency, if you want to create a point cloud from openni messages a lower rate, you may want to put the nodelets in the nodelet manager of openni (called "camera_nodelet_manager"):
<include file="$(find openni)/launch/openni.launch"/>
<group ns="camera">
    <!-- Throttling openni images at 5 Hz -->
    <node pkg="nodelet" type="nodelet" name="data_throttle" args="load rtabmap_ros/data_throttle camera_nodelet_manager">
      <param name="rate" type="double" value="5"/>
   
      <remap from="rgb/image_in"       to="rgb/image_rect_color"/>
      <remap from="depth/image_in"     to="depth_registered/image_raw"/>
      <remap from="rgb/camera_info_in" to="depth_registered/camera_info"/>
    
      <remap from="rgb/image_out"       to="rgb/image_rect_color_throttled"/>
      <remap from="depth/image_out"     to="depth_registered/image_raw_throttled"/>
      <remap from="rgb/camera_info_out" to="depth_registered/camera_info_throttled"/>
    </node>

    <!-- Create point clouds -->
    <node pkg="nodelet" type="nodelet" name="points_xyzrgb" args="load rtabmap_ros/point_cloud_xyzrgb camera_nodelet_manager">
      <remap from="rgb/image"        to="rgb/image_rect_color_throttled"/>
      <remap from="depth/image"      to="depth_registered/image_raw_throttled"/>
      <remap from="rgb/camera_info"  to="depth_registered/camera_info_throttled"/>
    </node>
</group>
Note that rgbd_launch (which openni includes) uses a lot the nodelets if you need more examples.

2. The copy cost issue is why nodelets exist. If you have algorithms running in different processes (different nodes), they should serialize/deserialize messages between them (over TCP/IP). If they run in the same process as nodelets in the same manager, the message can be copied directly in memory between the processes (I think they are not even deep copied if they use smart pointers) without serialization/deserialization. Generally, I use nodelets when I have algorithms on the same machine exchanging data at high framerate and/or that have large size (algorithms connected to openni is a good example, which process images at high frame rate).

3. In RTAB-Map, most nodelets are intended to be used with data coming from openni. Other nodes are used with data at a lower framerate. For convenience, I've seen other projects creating all algorithms as nodelets, but they provide also node wrappers, so you have the choice to use the nodelet interface or the node interface in the launch file.

cheers
Reply | Threaded
Open this post in threaded view
|

Re: How to use nodelets in ROS

Megacephalo
This post was updated on .
Hi Mathieu,

Thank you for your reply. About your answer to the second question, may I ask you one more question.
So, as I understood, if all nodes or processes are arranged in the manner as shown in Figure 1,

                                                                    Fig 1.


That is to say, if there are N threads registering to a single driver, then there are 1 serialization and N deserialization. However, if we arrange all threads into a single nodelet, then we can effectively reduce the number of deserialization, as shown in Figure 2

                                                                   Fig 2.


with one manager registering to the driver, then we only have one serialization and one deserialization from driver to the manager, and the latter would give N copies to every subscribed thread. And here my question is, according to what you mentioned, Is the kind of copy a "call by value", then how can it reduce copy cost? If it is so, is each copy independent from each other? i.e. Thread A receives a copy from manager, process the copy and pass down to thread B, then B would not receive the very same copy as A does from the manager.

Thank you so much !
Reply | Threaded
Open this post in threaded view
|

Re: How to use nodelets in ROS

matlabbe
Administrator
Hi,

From the nodelet documentation:

"Nodelets are designed to provide a way to run multiple algorithms on a single machine, in a single process, without incurring copy costs when passing messages intraprocess. roscpp has optimizations to do zero copy pointer passing between publish and subscribe calls within the same node."
...
"Any communications between them can use the zero copy roscpp publish call with a boost shared pointer."

So, only a pointer to data is shared between the nodelets. I think that if a nodelet publishes a pointer, it should not modify the content after that as the subscribers will read the same data.

cheers