ros多线程数据处理方法(在主函数中循环处理消息与回调函数循环冲突解决方法)

一曲冷凌霜 提交于 2020-01-29 11:36:13

在ros节点中,主函数中不能设置长时间的循环,否则会影响回调函数的执行

主函数如下

#include <iostream>
#include "senser_bridge.h"
#include "nav.h"

int main(int argc, char *argv[])
{
    ros::init(argc,argv,"nav_test");
    ROS_INFO("*******");
    SenserBridge senser_bridge;
    

    while(true){
        cout << "主函数" <<endl;
        sleep(1);
    }

    ros::spin();

}

SenserBridge类如下

SenserBridge::SenserBridge()
{
    imu_sub_ = nh_.subscribe("/insprobe/imu0", 200, &SenserBridge::ImuDataCollect, this);
    pose_pub_ = nh_.advertise<sensor_msgs::PointCloud2>("/pose",200);
}

//回调函数
void SenserBridge::ImuDataCollect(const sensor_msgs::Imu::ConstPtr &msg)
{
    sensor_msgs::Imu imu_data;
    imu_data = *msg;
    imu_data_.push_back(imu_data);
    UpdataImuNow();
    cout << "***回调函数***"<<endl;
}

执行该节点则会出现如下问题:

[ INFO] [1576593799.328774366]: *******
Start time is 1575361874
主函数
主函数
主函数
主函数
主函数
主函数
主函数
主函数
....

如果将主函数中ros::spin()放到while循环前面,则会导致while()循环不执行,主函数代码修改如下:

#include "senser_bridge.h"
#include "nav.h"

int main(int argc, char *argv[])
{
    ros::init(argc,argv,"nav_test");
    ROS_INFO("*******");
    SenserBridge senser_bridge;

    ros::spin();//放到while()循环前面了
    while(true){
        cout << "主函数" <<endl;
        sleep(1);
    }
    
}

则输出结果只有回调函数中的值了

[ INFO] [1576594011.172570488]: *******
Start time is 1575361874
***回调函数***
***回调函数***
***回调函数***
***回调函数***
***回调函数***
***回调函数***
***回调函数***
***回调函数***
***回调函数***
***回调函数***
***回调函数***
***回调函数***

ps.在同一个节点中,ros::spin()相当于单线程的subcriber循环,所有的subcriber和对应的回调函数都在这个线程中循环执行,当subcriber接受的topic频率很高时,可能会出现上一个subcriber的回调函数还没执行完,下一个subcriber的msg就来的情况,造成阻塞。可能通过多线程方式避免这种情况。参考:http://wiki.ros.org/roscpp/Overview/Callbacks%20and%20Spinning

https://blog.csdn.net/wengge987/article/details/50619851

http://m.blog.chinaunix.net/uid-27875-id-5817906.html

https://yuzhangbit.github.io/tools/several-ways-of-writing-a-ros-node/

使用boost::thread的C++多线程

#include <iostream>
#include <string>
#include <boost/thread.hpp>
#include "senser_bridge.h"
#include "nav.h"

void A()
{
    while(true)
    {
        sleep(1);
        cout<< "线程函数" <<endl;
    }

}

int main(int argc, char *argv[])
{
    ros::init(argc,argv,"nav_test");
    ROS_INFO("*******");
    SenserBridge senser_bridge;

    boost::thread server(A);//创建额外的线程,即可一起执行了

    ros::spin();

}

结果如下

[ INFO] [1576674662.700959004]: *******
Start time is 1575361874
线程函数
线程函数
***回调函数***
***回调函数***
***回调函数***
***回调函数***
***回调函数***
***回调函数***
***回调函数***
***回调函数***
***回调函数***
***回调函数***
***回调函数***
***回调函数***
***回调函数***
***回调函数***
***回调函数***
***回调函数***
线程函数
***回调函数***

可见在执行回调函数中也会有线程函数的执行,即可将回调函数获取的数据,放到线程函数中处理,而不用担心计算阻塞导致消息接收不到。

参考https://www.boost.org/doc/libs/1_67_0/doc/html/thread/thread_management.html#thread.thread_management.tutorial

https://www.jianshu.com/p/5e394f6aa4dc

https://www.cnblogs.com/liaocheng/p/4978398.html

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!