ROS-自定义msg类型以及使用-笔记

转载请标明出处:https://blog.csdn.net/u013271656/article/details/108778557

本文代码下载:https://download.csdn.net/download/u013271656/12883878

目录


本文代码结构如下所示:

为了便于理解,代码整体结构:

Test_ROS/src 结构-树状图:


 

1. 创建ROS工作空间

我们开始创建一个 catkin 工作空间

$ mkdir -p ~/TEST_ROS/src
$ cd ~/TEST_ROS/
$ catkin_make

catkin_make 命令在 catkin 工作空间 中是一个非常方便的工具。第一次在你的工作空间中运行它时,它会在你的 'src' 文件夹里创建一个 CMakeLists.txt 的链接。

接下来首先 source 一下新生成的 setup.*sh 文件:

$ source devel/setup.bash

要想保证工作空间已配置正确,需确保ROS_PACKAGE_PATH环境变量包含你的工作空间目录,采用以下命令查看:

OptiPlex-7060:~/my_work/ros/Test_ROS$ echo $ROS_PACKAGE_PATH 
/home/yuanwang/my_work/ros/Test_ROS/src:/opt/ros/kinetic/share

 

2. 创建msg消息

1. 创建一个空的package单独存放msg类型,这里建立一个名为test_msgs的包,用于创建自定义msg类型。

2. 接下来新建一个msg文件Test.msg。

$ cd Test_ROS/src
$ catkin_create_pkg test_msgs
$ touch Test.msg

Test.msg 定义类型如下所示: 

Header header
float32 id
float32[] data
string name
uint32 age
bool sex
geometry_msgs/Point pose

 

3. 修改package.xml && 修改CMakeLists.txt

上一节中通过命令 catkin_create_pkg 创建 test_msgs文件夹,test_msgs文件中会自动生成package.xml、CMakeLists.txt两个文件,现在让我们修改它。

3.1 package.xml

需要message_generation生成C++或Python能使用的代码,需要message_runtime提供运行时的支持,所以package.xml中添加以下两句:

<build_depend>message_generation</build_depend>
<run_depend>message_runtime</run_depend>

<!-- 新版本中 <run_depend>message_runtime</run_depend> -->
<!-- 替换为  <exec_depend>message_runtime</exec_depend> -->

完整的文件内容如下所示(package.xml

<?xml version="1.0"?>
<package format="2">
  <name>test_msgs</name>
  <version>0.0.0</version>
  <description>The test_msgs package</description>

  <!-- One maintainer tag required, multiple allowed, one person per tag -->
  <!-- Example:  -->
  <!-- <maintainer email="[email protected]">Jane Doe</maintainer> -->
  <maintainer email="[email protected]">yuanwang</maintainer>


  <license>TODO</license>
  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>message_generation</build_depend>
  <exec_depend>message_runtime</exec_depend>


  <!-- The export tag contains other, unspecified, tags -->
  <export>
    <!-- Other tools can request additional information be placed here -->

  </export>
</package>

3.2 CMakeLists.txt

CMakeLists.txt需要使用find_package命令查找依赖的包,通过add_message_files命令指定msg文件,通过generate_messages命令指定生成消息文件时的依赖项,通过catkin_package设置运行依赖。

完整的文件内容如下所示(CMakeLists.txt

cmake_minimum_required(VERSION 2.8.3)
project(test_msgs)

## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)

## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS roscpp rospy message_generation std_msgs geometry_msgs)

add_message_files(
  FILES
  Test.msg
  # Message2.msg
)

#generate_messages必须在catkin_package前面
generate_messages(
 DEPENDENCIES
 geometry_msgs
)

catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES test_msgs
#  CATKIN_DEPENDS other_catkin_pkg
#  DEPENDS system_lib
CATKIN_DEPENDS message_runtime
)



## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include
# ${catkin_INCLUDE_DIRS}
)

 

4. 编写talker.cc 、listener.cc 调用msg

4.1 编译msg.h

上一节[3]中配置好msg-xml-cmake文件,返回根目录编译 Test.msg 生成 Test.h。

$ cd Test_ROS
$ catkin_make

接下来可通过 rosmsg show test_msgs/Test  查看定义好的msg。

4.2 编写 talker.cc 、listener.cc

创建 Test_ROS/src/Test_src 文件夹,并创建src子目录存放 .cc文件

$ cd Test_ROS/src
$ catkin_create_pkg Test
$ mkdir src

在 Test_ROS/src/Test_src/src 中创建 talker.cc 、listener.cc。

