• ROS 节点通信


     "节点(Node)" 是ROS中指代连接到ROS网络的可执行文件的术语。接下来,我们将会创建两个节点,一个是发布器节点("talker"),它将不断的在ROS网络中广播消息;另一个是接收节点("listener"),从ROS网络中接收("talker")节点发送的信息。

    //发布节点

    #include "ros/ros.h"
    #include "std_msgs/String.h"
    int main(int argc, char **argv)
    {
      ros::init(argc, argv, "talker");//创建发布消息的节点。名字为talker
    
      ros::NodeHandle n;//为这个进程的节点创建一个句柄。
    
      ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
    /*告诉master我们将要在chatter topic上发布一个std_msgs/String的消息。这样master就会告诉所有
    
    订阅了chatter topic的节点,将要有数据发布。第二个参数是发布序列的大小。在这样的情况下,如
    
    果我们发布的消息太快,缓冲区中的消息在大于1000个的时候就会开始丢弃先前发布的消息。*/
    
     ros::Rate loop_rate(10);
    /*ros::Rate对象可以允许你指定自循环的频率。它会追踪记录自上一次调用Rate::sleep()后时间的流
    
    逝,并休眠直到一个频率周期的时间。在这个例子中,我们让它以10hz的频率运行。*/
     int count = 0;
    
    /*roscpp会默认安装一个SIGINT句柄,它负责处理Ctrl-C键盘操作——使得ros::ok()返回FALSE。
    ros::ok()返回false,如果下列条件之一发生:
    SIGINT接收到(Ctrl-C)
    被另一同名节点踢出ROS网络
    ros::shutdown()被程序的另一部分调用
    所有的ros::NodeHandles都已经被销毁
    一旦ros::ok()返回false, 所有的ROS调用都会失效。*/
     while (ros::ok())
         {
            /*我们使用一个由msg file文件产生的‘消息自适应’类在ROS网络中广播消息。现在我们使  
    
          用标准的String消息,它只有一个数据成员"data"。当然你也可以发布更复杂的消息类型*/。
           std_msgs::String msg;
           std::stringstream ss;
          ss << "hello world " << count;
          msg.data = ss.str();
           ROS_INFO("%s", msg.data.c_str());
      
         chatter_pub.publish(msg);//现在我们已经向所有连接到chatter topic的节点发送了消息。
        ROS_INFO("%s", msg.data.c_str());//ROS_INFO和类似的函数用来替代printf/cout.
    
        ros::spinOnce();
          /*在这个例子中并不是一定要调用ros::spinOnce(),因为我们不接受回调。然而,如果你想拓
    
    展这个程序,却又没有在这调用ros::spinOnce(),你的回调函数就永远也不会被调用。所以,在这里最
    
    好还是加上这一语句。*/
    
        loop_rate.sleep();//这条语句是调用ros::Rate对象来休眠一段时间以使得发布频率为10hz。
         ++count;
         }
    }


    对上边的内容进行一下总结:
    初始化ROS系统
    在ROS网络内广播我们将要在chatter topic上发布std_msgs/String消息
    以每秒10次的频率在chatter上发布消息
    接下来我们要编写一个节点来接收消息。


    #include "ros/ros.h"
    #include "std_msgs/String.h"
            /*这是一个回调函数,当消息到达chatter topic的时候就会被调用。消息是以 boost 
    
    shared_ptr指针的形式传输,这就意味着你可以存储它而又不需要复制数据*/
    void chatterCallback(const std_msgs::String::ConstPtr& msg)
       {
         ROS_INFO("I heard: [%s]", msg->data.c_str());
       }
    int main(int argc, char **argv)
       {
    	ros::init(argc, argv, "listener");
    	ros::NodeHandle n;
            /*告诉master我们要订阅chatter topic上的消息。当有消息到达topic时,ROS就会调用
    
    chatterCallback()函数。第二个参数是队列大小,以防我们处理消息的速度不够快,在缓存了1000个
    
    消息后,再有新的消息到来就将开始丢弃先前接收的消息。*/
    
    
    	ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
    /*NodeHandle::subscribe()返回ros::Subscriber对象,你必须让它处于活动状态直到你不再想订阅该
    
    消息。当这个对象销毁时,它将自动退订 上的消息。*/
    
    	ros::spin();
    /*ros::spin()进入自循环,可以尽可能快的调用消息回调函数。如果没有消息到达,它不会占用很多
    
    CPU,所以不用担心。一旦ros::ok()返回FALSE,ros::spin()就会立刻跳出自循环。这有可能是
    
    ros::shutdown()被调用,或者是用户按下了Ctrl-C,使得master告诉节点要shutdown。也有可能是节
    
    点被人为的关闭。*/
    	return 0;
        }


    下边,我们来总结一下:
    初始化ROS系统
    订阅chatter topic
    进入自循环,等待消息的到达
    当消息到达,调用chatterCallback()函数

    最后,在多个节点同时运行的时候,可以新打开一个终端,输入如下指令来观察节点的通信图。

    $rqt_graph



  • 相关阅读:
    第三周作业
    #第四周作业
    第十二周作业
    第十一周作业
    第九周作业
    第八周作业
    2019第七周作业
    第三次实验报告及第五次课程总结
    第二次课程总结&学习总结
    第三周实验和学习总结
  • 原文地址:https://www.cnblogs.com/zhubaohua-bupt/p/7182810.html
Copyright © 2020-2023  润新知