roscpp 节点的初始化和关闭

文章目录

  • 写在前面
  • 初始化节点
    • 初始化参数
  • 关闭节点

写在前面

近期在实现一个节点时,遇到了需要在关闭节点(Ctrl+C)时发送一个消息告知相关节点的情况,尝试了几种方法后效果都不理想,因为跳出while(ROS :: OK())循环时节点已经关闭,无法继续通过节点发布消息。后来重新查看roscpp的API文档时发现,roscpp包含了一个为 SIGINT 的句柄能够处理Ctrl+C关闭节点的信号,具体内容见本文第三节。

初始化节点

对于一个C++写的ROS程序,之所以它区别于普通C++程序,是因为代码中做了两层工作:

  1. 调用了ros::init()函数,从而初始化节点的名称和其他信息,一般我们ROS程序一开始都会以这种方式开始;
  2. 创建ros::NodeHandle对象,也就是节点的句柄,它可以用来创建Publisher、Subscriber以及做其他事情。

句柄(Handle)这个概念可以理解为一个“把手”,你握住了门把手,就可以很容易把整扇门拉开,而不必关心门是什么样子。NodeHandle就是对节点资源的描述,有了它你就可以操作这个节点了,比如为程序提供服务、监听某个topic上的消息、访问和修改param等等。

例子:

#include
int main(int argc, char** argv)
{
    ros::init(argc, argv, "your_node_name"); 
    ros::NodeHandle nh;
    //....节点功能
    //....
    ros::spin();//用于触发topic、service的响应队列
    return 0;
}

初始化参数

  1. argc和argv

    ROS使用这些来解析命令行中的重新映射参数。它还会修改它们,使它们不再包含任何重映射参数,因此,如果在处理命令行之前调用ros :: init(),则无需自己跳过这些参数。

  2. node_name

    这是将初始化的节点名称,在ROS系统中必须唯一。如果以与第一个相同的名称启动第二个节点,则第一个节点将自动关闭。如果您要运行多个同一节点而不必担心对其进行唯一命名,则可以使用下面介绍的init_options :: AnonymousName选项。

  3. options

    3.1 ros :: init_options :: NoSigintHandler

    不要安装SIGINT处理程序。在这种情况下,您应该安装自己的SIGINT处理程序,以确保节点退出时正确关闭。请注意,SIGINT的默认操作往往是终止该进程,因此,如果您要执行自己的SIGTERM处理,则还必须使用此选项。

    3.2 ros :: init_options :: AnonymousName

    匿名化节点名称。在节点名称的末尾添加一个随机数,以使其唯一。

    3.3 ros :: init_options :: NoRosout
    不要将rosconsole输出广播到/ rosout主题。

关闭节点

关闭一个节点可以直接在终端上按Ctrl+C,系统会自动触发SIGINT句柄来关闭这个进程;或者在程序中适时调用ros::shutdown()来手动关闭节点,但通常我们很少这样做。

先看WIKI中的例子:

#include 
#include 

void mySigintHandler(int sig)
{
  // Do some custom action.
  // For example, publish a stop message to some other nodes.
  
  // All the default sigint handler does is call shutdown()
  ros::shutdown();
}

int main(int argc, char** argv)
{
  ros::init(argc, argv, "my_node_name", ros::init_options::NoSigintHandler);
  ros::NodeHandle nh;

  // Override the default ros sigint handler.
  // This must be set after the first NodeHandle is created.
  signal(SIGINT, mySigintHandler);
  
  //...
  ros::spin();
  return 0;
}

头文件#include 是C标准函数库中的信号处理部分, 定义了程序执行时如何处理不同的信号。信号用作进程间通信, 报告异常行为(如除零)、用户的一些按键组合(如同时按下Ctrl与C键,产生信号SIGINT),个人理解为与C++框架QT中的信号槽机制的思想是类似的。


更多详细参考资料:
1.roscpp/Overview/Initialization and Shutdown
2.中国大学MOOC --《机器人操作系统入门》讲义 6.2节

你可能感兴趣的:(ROS入门)