运行环境:Ubuntu 16.04 64位虚拟机

 

ROS消息通信中使用的发布者(Publisher)和订阅者(Subscriber)可以被发送和接收所代替。在ROS中,发送端称为发布者,接收端称为订阅者。本节旨在创建一个简单的msg文件,并创建和运行发布者和订阅者节点。

创建功能包

以下命令是创建ros_tutorials_topic功能包的命令。这个功能包依赖于message_generation、std_msgs和roscpp功能包,因此将这些用作依赖选项。第二行命令意味着将使用创建新的功能包时用到的message_generation表示将使用创建新消息的功能包

std_msgs(ROS标准消息功能包)和roscpp(在ROS中使用C/C ++的客户端程序库)必须在创建功能包之前安装。用户可以在创建功能包时指定这些相关的功能包设置,但也可以在创建功能包之后直接在package.xml中修改。

$ cd ~/catkin_ws/src

$ catkin_create_pkg ros_tutorials_topic message_generation std_msgs roscpp

创建功能包时,将在~/catkin_ws/src目录中创建ros_tutorials_topic功能包目录,并在该功能包目录中创建ROS功能包的默认目录和CMakeLists.txt和package.xml文件。

然后是修改package.xml文件

注意:《ROS_Robot_Programming_CN.pdf》文档7.2.2章节有错,按照里面修改的编译会报错,

报错内容如下:

《ROS_Robot_Programming_CN.pdf》文档下载地址:

https://download.csdn.net/download/gs1069405343/11029109

正确的修改如下: 

  <license>Apache License 2.0</license>

  <buildtool_depend>catkin</buildtool_depend>

  <build_depend>roscpp</build_depend>

  <build_depend>std_msgs</build_depend>

  <build_export_depend>roscpp</build_export_depend>

  <build_export_depend>std_msgs</build_export_depend>

  <exec_depend>roscpp</exec_depend>

  <exec_depend>std_msgs</exec_depend>

修改构建配置文件(CMakeLists.txt)

详细的请参考ROS_Robot_Programming_CN.pdf 见第4.9节 或者学习笔记4

当前修改内如如下:

find_package(catkin REQUIRED COMPONENTS
  message_generation
  roscpp
  std_msgs
)

add_message_files(
FILES
MsgTutorial.msg
#   Message1.msg
#   Message2.msg
)

generate_messages(
  DEPENDENCIES
  std_msgs
)

catkin_package(
#  INCLUDE_DIRS include
   LIBRARIES ros_tutorials_topic
#  CATKIN_DEPENDS message_generation roscpp std_msgs
   CATKIN_DEPENDS roscpp std_msgs
#  DEPENDS system_lib
)

add_executable(topic_publisher src/topic_publisher.cpp)
add_executable(topic_subscriber src/topic_subscriber.cpp)
add_dependencies(topic_publisher ${${PROJECT_NAME}_EXPORTED_TARGETS} 
${catkin_EXPORTED_TARGETS})
add_dependencies(topic_subscriber ${${PROJECT_NAME}_EXPORTED_TARGETS} 
${catkin_EXPORTED_TARGETS})
target_link_libraries(topic_publisher ${catkin_LIBRARIES})
target_link_libraries(topic_subscriber ${catkin_LIBRARIES})

修改完之后,保存退出。

创建消息文件

在上述的CMakeLists.txt文中添加了如下选项。

add_message_files(FILES MsgTutorial.msg)

这意味着在构建时要包含消息MsgTutorial.msg,该消息将在此节点中被使用。现在

我们还没有创建MsgTutorial.msg,因此按以下顺序创建它:

$ roscd ros_tutorials_topic    → 移动到功能包目录

$ mkdir msg                → 功能包中创建新的msg消息目录

$ cd msg                  → 转到创建的msg目录

$ gedit MsgTutorial.msg      → 创建新的MsgTutorial.msg文件并修改内容

然后写入如下内容:

time stamp

int32 data

创建发布者节点

创建源码文件

$ roscd ros_tutorials_topic/src      → 移至src目录,该目录是功能包的源代码目录

$ sudo gedit topic_publisher.cpp     → 新建源文件并修改内容

在文件中添加如下代码

// ROS默认头文件
#include "ros/ros.h"

// MsgTutorial消息头文件( 构建后自动生成)
#include "ros_tutorials_topic/MsgTutorial.h"

 // 节点主函数
