ROS学习之 cpp消息发布者和消息订阅者


wiki链接: http://wiki.ros.org/roscpp/Overview/Publishers%20and%20Subscribers

一、发布一个话题

    其它相关链接:
        ros::NodeHandle,ros::NodeHandle::advertise() API:
            http://docs.ros.org/api/roscpp/html/classros_1_1NodeHandle.html
        ros::Publisher API:
            http://docs.ros.org/api/roscpp/html/classros_1_1Publisher.html
    创建一个句柄来向话题发布消息,使用ros::NodeHandle类,参见: http://wiki.ros.org/roscpp/Overview/NodeHandles
    NodeHandle::advertise()方法被用来创建一个ros::Publisher对象,该对象用于在话题上发布消息。
        ros::Publisher pub = nh.advertise<std_msgs::String>("topic_name", 5);
        std_msgs::String str;
        str.data = "hello world";
        pub.publish(str);
    1、内部线程发布
        当一个节点内部存在对于同一个话题的消息发布者和订阅者时,roscpp会跳过序列化和去序列化的过程(节省了处理过程和延迟)。
        该方法只适用于以共享指针发布的消息
            ros::Publisher pub = nh.advertise<std_msgs::String>("topic_name", 5);
            std_msgs::StringPtr str(new std_msgs::String);   //消息指针
            str->data = "hello world";
            pub.publish(str);
    2、发布消息可选项
        advertise()简单版的原型:
            template<class M>
            ros::Publisher advertise(const std::string& topic, uint32_t queue_size, bool latch = false);        
        参数说明: M,必须,这是一个模版参数,用于指定发布话题的具体消息的类型
              topic,必须,发布话题的名称
              queue_size,必须,消息队列的长度。如果发布消息的速度超过roscpp可以发布消息的速度,roscpp将丢弃最开始的消息
              latch,可选,使能连接的latching(门闩,弹簧锁)。当一个连接被latched,最后被发布的消息将被保存,自动发布给以后再订阅该话题的订阅者。

    3、发布者句柄的其它操作
        ros::Publisher 是内部引用的,也就是可以快速复制,而无需创建新的ros::Publisher.当所有ros::Publisher副本被销毁时,话题将被关闭。
        几个例外:
            1、ros::shutdown()调用,它将关闭所有publishers
            2、ros::Publisher::shutdown()调用,将关闭这一个话题,如果有的话。
            3、对同一话题,同一消息的多次调用NodeHandle::advertise()将产生对该话题的很多Publisher,它们被视为相互的副本。
        ros::Publisher实现了==,!=,和<操作符,也能用std::map,和std::set等
        可以使用ros::Publisher::getTopic()函数获取一个topic话题

    4、publish()行为和消息队列
        roscpp中的publish()是异步的,只有当话题有订阅者时才会工作(发布消息)。
        publish()自己本身很快,它1.将消息序列化进一个buffer;2.将buffer压入一个队列以备后续处理。
        这个队列之后被roscpp的内部线程处理,它将此队列送入每个连接此话题的subscriber,这一步中的队列长度取决于advertise()调用queue_size参数.
        如果队列长度溢出,最老的消息将在新消息加入队列之前被丢弃。
        
        注意:还有一个OS级的队列在传输层,比如TCP/UDP发送buffer.


二、订阅一个话题

    其它相关链接:
        ros::NodeHandle,ros::NodeHandle::subscribe() API:
            http://docs.ros.org/api/roscpp/html/classros_1_1NodeHandle.html
        ros::Subscriber API:
            http://docs.ros.org/api/roscpp/html/classros_1_1Subscriber.html
    创建一个句柄来向话题订阅消息,使用ros::NodeHandle类,参见: http://wiki.ros.org/roscpp/Overview/NodeHandles
    一个简单的订阅的全局函数:
    void callback(const std_msgs::StringConstPtr& str)
    {
        ...
    }

    ...
    ros::Subscriber sub = nh.subscribe("my_topic", 1, callback);    
    
    1、对订阅者的操作
        一个简单的ros::NodeHandle::subscribe()函数的原型如下:
        template<class M>
        ros::Subscriber subscribe(const std::string& topic, uint32_t queue_size, <callback, which may involve multiple arguments>, const ros::TransportHints& transport_hints = ros::TransportHints());
    参数说明:M,不必要,模版参数,说明消息的类型。对于subscribe()函数,不必显式定义消息的类型,编译器可以从回调函数的参数中来推测出消息的类型。
        topic,订阅的话题
        queue_size,roscpp使用该参数将此长度的消息队列传递给回调函数。
        <callback>,消息处理回调函数
        transport_hints,对roscpp传输层的具体指定


    2、回调函数原型
        一个回调函数的原型如下:
        void callback(const boost::shared_ptr<Message const>&);
    3、回调函数的类型
        1)一般函数
            一般函数的使用最为简单。
            例子如上。
        2)类成员方法
            类成员方法的使用也很简单,在调用时要加入类对象的参数
            void Foo::callback(const std_msgs::StringConstPtr& message)
            {
            }

            ...
            Foo foo_object;
            ros::Subscriber sub = nh.subscribe("my_topic", 1, &Foo::callback, &foo_object);
        3)仿函数对象(一个类的使用看上去像一个函数,包括 boost::bind)
            一个仿函数对象是一个定义了operator()函数的类。
            class Foo
            {
                public:
                  void operator()(const std_msgs::StringConstPtr& message)
                  {
                  }
            };
            传递给subscribe()函数的仿函数必须copyable,使用下述语法调用:
                ros::Subscriber sub = nh.subscribe<std_msgs::String>("my_topic", 1, Foo());

            注意:使用仿函数时,必须显式地声明消息类型模版参数,因为在此种情况下,编译器不会推测出消息类型。
    4、消息事件类[ROS 1.1+]

        MessageEvent API: http://docs.ros.org/api/roscpp_traits/html/classros_1_1MessageEvent.html
        MessageEvent类允许从一个订阅回调函数中提取消息的元数据信息。    
        
        使用语法如下:
            void callback(const ros::MessageEvent<std_msgs::String const>& event)
            {
              const std::string& publisher_name = event.getPublisherName();  //一些关于此消息事件的元数据信息
              const ros::M_string& header = event.getConnectionHeader();
              ros::Time receipt_time = event.getReceiptTime();

              const std_msgs::StringConstPtr& msg = event.getMessage();  //从消息事件中获取消息,然后可以进行相应处理
            }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值