ROS中处理回调数据

1. 使用回调函数

ROS中回调函数的主要作用是用来处理被调用的数据,所以需要注意回调函数外是无法处理这些数据的。

1.1 循环监控、调用回调函数 ros::spin()与ros::spinOnce()

ros::spin()ros::spinOnce(),都是ROS消息回调处理函数。这两个函数需要结合ros::Subscriber()(ROS消息订阅函数)来使用。消息回调处理的意思是调用回调函数处理订阅到的消息。首先,使用ros::Subscriber()进行消息订阅,但此处需要注意的是,我们写的诸如下面这句代码只是一个声明,程序并没有真正地执行回调函数,直到遇到ros::spin()或ros::spinOnce() 

ros::Subscriber sub = nh.subscribe("topic_name", 100, Callback);

其中,ros::spin()用于循环且监听回调函数(callback)。循环就是指程序运行到这里,就会一直在这里循环了。监听回调函数的意思是,如果这个节点有callback函数,那写一句ros::spin()在这里,就可以在有对应消息到来的时候,运行callback函数里面的内容。适用于写在程序的末尾(因为写在这句话后面的代码不会被执行),适用于订阅节点,且订阅速度没有限制的情况。

ros::spinOnce()用于监听反馈函数(callback)。只能监听反馈,不能循环。所以当你需要监听一下的时候,就调用一下这个函数。这个函数比较灵活,可以控制接收速度,一般与loop_rate.sleep(),ros::ok()等同时出现,用来控制处理回调函数的频率,并且没有消息就收来时,就会程序堵塞,不会占用CPU资源。

两条语句与publish没有关系,只与回调函数有关系。在使用ros::spin()的情况下,一般来说在初始化时已经设置好所有消息的回调,并且不需要其他背景程序运行。这样一来,每次消息到达时会执行用户的回调函数进行操作,相当于程序是消息事件驱动的;而在使用ros::spinOnce()的情况下,一般来说仅仅使用回调不足以完成任务,还需要其他辅助程序的执行:比如定时任务、数据处理、用户界面等。

1.2 回调消息队列与频率

关于消息接收回调机制在ROS官网上略有说明 (callbacks and spinning)。总体来说其原理是这样的:除了用户的主程序以外,ROS的socket连接控制进程会在后台接收订阅的消息,所有接收到的消息并不是立即处理,而是等到spin()或者spinOnce()执行时才集中处理。所以为了保证消息可以正常接收,需要尤其注意spinOnce()函数的使用 (对于spin()来说则不涉及太多的人为因素)。

在ROS中,当收到可以激活Callback函数的时机时,会将其压入一个队列,这个队列就是ros::CallbackQueue。当调用Spin或SpinOnce时,就会检查这个队列,如果队列为空,也就是没收到注册的Topic,则返回继续执行主函数;如果不为空,则从其中取出Callback函数来invoke,也就是会依次处理收到的数据。在文档中,提到会处理Callback最新一次的数据,但在实际执行过程中,发现在一次SpinOnce中同一个Topic可能会收到多个数据后进行多次处理,这就背离了项目中需要及时处理TopicA的需求。
 

2. 在回调函数外处理回调数据

因为回调函数无法返回指针或其他类型数据,所以无法在回调函数外利用回调函数中订阅得到的数据,需要通过类方法来定义回调函数

#include <ros/ros.h>
#include <std_msgs/String.h>
#include <sstream>

/**
 * This tutorial demonstrates subscribing to a topic using a class method as the callback.
 */

// %Tag(CLASS_WITH_DECLARATION)%
class Listener
{
public:
  std::string copy_data = "init init init";
  int count = 0;
public:
  void callback(const std_msgs::String::ConstPtr& msg);
  void print_data2(){std::cout << "Copy data is :" << copy_data << "\n";}
};
// %EndTag(CLASS_WITH_DECLARATION)%

void Listener::callback(const std_msgs::String::ConstPtr& msg)
{
  ROS_INFO("I heard: [%s]", msg->data.c_str());
  std::stringstream ss;
  ss << msg->data.c_str();
  ss >> copy_data;
  std::cout <<"copy_data is: " << copy_data <<"\n";
  print_data2();
  ++count;
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "listener_class");
  ros::NodeHandle n;

// %Tag(SUBSCRIBER)%
  Listener listener;
  ros::Subscriber sub = n.subscribe("chatter", 1000, &Listener::callback, &listener);
  ros::Rate loop_rate(10);
// %EndTag(SUBSCRIBER)%
  while(ros::ok() and listener.count <=3){
    ros::spinOnce();
    loop_rate.sleep();
  }
  std::cout << "After spin: \n";
  listener.print_data2();
  return 0;
}

  • 18
    点赞
  • 101
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ROS的Python代码回调函数是一种常见的处理机制。在代码,我们可以使用ro.Subscriber()函数来订阅指定的话题,并指定一个回调函数处理接收到的消息。当有消息到达订阅的话题时,ROS会自动调用回调函数处理消息。 回调函数通常在接收到消息后执行一系列的操作,包括对数据进行处理、更新地图等等。在处理回调函数A后,如果还需要进行其他的处理,可以在回调函数后添加一个while循环来执行需要执行的操作,然后在循环内调用rospy.spin()函数。这样做的好处是,rospy.spin()函数会持续监听话题,只要有新的消息到达,就会立即调用回调函数处理消息。同时,由于rospy.spin()函数并不会占用主线程,所以代码可以继续执行其他的操作。 需要注意的是,一旦进入rospy.spin()函数,它就会进入一个死循环,不会返回。只要回调函数队列回调函数等待执行,rospy.spin()函数就会立即去执行回调函数。如果回调函数队列为空,rospy.spin()函数会阻塞,不会占用CPU。这样可以保证回调函数能够及时响应消息,而不会错过任何消息。 综上所述,回调函数对于处理ROS的消息非常重要。可以通过订阅指定的话题并指定回调函数处理接收到的消息,并可以在回调函数后添加while循环来执行其他的操作,同时通过rospy.spin()函数来保证回调函数能够及时响应消息。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [ros下的python代码的编写与回调函数](https://blog.csdn.net/weixin_28930461/article/details/106444518)[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_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [ROS回调函数与spin()方法](https://blog.csdn.net/qq_33898609/article/details/105935613)[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_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值