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

How to port a node to nodelet as easy as possible?

asked 2019-11-14 19:34:58 -0500

PapaG gravatar image

I have a problem where I am having to compare PointCloud2 where all my clouds are currently coming from a nodelet. As I understand nodelets pass data around with addresses rather than chewing memory and so for a structure such as many clouds, passing this data around nodelets in the same manager would be more efficient. Is there an easy way to take an existing node and write it as a nodelet?

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
0

answered 2019-11-15 04:21:46 -0500

Delb gravatar image

updated 2019-11-15 04:22:22 -0500

There are no "easy" ways, you just need to follow the different steps described in the wiki and it shouldn't be too difficult. I will expand on each point to make it clear because I already had some trouble with it in the past (you can also check this really simple example) :

  • add the necessary #includes :

    #include <nodelet/nodelet.h>
    #include <pluginlib/class_list_macros.h>
    
  • get rid of int main()

You don't need it anymore since your program will be run via roslaunch and the different functions can be called from the the method onInit() (which is described under).

  • subclass nodelet::Nodelet

This means your class needs to inherit from nodelet::Nodelet like this :

class TestNodelet : public nodelet::Nodelet
  • move code from constructor to onInit()

The method onInit is called by the nodelet manager to initialize every nodelet. This method is defined as virtual in the Nodelet class API which means that you must declare this method every time you create a nodelet (in private). You will initialize everything in this method, like the nodehandle and your pub/sub or even your threads if you want.

  • add the PLUGINLIB_EXPORT_CLASS macro

Just add this at the end of your file (but within the namespace if you have one) :

PLUGINLIB_EXPORT_CLASS(test::TestNodelet, nodelet::Nodelet);
  • add <build_depend> and <run_depend> dependencies on nodelet in the package manifest.

Just add this in package.xml :

  <build_depend>pluginlib</build_depend>
  <build_depend>nodelet</build_depend>
  <exec_depend>pluginlib</exec_depend>
  <exec_depend>nodelet</exec_depend>
  • add the <nodelet> item in the <export> part of the package manifest

Still in package.cml, add this :

  <export>
      <nodelet plugin="${prefix}/plugins/nodelets.xml"/>
  </export>
  • create the .xml file to define the nodelet as a plugin

Create a folder plugins and add into it the file nodelets.cml :

<library path="lib/libtest_nodelet">
  <class name="your_package/TestNodelet"
         type="test::TestNodelet"
         base_class_type="nodelet::Nodelet">
    <description>
      Node to nodelet test
    </description>
  </class>
</library>
  • make the necessary changes to CMakeLists.txt (comment out a rosbuild_add_executable, add a rosbuild_add_library)

You need to add the same package as in the package.cml first :

find_package(catkin REQUIRED COMPONENTS
  roscpp
  pluginlib 
  nodelet 
)

And then you just need to define the nodelet as a library and link it :

# Nodelet library
add_library(test_nodelet src/test.cpp)
add_dependencies(test_nodelet ${PROJECT_NAME})
target_link_libraries(test_nodelet ${catkin_LIBRARIES})

So your code should be like this :

#include "ros/ros.h"
#include "std_msgs/String.h"
#include <nodelet/nodelet.h>
#include <pluginlib/class_list_macros.h>

namespace test {

/*********************
** Nodelet
**********************/
class TestNodelet : public nodelet::Nodelet
{
    public:
        TestNodelet()
        {
        }

    private:
        virtual void onInit()
        {
            ros::NodeHandle& private_nh = getPrivateNodeHandle();
            pub = private_nh.advertise<std_msgs::String>("out", 10);
            sub = private_nh.subscribe("in", 10, &TestNodelet::callback, this);
        }
        ros::Publisher pub;
        ros::Subscriber sub;

        void callback(const std_msgs::String::ConstPtr& input)
        {
            std_msgs::String output;
            output.data = input->data;
            pub.publish(output);
        }
};
PLUGINLIB_EXPORT_CLASS(test::TestNodelet, nodelet::Nodelet);
}

Now you just have to create a launch file with a nodelet manager and your nodelet :

<launch>
  <node pkg="nodelet" type="nodelet" name="nodelet_manager"  args="manager" output="screen"/>

  <node pkg="nodelet" type="nodelet" name="test" args="load your_package/TestNodelet ...
(more)
edit flag offensive delete link more

Question Tools

2 followers

Stats

Asked: 2019-11-14 19:34:58 -0500

Seen: 1,038 times

Last updated: Nov 15 '19