12-Ros 编写简单Pub和Sub节点[C++]

本教程介绍了如何创建C++开发语言的pub和sub节点,并演示二者之间通信。至于为什么选择deepin而不是ROS通用的ubuntu,也仅仅是为了支持国产系统。鉴于本人水平有限,如哪位攻城狮网友发现本文存在的问题,烦请留言指正,谢谢!

编写一个Publisher节点

节点是ROS术语,指连接到ROS网络的可执行程序。本教程我们创建一个Publisher节点,它会持续不断的向外广播消息。切换到beginner_tutorials包

roscd beginner_tutorials
# 创建src目录
mkdir -p src
# 然后在src目录下创建talker.cpp源文件
cd src
touch talker.cpp

之后将下面源码复制到taler.cpp

///ros/ros.h包好了ROS系统中最常见的头文件
#include "ros/ros.h"
/// 包含在std_msgs包里的String.h。这是一个自动从String.msg生成的头文件。具体可查阅msg对应的网站
#include "std_msgs/String.h"

#include <sstream>

/**
 * This tutorial demonstrates simple sending of messages over the ROS system.
 */
int main(int argc, char **argv)
{
  /**
   * ros::init()需要使用argc,argv两个参数,以便它可以执行命令行提供的ros参数和名称重映射
   * 对于编程式重映射,你可以使用不同版本的init(),它可以直接重映射。但对于大多数命令行程序
   * 来说传递argc,argv是最简单的方式。第三个参数是节点名称[不能有/]。在使用ros系统任何其他部分之前,必须
   * 调用ros::init()其中一个版本
   */
  ros::init(argc, argv, "talker");

  /**
   * NodeHandle是ROS通信中的主要访问点。创建第一个NodeHandle将实际知行节点初始化
   * 销毁最后一个NodeHanle时将清除节点正在使用的所有资源
   */
  ros::NodeHandle n;

  /**
  advertise()主要是告知ROS,接下来你要做什么。此处是将在topic:chatter上发布std_msgs/String类型的消息,
  master维护了哪些节点在发布什么消息订阅何种消息的注册表,advertise()调用后,master将通知其他订阅此消息的节点。
  订阅消息的节点会反过来与发布节点建立点对点通信关系。第二个参数是发布队列的大小,这里设置的是
  1000,在这种情况下,如果我们发布的太快,它将在开始丢数据之前缓存1000条消息。
  NodeHandle::advertise()返回ros::Publisher对象以方便你后续使用其成员函数publish()发布消息。一旦所有Publisher对象
  销毁后,也将自动取消此topic上的消息广播。
  **/
  ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);

  /// ros::Rate对象用于指定消息发布的频率。下面是要以10Hz的周期发布topic消息
  ros::Rate loop_rate(10);

  /**
   * 统计发送的消息数,用于创建第一无二的消息体.
   */
  int count = 0;
  /**
   * ros::ok()返回false的情况:
   *   1.CTRL-C
   *   2.被另一同名节点踢出ROS网络
   *   3.应用程序其他部分调用了ros::shutdown()
   *   4.所有的ros::NodeHandlers都销毁
   * 一旦ros::ok()返回失败,所有的ROS调用都将失败。
  **/ 
  while (ros::ok())
  {
    /**
     * 使用何时的消息适应类在ROS上广播消息。通常由msg文件产生,这里使用String消息
     */
    std_msgs::String msg;
    std::stringstream ss;
    ss << "hello world " << count;
    msg.data = ss.str();
    
    //替换cout/printf等的日志输出函数,可参考rosconsole
    ROS_INFO("%s", msg.data.c_str());

    /**
     * publish()会广播一条消息.参数就是消息对象。
     * 此处需要注意publish()中的参数的类型必须与advertise<>() 调用时设置的类型保持一致
     */
    chatter_pub.publish(msg);///发布消息

    /**
     * 这里ros::spinOnce()调用是不必要的。因为我们没有收到任何回调。但是如果你要在这个程序中添加
     * 一个subscriber,但是你的程序没有调用ros::spinOnce()那么subscriber所注册的回调函数永远
     * 不会被调用。这里添加上只是为了以防万一
    **/
    ros::spinOnce();

    loop_rate.sleep();///ros::Rate对象按照前面的设置进行休眠延时。
    ++count;
  }
  return 0;
}

msg
rosconsole

publisher的主要流程:

  • 初始化ros
  • 告知master我们要在哪个topic上发布什么类型的消息
  • 循环发布消息

编写一个subscriber

在src目录创建listener.cpp并复制如下代码

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

/**
 * 当subscriber在ROS系统中接收到消息会调用此回调函数.
 * 此消息在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,并设置节点名为listener
   */
  ros::init(argc, argv, "listener");

  /**
   * NodeHandle是ROS通信中的主要访问点。创建第一个NodeHandle将实际知行节点初始化
   * 销毁最后一个NodeHanle时将清除节点正在使用的所有资源
   */
  ros::NodeHandle n;

  /**
   * 与master通信,告知master此节点订阅chatter的主题消息.当接收到
   * chatter主题消息时会自动调用回调函数chatterCallback函数。第二个
   * 参数是队列大小,以防止我们不能足够快处理数据。如果队列中有1000条消息后
   * 后续消息在之前消息没处理的时候是会丢弃的。
   * n.subscribe()函数返回一个ros::Subscriber独享,你可以一致使用此对象,直到
   * 你想销毁此订阅对象时,它将自动取消对应主题消息的订阅。对于subscribe()函数其他版本
   * 可参考roscpp
   */
  ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);

  /**
   * 进入loop循环,以尽可能快的速度调用回调函数,不用担心,它不会耗费太多CPU资源。一旦ros::ok()返回false
   * ros::spin()也会退出。
   */
  ros::spin();

  return 0;
}

roscpp
subscriber的主要流程:

  • 初始化ros
  • 订阅topic消息
  • spin,等待消息到来
  • 消息到来后,回调函数调用,进行业务处理

构建节点

在此教程之前您使用catkin_create_pkg,其创建了package.xml和CMakeList.txt.
再经过前面srv,msg教程的修改后CMakeList.txt如下:

cmake_minimum_required(VERSION 2.8.3)
project(beginner_tutorials)

## Find catkin and any catkin packages
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs genmsg)

## Declare ROS messages and services
add_message_files(DIRECTORY msg FILES Num.msg)
add_service_files(DIRECTORY srv FILES AddTwoInts.srv)

## Generate added messages and services
generate_messages(DEPENDENCIES std_msgs)

## Declare a catkin package
catkin_package()

现在在此CMakeLists.txt的尾部添加如下内容

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)

修改后的CMakeList.txt如下:

cmake_minimum_required(VERSION 2.8.3)
project(beginner_tutorials)

## Find catkin and any catkin packages
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs genmsg)

## Declare ROS messages and services
add_message_files(FILES Num.msg)
add_service_files(FILES AddTwoInts.srv)

## Generate added messages and services
generate_messages(DEPENDENCIES std_msgs)

## Declare a catkin package
catkin_package()

## Build talker and listener
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)

这会创建两个可执行文件talker和listener.它们将默认进入您的devel空间的包目录里。默认
位于 devel/lib/<包名>
CMakeLists.txt修改完后可进行构建

# 构建
catkin_make
# 运行
source devel/setup.bash

## 运行方式1
#终端1
rosrun beginner_tutorials talker
# 终端2
rosrun beginner_tutorials listener

## 运行方式2
cd devel/lib/<包名>
# 终端1 
./talker
# 终端2
./listener

运行效果如下:
在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值