int main(int argc, char **argv)
{
    // 初始化节点名称
    ros::init(argc, argv, "topic_publisher");    

    // 声明一个节点句柄来与ROS系统进行通信
    ros::NodeHandle nh;

    // 声明发布者,创建一个使用ros_tutorials_topic功能包的MsgTutorial 消息文件的
    // 发布者ros_tutorial_pub。话题名称是"ros_tutorial_msg",
    // 消息文件发布者队列(queue)的大小设置为100
    ros::Publisher ros_tutorial_pub = nh.advertise<ros_tutorials_topic::MsgTutorial>("ros_tutorial_msg", 100);

    // 设定循环周期。"10"是指10Hz,是以0.1秒间隔重复
    ros::Rate loop_rate(10);

    // 以MsgTutorial消息文件格式声明一个 叫做msg的消息
    ros_tutorials_topic::MsgTutorial msg;

    // 声明要在消息中使用的变量
    int count = 0;
    while (ros::ok())
    {
         // 把当前时间传给msg的下级消息stamp 
        msg.stamp = ros::Time::now();

        // 将变量count的值传给下级消息data
        msg.data  = count;
        // 显示stamp.sec消息
        ROS_INFO("send msg = %d", msg.stamp.sec);
         // 显示stamp.nsec消息 
        ROS_INFO("send msg = %d", msg.stamp.nsec);
         // 显示data消息
        ROS_INFO("send msg = %d", msg.data);
         // 发布消息。
        ros_tutorial_pub.publish(msg);
         // 按照上面定义的循环周期进行暂歇
        loop_rate.sleep();
        // 变量count增加1
        ++count;
    }
    return 0;
}

然后保存退出。

创建订阅者节点

$ roscd ros_tutorials_topic/src     → 移动到src目录,该目录是功能包的源代码目录

$ sudo gedit topic_subscriber.cpp   → 创建和修改新的源代码文件

代码如下:

/ ROS的默认头文件
#include "ros/ros.h"
// MsgTutorial消息头文件(构建后自动生成)

#include "ros_tutorials_topic/MsgTutorial.h"
// 这是一个消息后台函数,
// 此函数在收到一个下面设置的名为ros_tutorial_msg的话题时候被调用。
// 输入的消息是从ros_tutorials_topic功能包接收MsgTutorial消息。
void msgCallback(const ros_tutorials_topic::MsgTutorial::ConstPtr& msg)
{
    ROS_INFO("recieve msg = %d", msg->stamp.sec);  // 显示stamp.sec消息
    ROS_INFO("recieve msg = %d", msg->stamp.nsec); // 显示stamp.nsec消息
    ROS_INFO("recieve msg = %d", msg->data);       // 显示data消息
}

// 节点主函数
int main(int argc, char **argv)
{
    // 初始化节点名称 
    ros::init(argc, argv, "topic_subscriber");

    // 声明用于ROS系统和通信的节点句柄
    ros::NodeHandle nh;

    // 声明订阅者,创建一个订阅者ros_tutorial_sub,
    // 它利用ros_tutorials_topic功能包的的MsgTutorial消息文件。
    // 话题名称是"ros_tutorial_msg",订阅者队列(queue)的大小设为100。
    ros::Subscriber ros_tutorial_sub = nh.subscribe("ros_tutorial_msg", 100, msgCallback);
    // 用于调用后台函数,等待接收消息。在接收到消息时执行后台函数。
    
    ros::spin();
    return 0;
}

 

然后保存退出

$ cd ~/catkin_ws     → 移动到catkin目录

$ catkin_make      → 执行catkin构建

运行发布者:

$ roscore

$ rosrun ros_tutorials_topic topic_publisher

运行订阅者:

$ rosrun ros_tutorials_topic topic_subscriber

下面,我们使用rostopic命令获取topic_publisher发布的话题吧。首先,我们来看一下ROS网络当前正在使用的话题列表。通过将list选项添加到rostopic命令来查看是否存在ros_tutorial_msg话题。

$ rostopic list

/ros_tutorial_msg

/rosout

/rosout_agg

接下来,让我们看看我们运行的发布者节点发布的消息。换句话说,是检查ros_tutorial_msg话题消息。您可以看到发布的消息

$ rostopic echo /ros_tutorial_msg

源码下载:

https://download.csdn.net/download/gs1069405343/11029120

 

 

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