【11】Writing a Simple Publisher and Subscriber (C++)

Publisher

#include "ros/ros.h"

#include "std_msgs/String.h"

#include <sstream>

int main(int argc, char **argv)

{

  ros::init(argc, argv, "talker");   //1.启动该节点  2.并设置其名称(名称要唯一)

  ros::NodeHandle n;      //设置节点句柄

  ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);

        //将节点设置成发布者,并将所发布主题的类型和名称告知节点管理器。

          第一个参数是消息的名称,设置为 message;

          第二个参数是缓冲区的大小。如果主题发布数据速度较快,那么将缓冲区设置为 1000 个消息
  ros::Rate loop_rate(10);    //发送数据的频率10Hz

  while (ros::ok())       //收到Crtl+C消息或者ROS停止运行,ros::ok()库会执行停止节点运行命令

  {

        //创建一个消息变量(消息的类型必须符合发送数据的要求)

    std_msgs::String msg;

    std::stringstream ss;

    ss << "hello world " << count;

    msg.data = ss.str();

    ROS_INFO("%s", msg.data.c_str());   //ROS_INFO and friends are our replacement for printf/cout.

    chatter_pub.publish(msg);          //就这样,消息被发布了。

    ros::spinOnce();            //若有Subscriber出现,ROS就会更新和读取所有主题

    loop_rate.sleep();               //按照10Hz的频率把程序挂起。(Why???)

    ++count;

  }

  return 0;



ROS Node

    1)在一个机器人软件中,有各种各样的node。别抢答,各种各样不是指localization,slam ,action这些功能的多种多样,而是指有消息的生产者,消费者,以及消费又生产的深加工者。先插一句吧,这次讨论涉及到这样的一个问题,在用ros构建一个机器人软件时,仅仅从功能划分的角度来构建node是否合适。是否还需要考虑让消息的流动更顺畅,让node更简洁高效呢?先说node是怎么跑的吧。当你建立一个node后,要么它按照一个固定的周期运行,要么它阻塞等待事件发生,由事件驱动运行。无论是那种,node都要干活,node干的什么活呢?callback queue里的活。这个callback queue里的callback是哪里来的呢?常见的是subscriber的callback,当然还有其他的,包括publisher的,service的。那这些callback是什么时候被调用的呢。那就是spin()或者spinonce()。spin调用在queue 里所有的availiable的callback,如果没有availible的,它就阻塞。spinonce,显然只调用一次,看看有没有准备好的callback,有就调用,没有就返回。那什么是availible的、准备好的呢?对于subscribe,准备好的就是那些有新消息的subscriber的callback。现在如果你明白了上述node的运行机理。你在感到舒服之余,请准备接收心烦的问题。1)第一个问题就是,如果subscriber没有收到新消息,那么它的callback就不会被执行。如果你想每次都运行callback呢?对不起,没办法,不是virgin我不娶。

    2)第二个问题,callback执行有个timeout值,如果设置不合理,要么费时,要么callback被中止。被中止呀,兄弟们,多可怕,万一是一个重要逻辑的一环呢?今天就聊到这里,最后送点福利,如果你想实现事件触发的node就用spin;如果你要固定周期的node,那就用spinonce+sleep,但一定要牢记,在每个周期里不是所有callback被执行。

Subscriber

#include "ros/ros.h"

#include "std_msgs/String.h"

        //每次该节点收到一条消息都会调用此函数,我们就可以使用或者处理数据。

            ROS_INFO()函数用于命令行打印数据

            (现在在这里面我们把收到的数据在命令行打印出来。)

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;

        //创建一个订阅者,并从topic获取以chatter为名的消息数据。

            设置缓冲区1000

            处理消息的回调函数为chatterCallback()

  ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);

        //ros::spin();库是node 读取数据的消息响应循环,当消息到达的时候,回调函数被调用。

             Ctrl+C时,node退出消息循环

  ros::spin();

  return 0;


编译节点

The generated CMakeLists.txt should look like this:

添加代码:

时间: 2024-10-13 16:54:22

【11】Writing a Simple Publisher and Subscriber (C++)的相关文章

ROS学习 Writing a Simple Publisher and Subscriber &amp; Examining them

本文主要部分全部来源于ROS官网的Tutorials. 创建Publisher Node roscd beginner_tutorials mkdir -p src gedit src/talker.cpp & 复制如下代码,其大致流程如下: Initialize the ROS system Advertise that we are going to be publishing std_msgs/String messages on the chatter topic to the mast

Writing a Simple Publisher and Subscriber

Writing the Publisher Node #!/usr/bin/env python # license removed for brevity import rospy from std_msgs.msg import String def talker(): pub = rospy.Publisher('chatter', String, queue_size=10) rospy.init_node('talker', anonymous=True) rate = rospy.R

Writing a Simple Publisher and Subscriber (Python)

Writing a Service Node Here we'll create the service ("add_two_ints_server") node which will receive two ints and return the sum. Change directory into the beginner_tutorials package, you created in the earlier tutorial, creating a package: $ ro

【POJ】3468 A Simple Problem with Integers ——线段树 成段更新 懒惰标记

A Simple Problem with Integers Time Limit:5000MS   Memory Limit:131072K Case Time Limit:2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each

【题解】 CF11D A Simple Task

[题解] CF11D A Simple Task 传送门 \(n \le 20\) 考虑状态压缩\(dp\). 考虑状态,\(dp(i,j,O)\)表示从\(i\)到\(j\)经过点集\(O\)的路径有多少. \(dp(i,j,O \bigcup i)=\Sigma dp(i,p,O)\),\(j-p\)有一条边. 考虑内存,我们可以认定状态压缩串中\(lowbit(x)\)位是一条路的起点,这样我们直接省掉一维.空间限制卡进去了. 考虑答案怎么统计,就是\((\Sigma (dp(i,j,O)

【kd-tree】bzoj3489 A simple rmq problem

Orz zyf教给蒟蒻做法 蒟蒻并不会这题正解……(可持久化树套树?...Orz 对于每个点,我们可以求出pre[i],nex[i],那么询问的答案就是:求max (a[i]),其中 i 满足(pre[i]<ql and nex[i]>qr and i∈[ql,qr]) 然后我们以(i,pre[i],nex[i])为坐标……将所有点抽象到三维空间中,每次查询就相当于是一次区域求最值! 这题我的感受: 因为前面做了两道区域求和的……然后思路不由自主又代入到搞[子树最大值]来更新答案……然而忘记了

【转载】C# Tutorial - Simple Threaded TCP Server

http://tech.pro/tutorial/704/csharp-tutorial-simple-threaded-tcp-server In this tutorial I'm going to show you how to build a threaded tcp server with C#. If you've ever worked with Window's sockets, you know how difficult this can sometimes be. Howe

【POJ】3468 A Simple Problem with Integers

这题用线段树轻松解了,重新用树状数组解,关键点是区间更新.公式推导如下:sum[x] = org_sum[x] + delta[1]*x + delta[2]*(x-1) + delta[x]*1           = org_sum[x] + Sigma(delta[1..x]) * (x+1) - Sigma(delta[i]*i)树状数组增加两个结点信息分别存delta[i] 和 delta[i] * i就好了. 1 /* 3468 */ 2 #include <iostream> 3

【HDOJ】4972 A simple dynamic programming problem

水题. 1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 5 int abs(int x) { 6 return x<0 ? -x:x; 7 } 8 9 int main() { 10 int t, n; 11 int cur, past; 12 __int64 ans; 13 bool flag; 14 15 #ifndef ONLINE_JUDGE 16 freopen("