ROS多线程处理方法

15 篇文章 1 订阅

1. 目的

ROS主线程

ROS本身占用计算资源较多, 且多传感器的时间戳不同步。
对于流程较长且循环执行的算法, 如果将所有处理任务都放在一个ROS节点的主线程中,
每次ros::spinOnce();执行一次算法流程, 主线程中的传感器回调函数也只执行一次, 可能导致高频传感器数据丢失。

多线程异步处理

本文受LeGO-LOAM源码中mapOptmization.cpp中闭环图优化的启发, 介绍一种在单个ROS节点内使用多线程的编程方法。

核心思想是:
(1) 在ROS主线程中仅处理传感器回调函数和一些耗时低的数据预处理, 并存放在队列或堆栈中;
(2) 将耗时高的算法流程分解为多个相对独立的子流程, 每个子流程放在一个新线程中。
这样, 将传感器数据采集和处理流程分开, 保证了ROS主线程的循环频率, 减少数据丢失。

需要注意的是, 最好使得每个子流程的处理时间相近, 若子流程之间有相互逻辑关系, 需要加入一些其他的控制标识量。

下面的示例代码中, func1() func2() func3()分别为子流程

代码

实现一个流程类

class WorkFlow()
{
	public:
	ros::NodeHandle nh;
	// 变量
	int a, b, c;
	// 处理函数
	void func1() {a++};
	void func2() {b++};
	void func3() {c++};
	// 线程回调函数
	void func1Thread()
	{
		ros::Rate rate(10);
        while(ros::ok())
        {
            func1();
            rate.sleep();
        }
	}
	
	void func2Thread()
	{
		ros::Rate rate(10);
        while(ros::ok())
        {
            func2();
            rate.sleep();
        }
	}
	
	void func3Thread()
	{
		ros::Rate rate(10);
        while(ros::ok())
        {
            func3();
            rate.sleep();
        }
	}
	
	WorkFlow():nh("~")
	{
		a = b = c = 0;
	}

	/*
	其他处理函数
	以及传感器回调函数
	*/
};

主函数

int main(int argc, char** argv)
{
    ros::init(argc, argv, "msg_buildIntensityMap");
    WorkFlow EX;

    std::thread Thread1(&WorkFlow::func1Thread, &EX);
    std::thread Thread2(&WorkFlow::func2Thread, &EX);
    std::thread Thread3(&WorkFlow::func3Thread, &EX);

    ros::Rate rate(20);
    while (ros::ok())
    {
        ros::spinOnce();
        rate.sleep();
    }
    Thread1.join();
    Thread2.join();
    Thread3.join();
    return 0;
}

2. 解释

主循环

下面主函数中的循环, 可用于处理耗时低的任务, 例如传感器数据回调函数

while (ros::ok())
{
    ros::spinOnce();
    rate.sleep();
}

std::Thread线程

下面线程函数中的循环, 可用于处理耗时较高的任务, 例如地图建模/点云分割/运动规划等
Thread1为例:

Thread1线程执行WorkFlow类对象EX的func1Thread()函数

std::thread Thread1(&WorkFlow::func1Thread, &EX);
Thread1.join();

func1Thread()函数循环执行func1()函数, func1()函数通常可用于处理耗时较高的任务

// 处理函数
void func1() {a++};
// 线程回调函数
void func1Thread()
{
	ros::Rate rate(10);
	while(ros::ok())
	{
	    func1();
	    rate.sleep();
	}
}

REF

  1. https://blog.csdn.net/Zed_Of_Zoe/article/details/116706974
  2. https://github.com/RobustFieldAutonomyLab/LeGO-LOAM
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
ROS中,可以使用多线程来处理回调函数。ROS提供了两种多线程回调处理方法ros::MultiThreadedSpinner和ros::AsyncSpinner。 ros::MultiThreadedSpinner是一个多线程回调处理类,它通过启动指定数量的Spinner线程并发执行Callback队列中的可用回调来处理回调函数。你可以通过指定回调队列来控制线程的数量和执行方式。 ros::AsyncSpinner是另一种多线程回调处理方法,它使用异步的方式来启停Spinner线程。你可以指定要开启的线程数量,并发执行Callback队列中的可用回调。 这两种多线程回调处理方法都能够在处理回调函数时提高效率,充分利用系统资源,同时保证其他回调函数不会被阻塞。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [ROS线程服务话题定时器等回调函数处理](https://blog.csdn.net/GeForeverr/article/details/108776801)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [【ROS】回调的多线程问题](https://blog.csdn.net/lemonxiaoxiao/article/details/128422748)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sdhdwyx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值