iohannes
Published on 2025-04-14 / 5 Visits

ros轻量节点nodelet

1. nodelet

nodelet 是 ROS 中一种轻量级的进程内通信机制,用于在同一个进程中运行多个节点,从而减少进程间通信的开销。nodelet 插件共享同一个进程空间,可以访问相同的资源(如内存、线程池等),从而减少资源的重复分配和通信开销。用于提高性能,特别是在处理大量数据(如点云数据)时。
nodelet::Nodelet 是所有 nodelet 插件的基类,提供了基本的初始化和生命周期管理功能。

2. 创建 Nodelet

// my_nodelet.cpp
#include <nodelet/nodelet.h>
#include <ros/ros.h>

namespace my_nodelet
{
    class MyNodelet : public nodelet::Nodelet
    {
    public:
        MyNodelet() {}
        ~MyNodelet() {}

    private:
        virtual void onInit()
        {
            nh_ = getNodeHandle();
            pnh_ = getPrivateNodeHandle();

            // 获取参数
            std::string param;
            if (pnh_.param("example_param", param, std::string("default_value")))
            {
                ROS_INFO_STREAM("Got parameter: " << param);
            }
            else
            {
                ROS_INFO_STREAM("Using default parameter value: default_value");
            }

            // 初始化其他资源
            ROS_INFO("MyNodelet initialized");
        }

        ros::NodeHandle nh_;
        ros::NodeHandle pnh_;
    };
}

// Register as nodelet
#include <pluginlib/class_list_macros.h>
PLUGINLIB_EXPORT_CLASS(my_nodelet::MyNodelet, nodelet::Nodelet)

3. 创建 CMakeLists.txt

// CMakeLists.txt
cmake_minimum_required(VERSION 3.0.2)
project(my_nodelet_package)

find_package(catkin REQUIRED COMPONENTS
  roscpp
  nodelet
  pluginlib
)

catkin_package(
  INCLUDE_DIRS include
  LIBRARIES my_nodelet
  CATKIN_DEPENDS roscpp nodelet pluginlib
)

include_directories(
  include
  ${catkin_INCLUDE_DIRS}
)

add_library(my_nodelet src/my_nodelet.cpp)
target_link_libraries(my_nodelet ${catkin_LIBRARIES})

4. 创建nodelet_plugins.xml文件

<library path="lib/libmy_nodelet">
  <class name="my_nodelet_package/MyNodelet" type="my_nodelet::MyNodelet" base_class_type="nodelet::Nodelet">
    <description>
      This is my custom nodelet.
    </description>
  </class>
</library>

创建 package.xml 文件

<package>
  <name>my_nodelet_package</name>
  <version>0.0.1</version>
  <description>The my_nodelet_package package</description>

  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>nodelet</build_depend>
  <build_depend>pluginlib</build_depend>
  <exec_depend>roscpp</exec_depend>
  <exec_depend>nodelet</exec_depend>
  <exec_depend>pluginlib</exec_depend>
</package>

<export>
  <nodelet plugin="${prefix}/nodelet_plugins.xml" />
</export>

5. 编写launch文件

<launch>
  <!-- 启动Nodelet管理器 -->
  <node pkg="nodelet" type="nodelet" name="nodelet_manager" args="manager" output="screen" />

  <!-- 加载Nodelet -->
  <node pkg="nodelet" type="nodelet" name="my_nodelet" args="load my_nodelet_package/MyNodelet nodelet_manager" output="screen">
    <!-- 传递参数 -->
    <param name="example_param" type="string" value="custom_value" />
  </node>
</launch>

6. 启动Nodelet

roslaunch my_nodelet_package my_nodelet.launch

7. 多个节点按顺序启动

控制多个nodelet的启动顺序可以通过在launch文件中合理组织节点的加载顺序来实现。

<launch>
  <!-- 启动Nodelet管理器 -->
  <node pkg="nodelet" type="nodelet" name="nodelet_manager" args="manager" output="screen" />

  <!-- 加载第一个Nodelet -->
  <node pkg="nodelet" type="nodelet" name="nodelet1" args="load my_nodelet_package/Nodelet1 nodelet_manager" output="screen">
    <param name="param1" type="string" value="value1" />
  </node>

  <!-- 加载第二个Nodelet -->
  <node pkg="nodelet" type="nodelet" name="nodelet2" args="load my_nodelet_package/Nodelet2 nodelet_manager" output="screen">
    <param name="param2" type="string" value="value2" />
  </node>

  <!-- 加载第三个Nodelet -->
  <node pkg="nodelet" type="nodelet" name="nodelet3" args="load my_nodelet_package/Nodelet3 nodelet_manager" output="screen">
    <param name="param3" type="string" value="value3" />
  </node>
</launch>