ros中message_filter类常用的使用方法

1.用途:

message_filter 是roscpp和rospy的实用程序库。 它集合了许多的常用的消息“过滤”算法。顾名思义,该类的作用就是消息过滤,当消息到达过滤器的时候,可能并不会立即输出,而是在稍后的时间点里满足一定条件下输出。

2.过滤模式:

为了提供统一的接口与输出,message_filters中所有的消息过滤器都遵循着相同的模式连接输入和输出。 
输入是通过过滤器构造函数或者是connectInput()方法链接。 
输出是通过registerCallback()方法注册回调函数输出

但是每个过滤器都定义了输入和输出的类型,所以并不是所有的过滤器都可以直接相互连接。 
例如,给出两个过滤器FooFilter和BarFilter,其中FooFilter的输出作为BarFilter的输入,将foo连接到bar可以是(在C ++中):

1. FooFilter foo;

2. BarFilter bar(foo);//通过过滤器构造函数

or:

1. FooFilter foo;

2. BarFilter bar;

3. bar.connectInput(foo);//connectInput()方法链接

3. subscriber 订阅模式

订阅者过滤器是对ROS订阅的封装,为其他过滤器提供源代码,订阅者过滤器无法将另一个过滤器的输出作为其输入,而是使用ROS主题作为其输入。

1. message_filters::Subscriber<std_msgs::UInt32> sub(nh, "my_topic", 1);

2.sub.registerCallback(myCallback);

等价于:ros::Subscriber sub = nh.subscribe("my_topic", 1, myCallback);

4. Time Synchronizer 时间同步器

TimeSynchronizer过滤器通过包含在其头中的时间戳来同步输入通道,并以单个回调的形式输出它们需要相同数量的通道。 C ++实现可以同步最多9个通道。

输入 
C ++: 最多9个独立的过滤器,每个过滤器的形式为void callback(const boost :: shared_ptr <M const>&)。 支持的过滤器数量由类创建的模板参数的数量决定。

输出

C ++: 对于消息类型M0..M8,void callback(const boost :: shared_ptr <M0 const>&,...,const boost :: shared_ptr <M8 const>&), 参数的数量由类创建的模板参数的数量决定。

假设您正在编写一个需要从两个时间同步主题处理数据的ROS节点。 您的程序可能看起来像这样:

 1     #include <message_filters/subscriber.h>
 2     #include <message_filters/time_synchronizer.h>
 3     #include <sensor_msgs/Image.h>
 4     #include <sensor_msgs/CameraInfo.h>
 5      
 6     using namespace sensor_msgs;
 7     using namespace message_filters;
 8      
 9     void callback(const ImageConstPtr& image, const CameraInfoConstPtr& cam_info)
10     {
11       // Solve all of perception here...
12     }
13      
14     int main(int argc, char** argv)
15     {
16       ros::init(argc, argv, "vision_node");
17      
18       ros::NodeHandle nh;
19      
20       message_filters::Subscriber<Image> image_sub(nh, "image", 1);
21       message_filters::Subscriber<CameraInfo> info_sub(nh, "camera_info", 1);
22       TimeSynchronizer<Image, CameraInfo> sync(image_sub, info_sub, 10);
23       sync.registerCallback(boost::bind(&callback, _1, _2));
24      
25       ros::spin();
26      
27       return 0;
28     }

5.Time Sequencer 时间序列

TimeSequencer过滤器根据报头的时间戳保证按时间顺序调用消息。TimeSequencer构造有一个特定的延迟,它指定在传递消息之前排队多长时间。 消息的回调直到消息的时间戳到达一定时间节点的时候才会调用。然而,对于所有已经至少延迟的消息,它们的回调被调用并保证是按时间顺序的。 如果一条消息从已经有其回调调用的消息之前的某个时间到达,则会被丢弃。

输入 
C++: void callback(const boost::shared_ptr<M const>&)

输出 
C++: void callback(const boost::shared_ptr<M const>&)

C ++版本采用延迟更新速率。 更新速率决定了定序器对准备好通过的消息检查其队列的频率。 最后一个参数是在开始抛出一些消息之前排队的消息数。

