ROS节点是什么 如何诞生的

2023-09-14  

** 一个节点的诞生**

在建立连接之前,首先要有节点。

节点就是一个独立的程序,它运行起来后就是一个普通的进程,与计算机中其它的进程并没有太大区别。

一个问题是:中为什么把一个独立的程序称为“节点”

这是因为ROS沿用了计算机中“节点”的概念。

在一个网络中,例如互联网,每一个上网的计算机就是一个节点。前面我们看到的客户端、服务器这样的称呼,也是从计算机网络中借用的。

下面来看一下节点是如何诞生的。我们在第一次使用ROS时,一般都会照着官方编写一个talker和一个listener节点,以熟悉ROS的使用方法。

我们以talker为例,它的部分代码如下。

#include "ros/ros.h"
int main(int argc, char **argv)
{
  /* You must call one of the versions of ros::init() befe using any other part of the ROS system. */
  ros::init(argc, argv, "talker");
  ros::NodeHandle n;

main函数里首先调用了init()函数初始化一个节点,该函数的定义在init.cpp文件中。

当我们的程序运行到init()函数时,一个节点就呱呱坠地了。

而且在出生的同时我们还顺道给他起好了名字,也就是"talker"。

名字是随便起的,但是起名是必须的。

我们进入init()函数里看看它做了什么,代码如下,看上去还是挺复杂的。它初始化了一个叫g_global_queue的数据,它的类型是CallbkQueuePtr。

这是个相当重要的类,叫“回调队列”,后面还会见到它。init()函数还调用了network、master、this_node、file_log、pa这几个命名空间里的init初始化函数各自实现一些变量的初始化,这些变量都以g开头,例如g_host、g_uri,用来表明它们是全局变量。

其中,network::init完成节点主机名、IP地址等的初始化,master::init获取master的URI、主机号和号。

this_node::init定义节点的命名空间和节点的名字,没错,把我们给节点起的名字就存储在这里。file_log::init初始化日志文件的路径。

void init(const M_string& remapngs, const std::string& name, uint32_t opons)
{
  if (!g_atexit_registered) {
    g_atexit_registered = true;
    atexit(atexitCallback);
  }
  if (!g_global_queue) {
    g_global_queue.reset(new CallbackQueue);
  }
  if (!g_initialized) {
    g_init_options = options;
    g_ok = true;
    ROSCONSOLE_AUTOINIT;
    // Disable SIGPIPE
#ifndef WIN32
    signal(SIGPIPE, SIG_IGN);
#else
    WSADATA wsaData;
    Wtartup(MAKEWORD(2, 0), &wsaData);
#endif
    check_ipv6_environment();
    network::init(remappings);
    master::init(remappings);
    // names:: namespace is initialized by this_node
    this_node::init(name, remappings, options);
    file_log::init(remappings);
    param::init(remappings);
    g_initialized = true;
  }
}

完成初始化以后,就进入下一步ros::NodeHandle n定义句柄。

我们再进入node_handle.cpp文件,发现构造函数NodeHandle::NodeHandle调用了自己的construct函数。然后,顺藤摸瓜找到construct函数,它里面又调用了ros::start()函数。

没错,我们又绕回到了init.cpp文件。

ros::start()函数主要实例化了几个重要的类,如下。

完成实例化后马上又调用了各自的start()函数,启动相应的动作。

这些都做完了以后就可以发布或订阅消息了。

一个节点的故事暂时就到这了。

TopicManager::instance()- >start();
ServeManager::instance()- >start();
ConnectionManager::instance()- >start();
PollManager::instance()- >start();
XMLRPCManager::instance()- >start();
文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。