ros2--spin

spin()接口对节点的作用

spin翻译为汉语是旋转,但是在ros2中翻译理解为旋转不号理解;

本意应该理解为循环;因为spin的作用就是创建执行器开启循环检测消息和事件,接收到消息和事件之后执行与之对应的回调函数;

而循环会导致阻塞;那么执行器的循环会一直占用CPU资源吗?

ros::spin() enters a loop, calling message callbacks as fast as possible. Don't worry though, if there's nothing for it to do it won't use much CPU. ros::spin() will exit once ros::ok() returns false, which means ros::shutdown() has been called, either by the default Ctrl-C handler, the master telling us to shutdown, or it being called manually.

ros::spin() 进入一个循环,尽可能快地调用消息回调。不过别担心,如果它什么都不做,它不会使用太多的CPU。一旦 ros::ok() 返回 false,ros::spin() 将退出,这意味着 ros::shutdown() 已被调用,要么被默认的 Ctrl-C 处理程序调用,要么由主机告诉我们关闭,要么被手动调用。

可见执行器内部的循环通过循环检测ros::ok()接口判断是否退出或者继续循环;

ros2中的执行器

教程

Executor负责从节点中收集待处理的回调,并决定执行它们的顺序和时间。

ros2执行器使用底层操作系统的一个或多个线程来调用(订阅、定时器、服务服务器、动作服务器等的)回调。

注意:是使用,不是生成线程,这个底层操作系统的线程指的是内核的线程---待确定;

也就是ros2中,回调函数的注册是通过在主线程中调用相关的接口完成注册的,但是回调函数的执行并不由主线程来执行,而是由底层操作系统的线程来执行。

ros2执行器本质上是一个类;

spin接口在内部创建的就是SingleThreadExecutor这个类的执行器对象;

spin的3种接口类型

spin

spin()首先创建一个单线程执行器进入一个无限循环,会尽可能快地执行消息的回调。但是,不需要担心CPU占用问题,因为没事干的时候,它并不怎么消耗CPU资源。

spin内部用于创建单线程执行器:

rclcpp::executors::SingleThreadedExecutor executor;

executor.add_node(node);

executor.spin();

将节点加入执行器,执行执行器的spin开始检测消息和时间,然后执行相应的回调函数,直到节点关闭;

spin_some

链接1

Create a default single-threaded executor and execute any immediately available work.

创建一个SingleThreadedExecutor执行器,会去(话题订阅)缓冲区中查看有没有回调函数。如果有,就马上处理一个回调函数并退出;否则,就退出这个接口,执行后续的代码。

这个接口会立马检测回调并执行返回;

spin_until_future_complete

源码:

template<typename NodeT = rclcpp::Node, typename FutureT, typename TimeRepT = int64_t,
  typename TimeT = std::milli>
rclcpp::FutureReturnCode
spin_until_future_complete(
  std::shared_ptr<NodeT> node_ptr,
  const FutureT & future,
  std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
{
  return rclcpp::spin_until_future_complete(node_ptr->get_node_base_interface(), future, timeout);
}

三个参数:

节点,期望的返回对象,超时时间;

默认要一直等待期望的结果返回。

期望的结果返回就执行器便退出;执行主线程后续代码;

#include <chrono>

#include "rclcpp/rclcpp.hpp"
#include "example_interfaces/srv/add_two_ints.hpp"

using namespace std::chrono_literals;

class ServiceClient_01:public rclcpp::Node{
public:
    ServiceClient_01(std::string name):Node(name){
        RCLCPP_INFO(this->get_logger(),"I am service client 01: %s",name.c_str());
        client_=this->create_client<example_interfaces::srv::AddTwoInts>("add_tow_ints_srv");
    }

    auto sendRequest(std::shared_ptr<example_interfaces::srv::AddTwoInts_Request> request){
        //1,等待server上线
        while(!client_->wait_for_service(1s)){
            //failed,检查rclcpp状态
            if(!rclcpp::ok()){
                RCLCPP_INFO(this->get_logger(),"interrupted while waiting for service.");
                break;
            }
            RCLCPP_INFO(this->get_logger(),"Wainting for the server to work...");
        }
        //2,构造请求
        // int n1=0,n2=0;
        // std::cin>>n1>>n2;
        // auto request=std::make_shared<example_interfaces::srv::AddTwoInts_Request>();
        // request->a=n1;
        // request->b=n2;
        //3,发送请求
        auto result=client_->async_send_request(request);
        return result;
    }

    // void responseCallback(example_interfaces::srv::AddTwoInts::Response::SharedPtr result){
    //     //auto response=result_future.get();
    //     RCLCPP_INFO(this->get_logger(),"Caculate result: %ld",result->sum);
    // }

    void responseCallback(std::future<example_interfaces::srv::AddTwoInts::Response::SharedPtr> result_future){
        auto response=result_future.get();
        RCLCPP_INFO(this->get_logger(),"Caculate result: %ld",response->sum);
    }
    

private:
    rclcpp::Client<example_interfaces::srv::AddTwoInts>::SharedPtr client_{};

    //回调函数
    // void _responseCallback(rclcpp::Client<example_interfaces::srv::AddTwoInts>::SharedFuture result_future){
    //     auto response=result_future.get();
    //     RCLCPP_INFO(this->get_logger(),"Caculate result: %ld",response->sum);
    // }
};

int main(int argc,char** argv){
    rclcpp::init(argc,argv);
    auto node=std::make_shared<ServiceClient_01>("service_client_01");
    auto request=std::make_shared<example_interfaces::srv::AddTwoInts_Request>();
    std::cin>>request->a>>request->b;
    auto result=node->sendRequest(request);
    //rclcpp::spin(node);
    if(rclcpp::spin_until_future_complete(node,result)==rclcpp::FutureReturnCode::SUCCESS){
        //node->responseCallback(result.future.get());
        node->responseCallback(std::move(result.future));
    }
    rclcpp::shutdown();
    return 0;
}

相关推荐

  1. ROS2+ROS_DOMAN_ID

    2024-07-12 17:06:01       46 阅读
  2. ROS2总结

    2024-07-12 17:06:01       27 阅读
  3. ROS2体系框架

    2024-07-12 17:06:01       28 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-12 17:06:01       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-12 17:06:01       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-12 17:06:01       58 阅读
  4. Python语言-面向对象

    2024-07-12 17:06:01       69 阅读

热门阅读

  1. NLP简介

    NLP简介

    2024-07-12 17:06:01      20 阅读
  2. Linux 内核中的 Makefile 和 Kconfig:深入理解与实践

    2024-07-12 17:06:01       18 阅读
  3. 【Cesium开发实战】淹没分析功能的实现

    2024-07-12 17:06:01       19 阅读
  4. 人生低谷来撸C#--007 结构体

    2024-07-12 17:06:01       23 阅读
  5. 自然语言处理:项目推荐

    2024-07-12 17:06:01       23 阅读
  6. vue3+ts 使用WebSocket

    2024-07-12 17:06:01       24 阅读
  7. Chubby VS Zookeeper

    2024-07-12 17:06:01       23 阅读
  8. 需求实现:字数限制500字

    2024-07-12 17:06:01       20 阅读
  9. 安全开发基础篇-数据溢出

    2024-07-12 17:06:01       26 阅读
  10. MySQL 用like “%x“,索引就一定会失效吗?

    2024-07-12 17:06:01       23 阅读
  11. Windows CMD 命令汇总表

    2024-07-12 17:06:01       18 阅读