博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Ros学习——C++发布器publisher和订阅器subscriber
阅读量:5781 次
发布时间:2019-06-18

本文共 8077 字,大约阅读时间需要 26 分钟。

 

1.编写发布器

  • 初始化 ROS 系统
  • 在 ROS 网络内广播我们将要在 chatter 话题上发布  类型的消息

  • 以每秒 10 次的频率在 chatter 上发布消息

在 beginner_tutorials package 里创建 src/talker.cpp 文件:

#include "ros/ros.h"      //一个实用的头文件,它引用了 ROS 系统中大部分常用的头文件#include "std_msgs/String.h"  //引用了  消息, 它存放在  package 里,是由 String.msg 文件自动生成的头文件。#include 
/** * This tutorial demonstrates simple sending of messages over the ROS system. */int main(int argc, char **argv){ /** * The ros::init() function needs to see argc and argv so that it can perform * any ROS arguments and name remapping that were provided at the command line. For programmatic * remappings you can use a different version of init() which takes remappings * directly, but for most command-line programs, passing argc and argv is the easiest * way to do it. The third argument to init() is the name of the node. * * You must call one of the versions of ros::init() before using any other * part of the ROS system. */ ros::init(argc, argv, "talker");  //初始化 ROS.可指定节点的名称。节点的名称必须唯一(名称内不能包含 / 等符号) /** * NodeHandle is the main access point to communications with the ROS system. * The first NodeHandle constructed will fully initialize this node, and the last * NodeHandle destructed will close down the node. */ ros::NodeHandle n;  //为这个进程的节点创建一个句柄。              //第一个创建的 NodeHandle 会为节点进行初始化,最后一个销毁的 NodeHandle 则会释放该节点所占用的所有资源 /** * The advertise() function is how you tell ROS that you want to * publish on a given topic name. This invokes a call to the ROS * master node, which keeps a registry of who is publishing and who * is subscribing. After this advertise() call is made, the master * node will notify anyone who is trying to subscribe to this topic name, * and they will in turn negotiate a peer-to-peer connection with this * node. advertise() returns a Publisher object which allows you to * publish messages on that topic through a call to publish(). Once * all copies of the returned Publisher object are destroyed, the topic * will be automatically unadvertised. * * The second parameter to advertise() is the size of the message queue * used for publishing messages. If messages are published more quickly * than we can send them, the number here specifies how many messages to * buffer up before throwing some away. */ ros::Publisher chatter_pub = n.advertise
("chatter", 1000);//告诉master 我们将要在 chatter(话题名) 上发布  消息类型的消息。             //如果我们发布的消息的频率太高,缓冲区中的消息在大于 1000 个的时候就会开始丢弃先前发布的消息。              //advertise返回一个 ros::Publisher 对象,它有两个作用: 1) 它有一个 publish() 成员函数可以让你在topic上发布消息; 2) 如果消息类型不对,它会拒绝发布。
ros::Rate loop_rate(10);///**   * A count of how many messages we have sent. This is used to create   * a unique string for each message.   */  int count = 0;  while (ros::ok())      //ros::ok()  {    /**     * This is a message object. You stuff it with data, and then publish it.     */    std_msgs::String msg;    std::stringstream ss;    ss << "hello world " << count;    msg.data = ss.str();    ROS_INFO("%s", msg.data.c_str());//ROS_INFO 和其他类似的函数可以用来代替 printf/cout 等函数。    /**     * The publish() function is how you send messages. The parameter     * is the message object. The type of this object must agree with the type     * given as a template parameter to the advertise<>() call, as was done     * in the constructor above.     */    chatter_pub.publish(msg);//向所有订阅 chatter 话题的节点发送消息。    ros::spinOnce();      //ros::spinOnce()这一语句,否则你的回调函数就永远也不会被调用    loop_rate.sleep();    //调用 ros::Rate 对象来休眠一段时间以使得发布频率为 10Hz。    ++count;  }  return 0;}

 

2.编写订阅器

  

  • 初始化ROS系统
  • 订阅 chatter 话题

  • 进入自循环,等待消息的到达
  • 当消息到达,调用 chatterCallback() 函数

 

在 beginner_tutorials package 目录下创建 src/listener.cpp 文件:

#include "ros/ros.h"#include "std_msgs/String.h"/** * This tutorial demonstrates simple receipt of messages over the ROS system. */void chatterCallback(const std_msgs::String::ConstPtr& msg)//是一个回调函数,当接收到 chatter 话题的时候就会被调用。{  ROS_INFO("I heard: [%s]", msg->data.c_str());}int main(int argc, char **argv){  /**   * The ros::init() function needs to see argc and argv so that it can perform   * any ROS arguments and name remapping that were provided at the command line. For programmatic   * remappings you can use a different version of init() which takes remappings   * directly, but for most command-line programs, passing argc and argv is the easiest   * way to do it.  The third argument to init() is the name of the node.   *   * You must call one of the versions of ros::init() before using any other   * part of the ROS system.   */  ros::init(argc, argv, "listener");  /**   * NodeHandle is the main access point to communications with the ROS system.   * The first NodeHandle constructed will fully initialize this node, and the last   * NodeHandle destructed will close down the node.   */  ros::NodeHandle n;  /**   * The subscribe() call is how you tell ROS that you want to receive messages   * on a given topic.  This invokes a call to the ROS   * master node, which keeps a registry of who is publishing and who   * is subscribing.  Messages are passed to a callback function, here   * called chatterCallback.  subscribe() returns a Subscriber object that you   * must hold on to until you want to unsubscribe.  When all copies of the Subscriber   * object go out of scope, this callback will automatically be unsubscribed from   * this topic.   *   * The second parameter to the subscribe() function is the size of the message   * queue.  If messages are arriving faster than they are being processed, this   * is the number of messages that will be buffered up before beginning to throw   * away the oldest ones.   */  ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
//告诉 master 我们要订阅 chatter 话题上的消息。当有消息发布到这个话题时,ROS 就会调用 chatterCallback() 函数。第二个参数是队列大小,以防我们处理消息的速度不够快,当缓存达到 1000 条消息后,再有新的消息到来就将开始丢弃先前接收的消息。
 

 

/** * ros::spin() will enter a loop, pumping callbacks. With this version, all * callbacks will be called from within this thread (the main one). ros::spin() * will exit when Ctrl-C is pressed, or the node is shutdown by the master. */ ros::spin();//ros::spin() 进入自循环,可以尽可能快的调用消息回调函数。 return 0; }

 

3.编译

  • 1.确认文件
cmake_minimum_required(VERSION 2.8.3)project(beginner_tutorials)## Find catkin and any catkin packagesfind_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs genmsg)## Declare ROS messages and servicesadd_message_files(DIRECTORY msg FILES Num.msg)add_service_files(DIRECTORY srv FILES AddTwoInts.srv)## Generate added messages and servicesgenerate_messages(DEPENDENCIES std_msgs)## Declare a catkin packagecatkin_package(
  • 2.在  文件末尾加入几条语句:
 

include_directories(include ${catkin_INCLUDE_DIRS})

add_executable(talker src/talker.cpp)

target_link_libraries(talker ${catkin_LIBRARIES})
add_dependencies(talker beginner_tutorials_generate_messages_cpp)

add_executable(listener src/listener.cpp)

target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(listener beginner_tutorials_generate_messages_cpp)

  • 1-2会生成两个可执行文件, talker 和 listener, 默认存储到  目录下,具体在~/catkin_ws/devel/lib/<package name> 中.
  • 3.如果在 *Groovy* 版本下,你可以使用下边的这个变量来添加对所有必须的文件依赖:
add_dependencies(talker ${catkin_EXPORTED_TARGETS})
  • 4.运行 catkin_make

 4.测试结果:

 

 

5.问题:

1.当你在package.xml中,添加完run_depend后,编译出错,显示The manifest must not cotain the following  tags:run_depend。

原因:软件包格式分两种,第一种的四种依赖关系分别是:

第二种的依赖关系变成:

 

解决:当你run_depend出错时,有可能是你的软件包格式是第二种,所以要把run_depend改成exec_depend

 

2.invoking "make cmake_check_build_system" failed

仔细检查:

cmake_minimum_required(VERSION 2.8.3)project(beginner_tutorials)## Find catkin and any catkin packagesfind_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs genmsg)## Declare ROS messages and servicesadd_message_files(DIRECTORY msg FILES Num.msg)add_service_files(DIRECTORY srv FILES AddTwoInts.srv)## Generate added messages and servicesgenerate_messages(DEPENDENCIES std_msgs)## Declare a catkin packagecatkin_package()  #尤其要注意,里面为空否则报上面的错

 

转载于:https://www.cnblogs.com/yrm1160029237/p/9991014.html

你可能感兴趣的文章
限时 | 你需要的人工智能学习资料,都在这里【附下载】
查看>>
一款简单的UILabel,可设置字间距,行间距等
查看>>
[Vue]手撸多文件上传组件
查看>>
自学 JAVA 的几点建议
查看>>
五个案例,三大心得,Meratix 创始人带你进阶深度学习的实践应用之路
查看>>
MaxCompute安全管理指南-基础篇
查看>>
2019年快来了,送给每位程序员一份新年计划清单
查看>>
Java Web开发中文乱码问题
查看>>
前端如何优化代码?
查看>>
Spring boot学习(六)Spring boot实现AOP记录操作日志
查看>>
@程序员,你会教自己的孩子学习编程吗?
查看>>
轻松学会责任链模式
查看>>
威胁快报|ProtonMiner挖矿蠕虫扩大攻击面,加速传播
查看>>
<<深入PHP面向对象、模式与实践>>读书笔记:面向对象设计和过程式编程
查看>>
架构的“一小步”,业务的一大步
查看>>
聊聊flink JobManager的heap大小设置
查看>>
PAT A1116
查看>>
App上架/更新怕被拒? iOS过审“避雷秘籍”请查收
查看>>
CentOS 7 防火墙操作
查看>>
关于 top 工具的 6 个替代方案
查看>>