ROS中nodelet的使用
1. 为什么使用nodelet?
Nodelet提供了一种方法,可以在同一台计算机上,在同一个进程内,运行多个算法,且在进程内消息传递时不产生复制成本(zero copy)。在一个node里面,roscpp利用指针传递可以实现在publish和subscribe调用时的零拷贝。为了实现相似的效果,多个nodelets允许将多个类动态加载到同一个node里,同时还提供独立的命名空间,从而使得这些nodelets尽管运行在同一个进程里,但却仍然像单独的node一样工作。也就实现了“在一个进程(node)里运行多个nodelet”的效果。
因此,大通量数据流可能包含多个nodelet,此时若将他们加载到同一个进程里,就可以避免数据拷贝和网络传输。
2. 在ROS工程中使用nodelet
2.1 创建工作空间和程序包
mkdir -p ~/catkin_ar/src
cd catkin_ar/
catkin_make
source devel/setup.sh
cd src
catkin_create_pkg try_nodelet roscpp rospy nodelet std_msgs sensor_msgs cv_bridge image_transport ddynamic_reconfigure
2.2 创建并且编写cpp文件与hpp文件
//try_use.hpp
#pragma once
#include <nodelet/nodelet.h>
#include <ros/ros.h>
namespace try_nodelet
{
class try_use : public nodelet::Nodelet
{
public:
virtual void onInit();
};
}
//try_use.cpp
#include <pluginlib/class_list_macros.h>
#include <../include/try_nodelet/try_use.hpp>
PLUGINLIB_EXPORT_CLASS(try_nodelet::try_use,nodelet::Nodelet)
namespace try_nodelet
{
void try_use::onInit()
{
NODELET_DEBUG("Initializing nodelet...");
ROS_INFO("Nodelet is Ok for test!!");
}
}
2.3 编写nodelet_plugins.xml
<library path="lib/libtry_nodelet">
<!--上面这个try_nodelet是包的名字,下面的那个是命名空间的名字-->
<class name="try_nodelet/try_use" type="try_nodelet::try_use" base_class_type="nodelet::Nodelet">
<description>
Trying to use nodelet in ROS.
</description>
</class>
</library>
2.4 修改CMakeLists.txt与package.xml
修改CMakeLists.txt
cmake_minimum_required(VERSION 3.0.2)
project(try_nodelet)
add_compile_options(-std=c++11)
#上面这个最好加上,否则可能会编译失败
find_package(catkin REQUIRED COMPONENTS
cv_bridge
ddynamic_reconfigure
image_transport
nodelet
roscpp
rospy
sensor_msgs
std_msgs
)
catkin_package(
INCLUDE_DIRS include
LIBRARIES try_nodelet
CATKIN_DEPENDS cv_bridge ddynamic_reconfigure image_transport nodelet roscpp rospy sensor_msgs std_msgs
# DEPENDS system_lib
)
include_directories(
include
${catkin_INCLUDE_DIRS}
)
add_library(${PROJECT_NAME}
src/try_use.cpp
)
add_dependencies(
${PROJECT_NAME}
${${PROJECT_NAME}_EXPORTED_TARGETS}
${catkin_EXPORTED_TARGETS}
)
修改package.xml
<?xml version="1.0"?>
<package format="2">
<name>try_nodelet</name>
<version>0.0.0</version>
<description>The try_nodelet package</description>
<maintainer email="npu-lqx@todo.todo">npu-lqx</maintainer>
<license>TODO</license>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>cv_bridge</build_depend>
<build_depend>ddynamic_reconfigure</build_depend>
<build_depend>image_transport</build_depend>
<build_depend>nodelet</build_depend>
<build_depend>roscpp</build_depend>
<build_depend>rospy</build_depend>
<build_depend>sensor_msgs</build_depend>
<build_depend>std_msgs</build_depend>
<build_export_depend>cv_bridge</build_export_depend>
<build_export_depend>ddynamic_reconfigure</build_export_depend>
<build_export_depend>image_transport</build_export_depend>
<build_export_depend>nodelet</build_export_depend>
<build_export_depend>roscpp</build_export_depend>
<build_export_depend>rospy</build_export_depend>
<build_export_depend>sensor_msgs</build_export_depend>
<build_export_depend>std_msgs</build_export_depend>
<exec_depend>cv_bridge</exec_depend>
<exec_depend>ddynamic_reconfigure</exec_depend>
<exec_depend>image_transport</exec_depend>
<exec_depend>nodelet</exec_depend>
<exec_depend>roscpp</exec_depend>
<exec_depend>rospy</exec_depend>
<exec_depend>sensor_msgs</exec_depend>
<exec_depend>std_msgs</exec_depend>
<export>
<nodelet plugin="${prefix}/nodelet_plugins.xml" />
</export>
</package>
3.启动ROS节点
3.1 编写launch文件进行快速启动
新建一个launch文件夹,并在文件夹中新建一个start.launch文件
<launch>
<node pkg="nodelet" type="nodelet" name="standalone_nodelet" args="manager" output="screen"/>
<node pkg="nodelet" type="nodelet" name="using_nodelet" args="load try_nodelet/try_use standalone_nodelet" output="screen">
</node>
</launch>
3.2 通过命令行运行
#终端1
roscore
#终端2
rosrun nodelet nodelet manager __name:=nodelet_manager
#终端3
rosrun nodelet nodelet load try_nodelet/try_use nodelet_manager __name:=using_nodelet
注意,如果这里报错“According to the loaded plugin descriptions the class try_nodelet/try_use with base class type nodelet::Nodelet does not exist.” 一般是因为运行manager的窗口(终端2)没有source
所以要么一开始就把source写进配置文件中,要么就每个相关的窗口都要source,这样能够避免很多问题,也方便自己找到程序的bug所在。
4.将已有的ROS工程改写为nodelet
待补充~