ROS官⽅教程[翻译]---message_filter的使⽤
1 综述
message_filters是⼀个⽤于roscpp和rospy的实⽤程序库。 它集合了许多的常⽤的消息“过滤”算法。
消息过滤器message_filters类似⼀个消息缓存,当消息到达消息过滤器的时候,可能并不会⽴即输出,⽽是在稍后的时间点⾥满⾜⼀定条件下输出。
举个例⼦,⽐如时间同步器,它接收来⾃多个源的不同类型的消息,并且仅当它们在具有相同时间戳的每个源上接收到消息时才输出它们,也就是起到了⼀个消息同步输出的效果。
2 过滤器模式
为了提供统⼀的接⼝与输出,message_filters中所有的消息过滤器都遵循着相同的模式连接输⼊和输出。
输⼊是通过过滤器构造函数或者是connectInput()⽅法链接。
输出是通过registerCallback()⽅法连接。
但是每个过滤器都定义了输⼊和输出的类型,所以并不是所有的过滤器都可以直接相互连接。
例如,给出两个过滤器FooFilter和BarFilter,其中FooFilter的输出作为BarFilter的输⼊,将foo连接到bar可以是(在C ++中):
FooFilter foo;
BarFilter bar(foo);//通过过滤器构造函数
或者是
FooFilter foo;
BarFilter bar;
在Python中
bar(foo)
或
然后接着讲bar输出到你所指定的回调函数中:
2.1 registerCallback()
你可以使⽤registerCallback()⽅法注册多个回调,他们将会按照注册的顺序依次进⾏调⽤。
在C++中,registerCallback()返回⼀个message_filters :: Connection对象,允许您通过调⽤其disconnect()⽅法断开回调。 如果您不想⼿动断开回调,则不需要存储此连接对象。
3 Subscriber订阅者
订阅者过滤器是对ROS订阅的封装,为其他过滤器提供源代码,订阅者过滤器⽆法将另⼀个过滤器的输出作为其输⼊,⽽是使⽤ROS主题作为其输⼊。
3.1 输⼊输出形式
输⼊
⽆输⼊连接
输出
C++: void callback(const boost::shared_ptr<M const>&)
Python: callback(msg)
3.2 例⼦(C++)
message_filters::Subscriber<std_msgs::UInt32> sub(nh, "my_topic", 1);
同等于
ros::Subscriber sub = nh.subscribe("my_topic", 1, myCallback);
3.3 例⼦(Python)
sub = message_filters.Subscriber("po_topic", robot_msgs.msg.Po)
4. Time Synchronizer 时间同步器
TimeSynchronizer过滤器通过包含在其头中的时间戳来同步输⼊通道,并以单个回调的形式输出它们需要相同数量的通道。 C ++实现可以同步最多9个通道。
4.1 输⼊输出形式
输⼊
C ++: 最多9个独⽴的过滤器,每个过滤器的形式为void callback(const boost :: shared_ptr <M const>&)。 ⽀持的过滤器数量由类创建的模板参数的数量决定。
Python: N个单独的过滤器,每个过滤器都有签名回调(msg)。
输出
C ++: 对于消息类型M0..M8,void callback(const boost :: shared_ptr <M0 const>&,...,const boost :: shared_ptr <M8 const>&), 参数的数量由类创建的模板参数的数量决定。
Python: callback(msg0 .. msgN)。 参数的数量由类创建的模板参数的数量决定。
4.2 例⼦(C++)
假设您正在编写⼀个需要从两个时间同步主题处理数据的ROS节点。 您的程序可能看起来像这样:
#include <message_filters/subscriber.h>
#include <message_filters/time_synchronizer.h>
#include <nsor_msgs/Image.h>
#include <nsor_msgs/CameraInfo.h>
using namespace nsor_msgs;
using namespace message_filters;
void callback(const ImageConstPtr& image, const CameraInfoConstPtr& cam_info)
{
/
/ Solve all of
}烤比萨
int main(int argc, char** argv)
{
ros::init(argc, argv, "vision_node");南珍珠泉
ros::NodeHandle nh;
message_filters::Subscriber<Image> image_sub(nh, "image", 1);
message_filters::Subscriber<CameraInfo> info_sub(nh, "camera_info", 1);
TimeSynchronizer<Image, CameraInfo> sync(image_sub, info_sub, 10);
ros::spin();
return0;
}
在这种特殊情况下,您可以使⽤image_transport中的CameraSubscriber类,它基本上封装了上⾯的过滤代码。
4.3 例⼦(Python)
import message_filters
from nsor_msgs.msg import Image, CameraInfo
def callback(image, camera_info):
# Solve all of
image_sub = message_filters.Subscriber('image', Image)
info_sub = message_filters.Subscriber('camera_info', CameraInfo)
ts = message_filters.TimeSynchronizer([image_sub, info_sub], 10)
rospy.spin()
5. Time Sequencer 时间序列
Python版的时间序列过滤器还未实现
TimeSequencer过滤器根据报头的时间戳保证按时间顺序调⽤消息。TimeSequencer构造有⼀个特定的延迟,它指定在传递消息之前排队多长时间。 消息的回调直到消息的时间戳到达⼀定时间节点的时候才会调⽤。然⽽,对于所有已经⾄少延迟的消息,它们的回调被调⽤并保证是按时间顺序的。 如果⼀条消息从已经有其回调调⽤的消息之前的某个时间到达,则会被丢弃。
5.1 输⼊输出格式
输⼊
C++: void callback(const boost::shared_ptr<M const>&)
输出
C++: void callback(const boost::shared_ptr<M const>&)
5.2 例⼦(C++)
C ++版本采⽤延迟更新速率。 更新速率决定了定序器对准备好通过的消息检查其队列的频率。 最后⼀个参数是在开始抛出⼀些消息之前排队的消息数。
message_filters::Subscriber<std_msgs::String> sub(nh, "my_topic", 1);
message_filters::TimeSequencer<std_msgs::String> q(sub, ros::Duration(0.1), ros::Duration(0.01), 10);
6. Cache 缓存
⽤于存储历史时间的消息记录。
给定消息流,最近的N个消息被缓存在环形缓冲器中,然后可以由客户端检索⾼速缓存的时间间隔。消息的时间戳从其头字段确定。
如果消息类型不包含标题,请参阅下⾯的解决⽅法。
追男生的方法缓存⽴即将消息传递到其输出连接。
6.1 输⼊输出形式
输⼊
C++: void callback(const boost::shared_ptr<M const>&) Python: callback(msg)
输出
C++: void callback(const boost::shared_ptr<M const>&) Python: callback(msg)纽扣菊
在C++中:
message_filters::Subscriber<std_msgs::String> sub(nh, "my_topic", 1);
message_filters::Cache<std_msgs::String> cache(sub, 100);
在Python中
sub = message_filters.Subscriber('my_topic', nsor_msgs.msg.Image)
cache = message_filters.Cache(sub, 100)
在这个例⼦中,Cache存储了从my_topic上接收的最后100条消息,并且在添加每条新消息时调⽤myCallback。然后,⽤户可以调⽤Interval(start,end)来提取部分缓存。
如果消息类型不包含通常⽤于确定其时间戳的头字段,并且缓存与allow_headerless = True相关联,则将当前ROS时间⽤作消息的时间戳。 ⽬前仅在Python中可⽤。
sub = message_filters.Subscriber('my_int_topic', std_msgs.msg.Int32)
cache = message_filters.Cache(sub, 100, allow_headerless=True)
# the cache assigns current ROS time as each message's timestamp爆浆巧克力蛋糕
7. Policy-Bad Synchronizer 基于策略的同步器 [ROS 1.1+]
Synchronizer filter同步过滤器通过包含在其头中的时间戳来同步输⼊通道,并以单个回调的形式输出
它们需要相同数量的通道。 C ++实现可以同步最多9个通道。
Synchronizer过滤器在确定如何同步通道的策略上进⾏模板化。 ⽬前有两个策略:ExactTime和ApproximateTime。
C++ Header: message_filters/synchronizer.h
7.1 输⼊输出形式
输⼊
C ++: 最多9个独⽴的过滤器,每个过滤器的形式为void callback(const boost :: shared_ptr <M const>&)。 ⽀持的过滤器数量由类创建的模板参数的数量决定。
Python: N个单独的过滤器,每个过滤器都有签名回调(msg)。
输出
乌镇古镇
C ++: 对于消息类型M0..M8,void callback(const boost :: shared_ptr <M0 const>&,...,const boost :: shared_ptr <M8 const>&)。 参数的数量由类创建的模板参数的数量决定。
Python: callback(msg0 .. msgN)。 参数的数量由类创建的模板参数的数量决定。
7.2 ExactTime策略
message_filters :: sync_policies :: ExactTime策略要求消息具有完全相同的时间戳以便匹配。 只有在具有相同确切时间戳的所有指定通道上收到消息时,才会调⽤回调。 从所有消息的头域读取时间戳(这是该策略所必需的)。
C++头⽂件:message_filters/sync_policies/exact_time.h
#include <message_filters/subscriber.h>
#include <message_filters/synchronizer.h>
闭组词
#include <message_filters/sync_policies/exact_time.h>
#include <nsor_msgs/Image.h>
#include <nsor_msgs/CameraInfo.h>
using namespace nsor_msgs;
using namespace message_filters;
void callback(const ImageConstPtr& image, const CameraInfoConstPtr& cam_info)
{
// Solve all of
}
int main(int argc, char** argv)
{
ros::init(argc, argv, "vision_node");
ros::NodeHandle nh;
message_filters::Subscriber<Image> image_sub(nh, "image", 1);
message_filters::Subscriber<CameraInfo> info_sub(nh, "camera_info", 1);
typedef sync_policies::ExactTime<Image, CameraInfo> MySyncPolicy;
// ExactTime takes a queue size as its constructor argument, hence MySyncPolicy(10)
Synchronizer<MySyncPolicy> sync(MySyncPolicy(10), image_sub, info_sub);
ros::spin();衣柜的英文
return0;
}
7.3 ApproximateTime 策略
message_filters :: sync_policies :: ApproximateTime策略使⽤⾃适应算法来匹配基于其时间戳的消息。
如果不是所有的消息都有⼀个标题字段,从中可以确定时间戳,请参见下⾯的解决⽅法。
C++头⽂件:message_filters/sync_policies/approximate_time.h
例⼦(C++)