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

Using same code to make a Node and Nodelet

asked 2012-08-23 05:26:40 -0600

John Hoare gravatar image

updated 2012-08-24 01:31:41 -0600

Has anyone implemented some sort of "standard" interface that you could code to, which could then generate both a standalone Node, and a Nodelet?

My main driver for this is that in my experience you can not unload a nodelet from the nodelet manager, or have the nodelet manager re-load the shared library that your nodelet lives in. For development, it's easier to build your code as a Node, and when you're comfortable that it is working, then change it to a nodelet.

Edit: It looks like as of Fuerte this is no longer true (although I haven't yet tried it out.) As long as a 1:1 mapping of library to nodelet is built, the nodelet manager (via pluginlib) should unload the library if all the nodelets in the library are no longer being used. (http://ros.org/reps/rep-0116.html) However, similar issues will occur if you are using two nodelets from the same library, and only want to modify one of them. (E.g. only shutting off one nodelet will not cause the shared library to be unloaded, and so the out of date version of the modified nodlet will be the one that the manager starts.)

edit retag flag offensive close merge delete

Comments

"can not unload a nodelet from the nodelet manager" - is this not exactly part of the functionality that the nodelet manager provides? Can you perhaps clarify a bit better what your problem is?

Daniel Stonier gravatar image Daniel Stonier  ( 2012-08-23 16:43:54 -0600 )edit

That makes more sense. I don't think there is a way around the out of date issue - that seems to be a reasonable expectation of the way things work. I never run into the issues though as I've always done nodelets and libraries in 1:1 fashion. I haven't noticed any significant drawbacks in doing so.

Daniel Stonier gravatar image Daniel Stonier  ( 2012-08-26 04:01:53 -0600 )edit

2 Answers

Sort by ยป oldest newest most voted
10

answered 2012-08-23 07:37:07 -0600

jbohren gravatar image

The pattern I tend to use is to just implement the core processing in another class whose constructor takes a NodeHandle as an argument. Then I build that class into a library and implement very thin wrappers for the node and nodelet that instantiate that class.

edit flag offensive delete link more
4

answered 2012-08-23 16:53:23 -0600

Daniel Stonier gravatar image

updated 2012-08-26 04:03:26 -0600

If you build something as a nodelet - you should be able to run it in two ways

  1. As part of a group of nodelets under a Nodelet Manager
  2. As a standalone node

Once I make a nodelet, reproducing it as a node is redundant. Some history: nodelets came after nodes once they realised there was a need. Their implementation (nodelets can detect when communications are intra or inter and behave accordingly) was such that the node actually became superflous. But we still have nodes because people are familiar with them and they are a little easier to code.

An example standalone nodelet launcher:

<launch>
    <node pkg="nodelet" type="nodelet" name="navi_base" args="standalone goo/GooNodelet">
        <rosparam file="$(find goo)/resources/yaml/navi_base.yaml" command="load" />
    </node>
</launch>

If instead, you wish the classes in your library to be more widely available to different systems, then jbohren's method is a good way of making that possible. However, I don't think that's strictly necessary. A library in ros can have two api's:

  1. a c++ api (like your regular old standard library)
  2. a ros comms api (msgs, srvs and actions)

If you expose your interface via ros comms through a nodelet, then you don't need to expose a c++ api simultaneously. And if you're using nodelets, you don't have to worry about this communciation being significantly slower. Mixing in a c++ api doesn't provide any appreciable benefit.

Sometimes however you need to provide only a c++ api to clients (i.e. non ros users). Then you need to get rid of the ros components completely. We do that occasionally - and if we want to use the same library in a ros system, we create a separate nodelet library which wraps the c++ library. Nodelet subscriber callbacks can utilise the c++ api directly, whereas publishers can be triggered by mechanisms like signals (sigslots) coming from the c++ library.

edit flag offensive delete link more

Comments

What do you mean running it as a standalone node? How is this actually achieved? I'm sure you could have it run its own unique nodelet manager and load the single nodelet in. Is that what you're implying, or is there something else I'm not seeing?

John Hoare gravatar image John Hoare  ( 2012-08-24 01:29:56 -0600 )edit

The nodelet manager lets you run either way - do the following: 'roscd nodelet/bin; ./nodelet --help'. There are launch files everywhere which are enlightening as well. I'll update my post above with some examples.

Daniel Stonier gravatar image Daniel Stonier  ( 2012-08-24 01:42:14 -0600 )edit

With respect to why we still have nodes, we currently also have no way to introspect on the internal communication graph of a collection of nodelets in the same manager.

jbohren gravatar image jbohren  ( 2012-08-24 01:53:24 -0600 )edit

Yes, it's difficult to introspect inside a nodelet group, but that is not my meaning. My understanding is that standalone nodes are fundamentally equivalent to a node. Hence nodelet code can be used for two purposes (intra and inter), nodes only one of those - hence nodes are effectively redundant.

Daniel Stonier gravatar image Daniel Stonier  ( 2012-08-24 02:06:10 -0600 )edit

@snorri Yeah, a standalone nodelet is just like a node, but is definitely more complex.

jbohren gravatar image jbohren  ( 2012-08-24 04:21:58 -0600 )edit

My main concern is that this approach (and the other) requires a lot of "boilerplate" code, and my question was mostly referring to avoiding creating this boilerplate code. @snorri 's approach requires boilerplate code in the form of launch files, and @jbohren is implementing the node & nodelets.

John Hoare gravatar image John Hoare  ( 2012-08-27 05:02:57 -0600 )edit

Question Tools

Stats

Asked: 2012-08-23 05:26:40 -0600

Seen: 2,405 times

Last updated: Aug 26 '12