ROS学习之cpp节点的启动与关闭


wiki链接:http://wiki.ros.org/roscpp/Overview/Initialization%20and%20Shutdown

        

一、节点的初始化


    对于一个cpp节点(指基于roscpp程序包的节点),其初始化有两个阶段:
    a) 通过调用ros::init()函数来初始化节点。可以用命令行参数来命名节点和设置一些其它选项。
    b) 通过创建ros::NodeHandle实例来启动节点。在一些更高级的情形可以采用不同的方式。

    1.初始化roscpp 节点
        ros::init()  API链接:http://docs.ros.org/api/roscpp/html/init_8h.html
        在node代码中在调用其它roscpp函数前,首先调用ros::init()函数
        例如:  ros::init(argc, argv, "my_node_name");
            ros::init(argc, argv, "my_node_name", ros::init_options::AnonymousName);

        函数原型:void ros::init(<command line or remapping arguments>, std::string node_name, uint32_t options);

            argc和argv:解析命令行重映射参数
            node_name:节点名,在ros系统中,节点名必须唯一;如果重名节点被运行,那之前的节点就会自动关闭。
            options:选项参数,明确roscpp的一些具体的行为
        初始化节点只是简单地从命令行参数和环境中确定像节点名、名字空间以及重映射。它不会与主节点master交互。

        1) 初始化选项
        ros::init_options API链接: http://docs.ros.org/api/roscpp/html/namespaceros_1_1init__options.html

        2)获取你的命令行参数
        ros::removeROSArgs() API链接: http://docs.ros.org/api/roscpp/html/init_8h.html

    2.启动roscpp节点

        最常用的启动roscpp节点的方式就是创建ros::NodeHandle实例:
        ros::NodeHandle nh;

        当第一个节点句柄创建时,它会调用ros::start(),当最后一个节点句柄销毁时,它会调用ros::shutdown().
        如果想手动管理节点的生命周期,可以自己调用ros::start(),ros::shutdown().

        

二、节点的关闭


    1.关闭节点
        节点会在调用ros::shutdown()函数时被关闭,这将杀死所有该节点相关的订阅者,发布者,服务请求,服务提供...

    2.关闭测试

        有两种测试关闭状态的方法。最常用的方法是ros::ok(),一旦ros::ok()返回false,节点就已经被关闭了。
            while(ros::ok())
            { ... }
        
        另一种是使用ros::isShutDown()方法。当ros::shutdown()函数被调用时,该函数返回true.
            在一个持久的服务回调函数中使用该测试函数测试是否应该结束,这时候不能使用ros::ok()来测试,因为节点在回调函数运行时无法完成shutdown

        自定义的SIGINT句柄:信号中断句柄。
            使用方法:
                #include <ros/ros.h>
                #include <signal.h>

                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;
                }

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
ROS2中,可以使用`rcl_interfaces/msg/ParameterEvent`消息来广播节点的参数变更事件,其中包括节点的IP地址变更。具体实现步骤如下: 1. 在节点启动时,获取当前的IP地址,并将其保存在节点的参数中。例如,可以使用`gethostname`和`gethostbyname`函数来获取主机名和IP地址,并使用`rclcpp::Parameter`来保存IP地址参数。 2. 监听节点参数变更事件,当节点的IP地址参数发生变化时,构造一个`rcl_interfaces/msg/ParameterEvent`消息,并使用`rclcpp::Publisher`将其发布到指定的话题。 3. 其他节点可以通过订阅该话题来获取节点的IP地址变更事件。在收到事件后,可以根据事件中包含的参数信息来更新节点的IP地址。 下面是一个简单的示例代码,用于将节点的IP地址保存为参数,并在IP地址变更时广播事件: ```cpp #include <unistd.h> #include <arpa/inet.h> #include "rclcpp/rclcpp.hpp" #include "rcl_interfaces/msg/parameter_event.hpp" using namespace std::chrono_literals; class NodeWithIP : public rclcpp::Node { public: NodeWithIP() : Node("node_with_ip") { // Get current IP address and save it as a parameter char hostname[1024]; gethostname(hostname, 1024); struct hostent* host_info = gethostbyname(hostname); char ip_address[INET_ADDRSTRLEN]; inet_ntop(AF_INET, host_info->h_addr_list[0], ip_address, INET_ADDRSTRLEN); this->declare_parameter<std::string>("ip_address", ip_address); // Publish parameter events when IP address changes ip_address_ = ip_address; timer_ = create_wall_timer(1s, [this](){ char hostname[1024]; gethostname(hostname, 1024); struct hostent* host_info = gethostbyname(hostname); char ip_address[INET_ADDRSTRLEN]; inet_ntop(AF_INET, host_info->h_addr_list[0], ip_address, INET_ADDRSTRLEN); if (ip_address != ip_address_) { ip_address_ = ip_address; rcl_interfaces::msg::ParameterEvent event; event.node = this->get_name(); event.stamp = this->now(); event.parameters.push_back(rclcpp::Parameter("ip_address", ip_address)); parameter_event_pub_->publish(event); } }); parameter_event_pub_ = create_publisher<rcl_interfaces::msg::ParameterEvent>("parameter_events", 10); } private: std::string ip_address_; rclcpp::TimerBase::SharedPtr timer_; rclcpp::Publisher<rcl_interfaces::msg::ParameterEvent>::SharedPtr parameter_event_pub_; }; int main(int argc, char** argv) { rclcpp::init(argc, argv); auto node_with_ip = std::make_shared<NodeWithIP>(); rclcpp::spin(node_with_ip); rclcpp::shutdown(); return 0; } ``` 在上面的示例代码中,节点启动时获取当前的IP地址,并将其保存为`ip_address`参数。然后,节点创建一个定时器,每隔1秒钟检查一次IP地址是否发生变化。如果IP地址发生变化,则构造一个`rcl_interfaces::msg::ParameterEvent`消息,并将其发送到名为`parameter_events`的话题。 其他节点可以通过订阅`parameter_events`话题来获取节点IP地址的变更事件。在收到事件后,可以根据事件中包含的参数信息来更新节点的IP地址。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值