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>&)
, 参数的数量由类创建的模板参数的数量决定。
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