1     message_filters::Subscriber<std_msgs::String> sub(nh, "my_topic", 1);
2     message_filters::TimeSequencer<std_msgs::String> seq(sub, ros::Duration(0.1), ros::Duration(0.01), 10);
3     seq.registerCallback(myCallback);

6. 与tf::MessageFilter类联合使用

tf::MessageFilter可以订阅任何的ROS消息,然后将其缓存,直到这些消息可以转换到目标坐标系,然后进行相应的处理(进入回调函数)。

tf::MessageFilter的初始化需要message_filters::Subscriber,tf转换,目标坐标系,等待时间。当message_filters::Subscriber的消息能够由tf转换到目标坐标系时,调用回调函数,回调函数由tf::MessageFilter::registerCallback()进行注册。

tf::MessageFilter< M > Class Template Reference:

http://docs.ros.org/diamondback/api/tf/html/c++/classtf_1_1MessageFilter.html

在gmapping中的事例代码:

 1 tf_ = new TransformListenerWrapper();
 2 message_filters::Subscriber<sensor_msgs::LaserScan>* laser_scan_sub_;
 3 tf::MessageFilter<sensor_msgs::LaserScan>* laser_scan_filter_;
 4  
 5 laser_scan_sub_ = new message_filters::Subscriber<sensor_msgs::LaserScan>(nh_, scan_topic_, 100);
 6 laser_scan_filter_ = new tf::MessageFilter<sensor_msgs::LaserScan>(*laser_scan_sub_, 
 7                                                         *tf_, 
 8                                                         odom_frame_id_, 
 9                                                         100);
10  
11 laser_scan_filter_->registerCallback(boost::bind(&AmclNode::laserReceived, this, _1));
12  
13 void AmclNode::laserReceived(const sensor_msgs::LaserScanConstPtr& laser_scan){
14     this->tf_->transformPose(base_frame_id_, ident, laser_pose);//这个函数的意思是,ident在base_frame_id下的表示为laser_pose
15 }

 

wiki教程:http://wiki.ros.org/tf/Tutorials/Using%20Stamped%20datatypes%20with%20tf%3A%3AMessageFilter

 1 #include "ros/ros.h"
 2 #include "tf/transform_listener.h"
 3 #include "tf/message_filter.h"
 4 #include "message_filters/subscriber.h"
 5 
 6 class PoseDrawer
 7 {
 8 public:
 9   PoseDrawer() : tf_(),  target_frame_("turtle1")
10   {
11     point_sub_.subscribe(n_, "turtle_point_stamped", 10);
12     tf_filter_ = new tf::MessageFilter<geometry_msgs::PointStamped>(point_sub_, tf_, target_frame_, 10);
13     tf_filter_->registerCallback( boost::bind(&PoseDrawer::msgCallback, this, _1) );
14   } ;
15 
16 private:
17   message_filters::Subscriber<geometry_msgs::PointStamped> point_sub_;
18   tf::TransformListener tf_;
19   tf::MessageFilter<geometry_msgs::PointStamped> * tf_filter_;
20   ros::NodeHandle n_;
21   std::string target_frame_;
22 
23   //  Callback to register with tf::MessageFilter to be called when transforms are available
24   void msgCallback(const boost::shared_ptr<const geometry_msgs::PointStamped>& point_ptr) 
25   {
26     geometry_msgs::PointStamped point_out;
27     try 
28     {
29       tf_.transformPoint(target_frame_, *point_ptr, point_out);
30       
31       printf("point of turtle 3 in frame of turtle 1 Position(x:%f y:%f z:%f)\n", 
32              point_out.point.x,
33              point_out.point.y,
34              point_out.point.z);
35     }
36     catch (tf::TransformException &ex) 
37     {
38       printf ("Failure %s\n", ex.what()); //Print exception which was caught
39     }
40   };
41 
42 };
43 
44 
45 int main(int argc, char ** argv)
46 {
47   ros::init(argc, argv, "pose_drawer"); //Init ROS
48   PoseDrawer pd; //Construct class
49   ros::spin(); // Run until interupted 
50 };

 

 参考:https://blog.csdn.net/RainVictor1/article/details/79722421?utm_source=blogxgwz8

           https://blog.csdn.net/liuerin/article/details/106212289

 

posted @ 2020-06-23 16:11  万丈高楼平地起  阅读(2161)  评论(0编辑  收藏  举报