Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

One thing that helps me is to write each nodelet/node so that it can be built either (or indeed both!) ways. Put all your functionality into a class with a constructor that takes both the public and private node handles.

We then have this template that generates a thin interface class between the Nodelet code and our implementation:

namespace nodelet_helper{
    template<typename T>
    class TNodelet: public nodelet::Nodelet
    {
    public:
        TNodelet() {};

        void onInit() {
            NODELET_DEBUG("Initializing nodelet");

            m_theT = std::unique_ptr<T>(new T(getNodeHandle(), getPrivateNodeHandle()));
        }

    private:
        std::unique_ptr<T> m_theT;
    };
} // End nodelet_helper namespace

Then, to use it we have code like this:

namespace my_vision_tasks {
    using VisionTaskOneNodelet = nodelet_helper::TNodelet<VisionTaskOne>;
    using VisionTaskTwoNodelet = nodelet_helper::TNodelet<VisionTaskTwo>;
}

PLUGINLIB_EXPORT_CLASS(my_vision_tasks::VisionTaskOneNodelet, nodelet::Nodelet)
PLUGINLIB_EXPORT_CLASS(my_vision_tasks::VisionTaskTwoNodelet, nodelet::Nodelet)

Finally, the XML is:

<library path="lib/libstructure_from_motion_v2_nodelet">
  <class name="my_vision_tasks/VisionTaskOneNodelet" type="my_vision_tasks::VisionTaskOneNodelet" base_class_type="nodelet::Nodelet">
    <description>Task one</description>
  </class>

  <class name="my_vision_tasks/VisionTaskOneNodelet" type="my_vision_tasks::VisionTaskOneNodelet" base_class_type="nodelet::Nodelet">
    <description>Task two</description>
  </class>
</library>

One thing that helps me is to write each nodelet/node so that it can be built either (or indeed both!) ways. Put all your functionality into a class with a constructor that takes both the public and private node handles.

We then have this template that generates a thin interface class between the Nodelet code and our implementation:

namespace nodelet_helper{
    template<typename T>
    class TNodelet: public nodelet::Nodelet
    {
    public:
        TNodelet() {};

        void onInit() {
            NODELET_DEBUG("Initializing nodelet");

            m_theT = std::unique_ptr<T>(new T(getNodeHandle(), getPrivateNodeHandle()));
        }

    private:
        std::unique_ptr<T> m_theT;
    };
} // End nodelet_helper namespace

Then, to use it we have code like this:

namespace my_vision_tasks {
    using VisionTaskOneNodelet = nodelet_helper::TNodelet<VisionTaskOne>;
    using VisionTaskTwoNodelet = nodelet_helper::TNodelet<VisionTaskTwo>;
}

PLUGINLIB_EXPORT_CLASS(my_vision_tasks::VisionTaskOneNodelet, nodelet::Nodelet)
PLUGINLIB_EXPORT_CLASS(my_vision_tasks::VisionTaskTwoNodelet, nodelet::Nodelet)

Finally, the XML is:

<library path="lib/libstructure_from_motion_v2_nodelet">
  <class name="my_vision_tasks/VisionTaskOneNodelet" type="my_vision_tasks::VisionTaskOneNodelet" base_class_type="nodelet::Nodelet">
    <description>Task one</description>
  </class>

  <class name="my_vision_tasks/VisionTaskOneNodelet" type="my_vision_tasks::VisionTaskOneNodelet" name="my_vision_tasks/VisionTaskTwoNodelet" type="my_vision_tasks::VisionTaskTwoNodelet" base_class_type="nodelet::Nodelet">
    <description>Task two</description>
  </class>
</library>