【ROS通信机制进阶一】初始化函数和话题服务对象

这里记录下ROS中初始化函数和话题服务对象的进阶操作,其实涉及的代码不多,主要借助之前写好的话题发布者和订阅者进行举例。

1 先介绍初始化函数

/** @brief ROS初始化函数。
 *
 * 该函数可以解析并使用节点启动时传入的参数(通过参数设置节点名称、命名空间...) 
 *
 * 该函数有多个重载版本,如果使用NodeHandle建议调用该版本。 
 *
 * \param argc 参数个数(n+1,其中那1个是自身)
 * \param argv 参数列表
 * \param name 节点名称,需要保证其唯一性,不允许包含命名空间
 * 节点名称要唯一,否则重复启动,启动早的容易被覆盖
 *  ros::init_options::AnonymousName:避免同一个名称的节点多次启动,会追加时间的编码
 * \param options 节点启动选项,被封装进了ros::init_options
 *
 */
void init(int &argc, char **argv, const std::string& name, uint32_t options = 0);

初始状态:

//1 初始化ros节点
ros::init(argc,argv,"publisher");

改变后的状态

//1 初始化ros节点
ros::init(argc,argv,"publisher",ros::init_options::AnonymousName);

2 话题服务对象

/**
* \brief 根据话题生成发布对象
*
* 在 ROS master 注册并返回一个发布者对象,该对象可以发布消息
*
* 使用示例如下:
*
*   ros::Publisher pub = handle.advertise<std_msgs::Empty>("my_topic", 1);
*
* \param topic 发布消息使用的话题
*
* \param queue_size 等待发送给订阅者的最大消息数量
*
* \param latch (optional) 如果为 true,该话题发布的最后一条消息将被保存,并且后期当有订阅者连接时会将该消息发送给订阅者
一般在发送静态地图时,设置为 true,这时发送方仅需要发送一次,即可当接收方连接时,收到消息
*
* \return 调用成功时,会返回一个发布对象
*
*
*/

调用 latch 之前

 //3 创建发布者对象
 //ros::Publisher pub =nh.advertise<std_msgs::String>("fang",10);

调用 latch 之后

ros::Publisher pub = nh.advertise<std_msgs::String>("fang",10,true);

发布方完整代码 C++

#include "ros/ros.h"
#include "std_msgs/String.h"
#include 

int main(int argc,char *argv[]){
    /*
    init 方法中,有几个参数
        argc:参数个数(n+1,其中那1个是自身)
        argv:接收传递的参数
       
        options: 可选项
              name:节点名称要唯一,否则重复启动,启动早的容易被覆盖
              ros::init_options::AnonymousName:避免同一个名称的节点多次启动,会追加时间的编码
     */
   setlocale(LC_ALL,"");
    //1 初始化ros节点
    ros::init(argc,argv,"publisher",ros::init_options::AnonymousName);
    //2 创建句柄
    ros::NodeHandle nh;
   /**
* \brief 根据话题生成发布对象
*
* 在 ROS master 注册并返回一个发布者对象,该对象可以发布消息
*
* 使用示例如下:
*
*   ros::Publisher pub = handle.advertise("my_topic", 1);
*
* \param topic 发布消息使用的话题
*
* \param queue_size 等待发送给订阅者的最大消息数量
*
* \param latch (optional) 如果为 true,该话题发布的最后一条消息将被保存,并且后期当有订阅者连接时会将该消息发送给订阅者
一般在发送静态地图时,设置为 true,这时发送方仅需要发送一次,即可当接收方连接时,收到消息
*
* \return 调用成功时,会返回一个发布对象
*
*
*/
    //3 创建发布者对象
    //ros::Publisher pub = nh.advertise("fang",10);
    ros::Publisher pub = nh.advertise<std_msgs::String>("fang",10,true);
    //4 编写发布逻辑并发布数据
     // 创建被发布的信息
    std_msgs::String msg;
    //定义频率
    ros::Rate rate(10);
    //设置编号
    int count=0;
    //可让发送数据前 休眠3秒 当作是注册到roscore的时间
    //这样可保证订阅者 可 接收到前几个信息
    ros::Duration(3).sleep();
     //循环发布
     while(ros::ok()){
        count++;
        std::stringstream ss;
        ss << "hello ---> " << count;

        msg.data = ss.str();
        if(count <= 10){
             pub.publish(msg);
            //添加日志
            ROS_INFO("发布的数据为: %s",ss.str().c_str());
        }
       
        rate.sleep();
        //官方建议 主要用于调用回调函数
        ros::spinOnce();
     }
    return 0;
}

订阅方完整代码 C++

#include "ros/ros.h"
#include "std_msgs/String.h"
void doMsg(const std_msgs::String::ConstPtr &msg){
    ROS_INFO("subcribe msg: %s", msg->data.c_str());
}
int main(int argc, char *argv[]){
    setlocale(LC_ALL,"");
    //1 初始化ros节点
    ros::init(argc,argv,"subcribe");
    //2 创建句柄
    ros::NodeHandle nh;
    //3 创建发布者对象
    ros::Subscriber sub = nh.subscribe("fang",10,doMsg);
   //为了处理上面的回调函数
    ros::spin();
    return 0;
}

发布和订阅效果

【注】这里的消息发布方即使 init 同名情况下,仍可发布,主要是因为在 ros::init 中添加了 ros::init_options::AnonymousName
先启动

roscore

然后再启动 发布节点,测试 latch 的作用,即发布者先发布,待发布者将十条数据发完,订阅者在启动,测试订阅者能否接收到信息。

source ./devel/setup.bash
rosrun plumbing_test(项目名) test01_pub_node(节点名)

十条数据结束:
【ROS通信机制进阶一】初始化函数和话题服务对象_第1张图片

然后再运行订阅节点

source ./devel/setup.bash
rosrun plumbing_test(项目名) test01_sub_node(节点名)

在这里插入图片描述
则明显,在发布节点结束后,订阅节点仍能接收到最后一条消息。

你可能感兴趣的:(C++,ROS,c++)