4.2.1 完整的文件内容如下所示( talker.cc

#include <ros/ros.h>
#include <test_msgs/Test.h>

int main(int argc, char **argv)
{
  ros::init(argc, argv, "msg_talker");
  ros::NodeHandle n;

  // odeHandle::advertise() 返回一个 ros::Publisher 对象,它有两个作用:
  //    1. 它有一个 publish() 成员函数可以让你在topic上发布消息
  //    2. 如果消息类型不对,它会拒绝发布, 
  //    ps: 此处,缓冲区中的消息在大于 1000 个的时候就会开始丢弃先前发布的消息。
  ros::Publisher msg_pub = n.advertise<test_msgs::Test>("test_msg", 1000);


  // ros::Rate 对象可以允许你指定自循环的频率
  // 此处为10hz
  ros::Rate loop_rate(10);
  int count = 0;

  // roscpp 会默认生成一个 SIGINT 句柄,它负责处理 Ctrl-C 键盘操作——使得 ros::ok() 返回 false
  // new msg
  test_msgs::Test msg_temp;
  while (ros::ok())
  {
    // **************************************
    // msg 初始化值
    if (count == 0){
        std::cout << "Various types of initialization values: \n";

        std::cout << "msg.header(header): " << msg_temp.header.stamp.toSec() << std::endl;
        std::cout << "msg.id(float32): " << msg_temp.id << std::endl;
        std::cout << "msg.data(float32[]).size: " << msg_temp.data.size() << std::endl;
        std::cout << "msg.name(string): " << msg_temp.name << std::endl;
        std::cout << "msg.age(uint32): " << msg_temp.age << std::endl;
        std::cout << "msg.sex(bool): " << msg_temp.sex << std::endl;
        std::cout << "msg.pose(geometry_msgs/Pose): " << msg_temp.pose.x << "," << 
            msg_temp.pose.y << "," << msg_temp.pose.z << std::endl << std::endl;
        
        ++count;
    }
    
    
    // **************************************
    // ros-msg [] 用法与 c++ std::vector 相同
    float array[3] = {1.1, 1.2, 1.3};
    std::vector<float> array1(array,array+3);
    msg_temp.data = array1;
    std::cout << "msg.data.size: " << msg_temp.data.size() << std::endl << "msg.data : ";
    for(std::vector<float>::iterator it = msg_temp.data.begin(); it != msg_temp.data.end(); ++it)
    {
      std::cout << *it << " ";
    }
    std::cout << std::endl << std::endl;


    // push_back
    msg_temp.data.push_back(100.0);
    std::cout << "msg.data.size: " << msg_temp.data.size() << std::endl << "msg.data : ";
    for(std::vector<float>::iterator it = msg_temp.data.begin(); it != msg_temp.data.end(); ++it)
    {
      std::cout << *it << " ";
    }
    std::cout << std::endl;
    std::cout << " ----------------------- " << std::endl;


    // **************************************
    // 这里,我们向所有订阅 chatter 话题的节点发送消息
    msg_pub.publish(msg_temp);

    // 在这个例子中并不是一定要调用 ros::spinOnce(),因为我们不接受回调。
    // 然而,如果你的程序里包含其他回调函数,最好在这里加上 ros::spinOnce()这一语句,
    // 否则你的回调函数就永远也不会被调用了
    ros::spinOnce();

    // 这条语句是调用 ros::Rate 对象来休眠一段时间以使得发布频率为 10Hz
    loop_rate.sleep();
  }

  std::cout << "---- end ----" << std::endl;
  std::cout << "msg.data.size: " << msg_temp.data.size() << std::endl;

  return 0;
}

4.2.2 完整的文件内容如下所示( listener.cc )

#include <ros/ros.h>
#include <test_msgs/Test.h>

void msgCallback(const test_msgs::Test::ConstPtr &msg)
{
  // 接收msg, print
  std::cout << "msg.data.size: " << msg->data.size() << std::endl << "msg.data : ";
  std::cout << "msg->data[0]=" << msg->data[0] << std::endl;
}

int main(int argc,char ** argv)
{
  ros::init(argc,argv,"test1");
  ros::NodeHandle n;

  ros::Subscriber msg_sub = n.subscribe("test_msg", 100, msgCallback);

  ros::spin();
  return 0;
}

 

5. 编译并运行

(1) 编译 && 启动 ros 初始结点:

$ catkin_make
$ roscore

(2) 重新打开一个终端,打开终端后别忘 source devel/setup.bash 

$ rosrun Test_src talker

(3)完成第二步后,talker节点开始运行,talker.cc 中注释的很清楚,结果如下:

参考:

http://wiki.ros.org/cn/ROS/Tutorials/InstallingandConfiguringROSEnvironment

http://wiki.ros.org/cn/ROS/Tutorials/WritingPublisherSubscriber%28python%29

 

猜你喜欢

转载自blog.csdn.net/u013271656/article/details/108778557
今日推荐