ROS只发布和订阅一次消息

只发布一次消息

1
2
3
4
5
6
ros::init(argc,argv,"op_motor");
ros::NodeHandle nh;
ros::Publisher pub = nh.advertise<std_msgs::Bool>("Switch",1000);
//不必判断订阅者,直接等待1秒钟,只发布一次
sleep(1);
pub.publish(msg);

只发布一次消息就简单了,不必用while循环,直接发布就可以,但是最好也延时一次,防止订阅者的网络状况不好,当然如果不考虑有没有订阅者就不必延时了,不过这样没什么意义。


ROS只订阅一次消息

1
2
3
4
5
6
7
8
9
10
11
12
ros::init(argc,argv,"node");
ros::NodeHandle nh;
boost::shared_ptr<riki_msgs::Battery const> Edge; // 必须有const
Edge = ros::topic::waitForMessage<riki_msgs::Battery>("BMS",ros::Duration(0.1));
if(Edge != NULL)
{
riki_msgs::Battery bat = *Edge;
cout<<"battery:"<< bat.Ah <<endl;
cout<<"battery:"<< Edge->Ah <<endl;
}
else
cout<<"no message from topic BMS"<<endl;

waitForMessage是等待一次消息,造成的网络传输会出现延时。如果是获得消息后再发布,新话题的发布频率会明显下降 为了保证发布频率,还是尽量使用spin()

这里用到的函数是ros::topic::waitForMessage,没有涉及回调函数,它有4个重载,常用的是两个:

1
2
3
template<class M> boost::shared_ptr< M const >   waitForMessage (const std::string &topic, ros::Duration timeout)

template<class M> boost::shared_ptr< M const > waitForMessage (const std::string &topic, ros::NodeHandle &nh)

第一个是订阅话题topic,假如没有发布话题,那么等待时间timeout,超时后程序继续执行;第二个是如果没有发现话题topic,会一直阻塞,不能向下运行,除非执行rosnode kill。前一个用的比较多,注意时间不要设置太短,否则可能因为网络状况不好而订阅失败。

返回类型一看就知道是模板类的Boost共享指针,从这里就可以看出, 消息是以const Boost共享指针的形式传输,我们可以存储它而又不需要复制数据waitForMessage就是返回了订阅到的消息,取指向就可以获得消息成员,也可以直接用指针获得消息成员。
注意模板类型有const,否则不符合重载声明

回调函数中常见的MsgType::ConstPtr参数类型其实就是boost::shared_ptr<const MsgType>

MsgType::Ptr就是boost::shared_ptr<MsgType>

参考:

How do I publish exactly one message
ros::topic Namespace