3.1 Node以及Master
从功能角度来说,通常一个node负责者机器人的某一个单独的功能。由于机器人的功能模块非常复杂,我们往往不会把所有功能都集中到一个node上,而会采用分布式的方式,把鸡蛋放到不同的篮子里。例如有一个node来控制底盘轮子的运动,有一个node驱动摄像头获取图像,有一个node驱动激光雷达,有一个node根据传感器信息进行路径规划……这样做可以降低程序发生崩溃的可能性,试想一下如果把所有功能都写到一个程序中,模块间的通信、异常处理将会很麻烦。
由于机器人的元器件很多,功能庞大,因此实际运行时往往会运行众多的node,负责感知世界、控制运动、决策和计算等功能。那么如何合理的进行调配、管理这些node?这就要利用ROS提供给我们的节点管理器master, master在整个网络通信架构里相当于管理中心,管理着各个node。node首先在master处进行注册,之后master会将该node纳入整个ROS程序中。node之间的通信也是先由master进行“牵线”,才能两两的进行点对点通信。当ROS程序启动时,第一步首先启动master,由节点管理器处理依次启动node。
接下来我们来介绍如何用C++编写一个Node。
3.3 Node编写
当执行一个ROS程序,就被加载到了内存中,就成为了一个进程,在ROS里叫做节点。每一个ROS的节点尽管功能不同,但都有必不可少的一些步骤,比如初始化、销毁,需要通行的场景通常都还需要节点的句柄。 这一节我们来学习Node最基本的一些操作。
3.3.1 节点编写
在第二章节中我们建立了一个ros_workspace的工作空间同时在工作空间中创建了一个命名为test_pkg的功能包。本节中我们继续在test_pkg中创建一个节点。
在路径
ros_workspace/src/test_pkg/src
路径下创建一个cpp文件命名为:test.cpp。
在终端输入一下命令进入指定路径;
cd ~/ros_workspace/src/test_pkg/src
在终端输入以下命令打开test.cpp
gedit test.cpp
输入以下代码:
#include"ros/ros.h"
#include"std_msgs/String.h"
#include"sstream"
int main(int argc,char **argv)
{
ros::init(argc,argv,"talker");
ros::NodeHandle n;
ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter",1000);
ros::Rate loop_rate(10);
int count = 0;
while(ros::ok())
{
std_msgs::String msg;
std::stringstream ss;
ss<<"hello world" <<count;
msg.data = ss.str();
ROS_INFO("%s",msg.data.c_str());
chatter_pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
++count;
}
return 0;
}
上述测试代码创建了一个话题,并向其中发布“hello world”。
3.3.2 CMakeLists.txt文件修改
在完成了节点源码编写之后,需要修改test_pkg包下的CMakeLists.txt文件(具体路径为:ros_workspace/src/test_pkg/CMakeLists.txt ),将编辑的源码生成可执行文件。
需要修改以下两条指令:
add_executable(${PROJECT_NAME}_node src/test_pkg_node.cpp)
该条指令用于指定将该功能包src目录下的哪个源文件编译为可执行程序,其中:
${PROJECT_NAME}_node
为生成可执行程序的名字,该名字可以任意指定。
src/node.cpp:为编译要使用的源码的文件名。
target_link_libraries(${PROJECT_NAME}_node
${catkin_LIBRARIES}
)
该条指令用于指定所使用的一些链接库。
当修改完CMakeLists.txt文件后 就可以在工作空间的根目录下 使用catkin_make进行编译了。
$ cd ~/ros_workspace
$ catkin_make
编译生成的可执行文件位于:/home/reinovo/ros_workspace/devel/lib/test_pkg/路径下,命名为:test_pkg_node。大家可以自行查看是否有该文件生成。
3.3.3 运行生成的Node
打开一个终端输入以下命令:
$ roscore //打开Master
重新打开一个终端输入以下命令运行test_pkg_node节点。
$ rosrun test_pkg test_pkg_node
注意:用rosrun运行节点之前一定要先运行roscore不然会报错