【ROS2多进程】
【ROS2多进程】
执行器(Executor)
调用订阅、定时器、服务的回调,以响应收到的消息和事件
rclcpp::spin(node)
->拓展
//创建单线程执行器
rclcpp::executors::SingleThreadedExecutor executor;
//添加节点
executor.add_node(node);
//运行节点
executor.spin();
Executor
类
//单线程执行器
SingleThreadedExecutor
//多线程执行器:创建额外进程并行处理消息/事件
MultiThreadedExecutor
//静态单线程执行器:调用添加节点函数时,扫描节点结构,确定节点订阅和定时器
StaticSingleThreadedExecutor
回调组
配合多线程执行器
public:
service_callback_group_=this->create_callback_group(
rclcpp::CallbackGroupType::MutuallyExclusive);//互斥回调组
rclcpp::CallbackGroupType::Reentrant//可重入回调组
// 依赖上下文/需要处理顺序的场景:不要使用可重入回调组
service_=this->create_service<example_interfaces::srv::AddTwoInts>(
"add_two_ints",
std::bind(&LearnExecutorNode::add_two_ints_callback,this,
std::placeholders::_1,std::placeholders::_2),
rmw_qos_profile_services_default,service_callback_group_);
private:
rclcpp::CallbackGroup::SharedPtr service_callback_group_;
使用
#include"example_interfaces/srv/add_two_ints.hpp"
#include"rclcpp/rclcpp.hpp"
#include"std_msgs/msg/string.hpp"
#include<sstream>
class LearnExecutorNode : public rclcpp::Node{
public:
LearnExecutorNode() : Node("learn_executor"){
//发布者
publisher_ = this->create_publisher<std_msgs::msg::String>("string_topic",10);
//定时器
timer_=this->create_wall_timer(std::chrono::seconds(1),
std::bind(&LearnExecutorNode::timer_callback,this));
//服务端
service_=this->create_service<example_interfaces::srv::AddTwoInts>(
"add_two_ints",std::bind(&LearnExecutorNode::add_two_ints_callback,this,
std::placeholders::_1,std::placeholders::_2)
);
}
private:
void timer_callback(){
auto msg=std_msgs::msg::String();
msg.data="话题发布:"+thread_info();
RCLCPP_INFO(this->get_logger(),msg.data.c_str());
publisher_->publish(msg);
}
std::string thread_info(){
std::ostringstream thread_str;
thread_str<<"线程ID:"<<std::this_thread::get_id();
return thread_str.str();
}
void add_two_ints_callback(
const std::shared_ptr<example_interfaces::srv::AddTwoInts::Request> request,
std::shared_ptr<example_interfaces::srv::AddTwoInts::Response> response
)
{
RCLCPP_INFO(this->get_logger(),"服务开始处理:%s",thread_info().c_str());
std::this_thread::sleep_for(std::chrono::seconds(10));
response->sum=request->a+request->b;
RCLCPP_INFO(this->get_logger(),"服务处理完成:%s",thread_info().c_str());
}
rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
rclcpp::TimerBase::SharedPtr timer_;
rclcpp::Service<example_interfaces::srv::AddTwoInts>::SharedPtr service_;
};
int main(int argc,char** argv){
rclcpp::init(argc,argv);
auto node=std::make_shared<LearnExecutorNode>();
auto executor=rclcpp::executors::SingleThreadedExecutor();//使用单线程执行器对节点事件进行处理
executor.add_node(node);
executor.spin();
rclcpp::shutdown();
return 0;
}
->main中单线程
auto executor=rclcpp::executors::SingleThreadedExecutor();
->运行结果单线程
ros2 service call /add_two_ints example_interfaces/srv/AddTwoInts "{}"
->修改为多进程
auto executor=rclcpp::executors::MultiThreadedExecutor();
->修改默认进程数量
//修改进程数量
size_t N=3;//设置进程数量
auto options=rclcpp::ExecutorOptions();
auto executor=rclcpp::executors::MultiThreadedExecutor(options,N);
※服务处理和定时器无法同时运行/无法并行处理请求:
不指定回调组时,ros2会采用默认回调组->定时器和服务处理都在同一回调组
->使用互斥回调组
->可并行进行:在处理服务时同步发布话题
->并行处理:使用可重入回调组