该节内容主要来自于官方文档的两个小节:
1.使用rosed来编辑
2.创建ros消息的服务

先来看rosed:

  1. rosed
    rosed命令是rosbash的一部分,使用rosed可以直接编辑包中的一个文件,而无需键入文件所在的全路径,用法如下:

    $ rosed [package_name] [filename]
    

    例如我们想编辑roscpp包下的Logger.msg,则输入如下命令:

    $ rosed roscpp Logger.msg
    

    则会使用vim打开Logger.msg进入编辑状态。
    同时,rosed支持使用tab键实现自动完成功能,用法如下:

    $ rosed [package_name] <tab><tab>
    

    例如:

    $ rosed roscpp <tab><tab>
    

    注意:两个tab和包名之间有空格。
    会列出roscpp包中的所有的文件:

    Empty.srv                   roscpp.cmake
    genmsg_cpp.py roscppConfig.cmake
    gensrv_cpp.py roscppConfig-version.cmake
    GetLoggers.srv roscpp-msg-extras.cmake
    Logger.msg roscpp-msg-paths.cmake
    msg_gen.py SetLoggerLevel.srv
    package.xml

    并且,rosed还可以指定编辑器,默认的采用vim编辑器,可以通过设置~/.bashrc文件中的环境变量来指定编辑器:
    例如输入如下命令将编辑器设置为nano编辑器。

    export EDITOR='nano -w'
    

    也可以使用如下命令设置为gedit:

    export EDITOR='gedit -w'
    
  2. msg和srv文件介绍
    • msg:msg文件是ros中描述msg消息成员的文本文件,他可以生成不同语言中的消息代码。
    • srv:srv文件是ros中描述服务类型成员的文本文件,他包含请求和响应两部分。

    msg文件每行包含一个类型和一个变量名:
    其中,变量类型可以为如下类型:

    • int8, int16, int32, int64 (以及uint)
    • float32, float64
    • string
    • time, duration
    • 其他消息类型
    • 变长度以及定长度的数组[]

    此外还有一个特殊类型,头类型(Header),Header类型包含一个时间戳和坐标轴信息,这些信息在ROS中很常用。一个典型的ros消息定义如下:

     Header header
    string child_frame_id
    geometry_msgs/PoseWithCovariance pose
    geometry_msgs/TwistWithCovariance twist

    srv文件定义与msg类似,也是由不同行组成,每行包含一个变量类型和一个变量名,不过srv包含请求(request)和响应(response)两个部分,该两部分用一行三短杠---分隔开。例如:

    int64 A
    int64 B
    ---
    int64 Sum

    在上面的例子中:A和B是请求,Sum是响应。

  3. 使用msg
    1. 创建msg
      比如使用如下命令可以在之前的示例包里创建一个新msg:

      $ roscd beginner_tutorials
      $ mkdir msg
      $ echo "int64 num" > msg/Num.msg

      该msg只有一行,当然也可以创建一个更复杂的msg

      string first_name
      string last_name
      uint8 age
      uint32 score

      然后,为了确保该msg文件能被转化为其他语言的代码,需要检查package.xml中如下两行存在且未被注释掉:(查看之后发现默认是注释掉的)

      <build_depend>message_generation</build_depend>
      <exec_depend>message_runtime</exec_depend>

      在编译期间,我们需要启用message_generation,在运行期间,我们需要启用message_runtime。
      然后使用你最喜爱的编辑器打开CMakeLists.txt(可以使用rosed)
      然后在find_package中添加message_generation的条目:

      ## 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
      std_msgs
      message_generation
      )

      同时,确保在运行时依赖中也添加了该消息的依赖:

      catkin_package(
      # INCLUDE_DIRS include
      # LIBRARIES begginner_tutorials
      # CATKIN_DEPENDS roscpp rospy std_msgs
      # DEPENDS system_lib
      CATKIN_DEPENS message_runtime
      )

      找到添加消息文件的代码段:

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

      取消注释并添加该消息文件名:

      add_message_files(
      FILES
      Num.msg
      )

      确保generate_message被调用:

      generate_messages(
      DEPENDENCIES
      std_msgs
      )
    2. 查看msg的信息
      定义信息之后,可以用rosmsg命令来查看消息的信息:
      $ rosmsg show [message type]
      

      例如,对于上述定义的信息,用如下命令:

      $ rosmsg show beginner_tutorials/Num
      

      可以看到返回为:

      int64 num
      

      也可以不写全路径,如果你不记得该消息在哪个包下面,可以这样写:

      $ rosmsg show Num
      

      返回为:

      [beginner_tutorials/Num]:
      int64 num
  4. 使用srv
    1.  创建srv
      类似于msg,我们先创建一个srv的文件夹:

      $ roscd beginner_tutorials
      $ mkdir srv

      可以在其中手动写一个srv文件,也可以将其他地方的srv文件复制过来,在此处介绍一个ros下面复制文件的命令,roscp,该命令用法如下:

      $ roscp [package_name] [file_to_copy_path] [copy_path]
      

      然后我们将rospy_tutorials包中的srv文件复制过来:

      $ roscp rospy_tutorials AddTwoInts.srv srv/AddTwoInts.srv
      

      同时在package.xml中启用message_generation和message_runtime(该步与msg相同)。

      然后在find_package的调用中增加message_generation(与msg中相同)。
      不同的是在add_service_files的调用中要添加与服务对应的条目。

      add_service_files(
      FILES
      AddTwoInts.srv
      )
    2. 查看srv的信息
      与rosmsg类似,ros也提供了rossrv来查看srv服务相关的信息:
      例如:
      $ rossrv show beginner_tutorials/AddTwoInts
      

      返回:

      int64 a
      int64 b
      ---
      int64 sum

      也可以不加路径:

      $ rossrv show AddTwoInts
      [beginner_tutorials/AddTwoInts]:
      int64 a
      int64 b
      ---
      int64 sum [rospy_tutorials/AddTwoInts]:
      int64 a
      int64 b
      ---
      int64 sum
  5. 通用步骤(个人感觉应该该节改名为编译步骤)
    如果进行完了如上步骤,然后就可以编译这些msg和srv,取消CMakeLists.txt中以下几行的注释:
    generate_messages(
    DEPENDENCIES
    std_msgs
    )

    然后运行catkin_make进行编译:

    # In your catkin workspace
    $ roscd beginner_tutorials
    $ cd ../..
    $ catkin_make install
    $ cd -

    则会将msg和srv文件编译成其他语言的代码。例如,对于msg,C++的头文件会包含在~/catkin_ws/devel/include/beginner_tutorials/中;
    python的源文件会包含在~/catkin_ws/devel/lib/python2.7/dist-packages/beginner_tutorials/msg中;
    ~/catkin_ws/devel/share/common-lisp/ros/beginner_tutorials/msg/中。
    srv文件对于C++会和msg文件生成的源文件在统一文件夹中,而python和lisp的srv文件生成的文件会在单独的srv文件夹中,该文件夹与msg文件夹在同一个目录下。
    看一个C++的msg头文件:

    // Generated by gencpp from file begginner_tutorials/Num.msg
    // DO NOT EDIT! #ifndef BEGGINNER_TUTORIALS_MESSAGE_NUM_H
    #define BEGGINNER_TUTORIALS_MESSAGE_NUM_H #include <string>
    #include <vector>
    #include <map> #include <ros/types.h>
    #include <ros/serialization.h>
    #include <ros/builtin_message_traits.h>
    #include <ros/message_operations.h> namespace begginner_tutorials
    {
    template <class ContainerAllocator>
    struct Num_
    {
    typedef Num_<ContainerAllocator> Type; Num_()
    : num(0) {
    }
    Num_(const ContainerAllocator& _alloc)
    : num(0) {
    (void)_alloc;
    } typedef int64_t _num_type;
    _num_type num; typedef boost::shared_ptr< ::begginner_tutorials::Num_<ContainerAllocator> > Ptr;
    typedef boost::shared_ptr< ::begginner_tutorials::Num_<ContainerAllocator> const> ConstPtr; }; // struct Num_ typedef ::begginner_tutorials::Num_<std::allocator<void> > Num; typedef boost::shared_ptr< ::begginner_tutorials::Num > NumPtr;
    typedef boost::shared_ptr< ::begginner_tutorials::Num const> NumConstPtr; // constants requiring out of line definition template<typename ContainerAllocator>
    std::ostream& operator<<(std::ostream& s, const ::begginner_tutorials::Num_<ContainerAllocator> & v)
    {
    ros::message_operations::Printer< ::begginner_tutorials::Num_<ContainerAllocator> >::stream(s, "", v);
    return s;
    } } // namespace begginner_tutorials namespace ros
    {
    namespace message_traits
    { // BOOLTRAITS {'IsFixedSize': True, 'IsMessage': True, 'HasHeader': False}
    // {'std_msgs': ['/opt/ros/kinetic/share/std_msgs/cmake/../msg'], 'begginner_tutorials': ['/home/shao/catkin_ws/src/begginner_tutorials/msg']} // !!!!!!!!!!! ['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_parsed_fields', 'constants', 'fields', 'full_name', 'has_header', 'header_present', 'names', 'package', 'parsed_fields', 'short_name', 'text', 'types'] template <class ContainerAllocator>
    struct IsFixedSize< ::begginner_tutorials::Num_<ContainerAllocator> >
    : TrueType
    { }; template <class ContainerAllocator>
    struct IsFixedSize< ::begginner_tutorials::Num_<ContainerAllocator> const>
    : TrueType
    { }; template <class ContainerAllocator>
    struct IsMessage< ::begginner_tutorials::Num_<ContainerAllocator> >
    : TrueType
    { }; template <class ContainerAllocator>
    struct IsMessage< ::begginner_tutorials::Num_<ContainerAllocator> const>
    : TrueType
    { }; template <class ContainerAllocator>
    struct HasHeader< ::begginner_tutorials::Num_<ContainerAllocator> >
    : FalseType
    { }; template <class ContainerAllocator>
    struct HasHeader< ::begginner_tutorials::Num_<ContainerAllocator> const>
    : FalseType
    { }; template<class ContainerAllocator>
    struct MD5Sum< ::begginner_tutorials::Num_<ContainerAllocator> >
    {
    static const char* value()
    {
    return "57d3c40ec3ac3754af76a83e6e73127a";
    } static const char* value(const ::begginner_tutorials::Num_<ContainerAllocator>&) { return value(); }
    static const uint64_t static_value1 = 0x57d3c40ec3ac3754ULL;
    static const uint64_t static_value2 = 0xaf76a83e6e73127aULL;
    }; template<class ContainerAllocator>
    struct DataType< ::begginner_tutorials::Num_<ContainerAllocator> >
    {
    static const char* value()
    {
    return "begginner_tutorials/Num";
    } static const char* value(const ::begginner_tutorials::Num_<ContainerAllocator>&) { return value(); }
    }; template<class ContainerAllocator>
    struct Definition< ::begginner_tutorials::Num_<ContainerAllocator> >
    {
    static const char* value()
    {
    return "int64 num\n\
    ";
    } static const char* value(const ::begginner_tutorials::Num_<ContainerAllocator>&) { return value(); }
    }; } // namespace message_traits
    } // namespace ros namespace ros
    {
    namespace serialization
    { template<class ContainerAllocator> struct Serializer< ::begginner_tutorials::Num_<ContainerAllocator> >
    {
    template<typename Stream, typename T> inline static void allInOne(Stream& stream, T m)
    {
    stream.next(m.num);
    } ROS_DECLARE_ALLINONE_SERIALIZER
    }; // struct Num_ } // namespace serialization
    } // namespace ros namespace ros
    {
    namespace message_operations
    { template<class ContainerAllocator>
    struct Printer< ::begginner_tutorials::Num_<ContainerAllocator> >
    {
    template<typename Stream> static void stream(Stream& s, const std::string& indent, const ::begginner_tutorials::Num_<ContainerAllocator>& v)
    {
    s << indent << "num: ";
    Printer<int64_t>::stream(s, indent + " ", v.num);
    }
    }; } // namespace message_operations
    } // namespace ros #endif // BEGGINNER_TUTORIALS_MESSAGE_NUM_H

    还是挺复杂的。

ROS学习笔记9-创建ros消息和服务的更多相关文章

  1. ROS学习手记 - 7 创建ROS msg & srv

    至此,我们初步学习了ROS的基本工具,接下来一步步理解ROS的各个工作部件的创建和工作原理. 本文的详细文档:http://wenku.baidu.com/view/623f41b3376baf1ff ...

  2. ROS学习笔记二:ROS系统架构及概念

    本文主要是了解ROS的系统架构.文件夹结构以及工作所需的核心文件. ROS系统架构主要被设计和划分为三部分,每一部分代表一个层级的概念:文件系统级(The filesystem level).计算图级 ...

  3. ROS学习笔记一(ROS的catkin工作空间)

    在安装完成ROS indigo之后,需要查看环境变量是否设置正确,并通过创建一个简单的实例来验证ROS能否正常运行. 1 查看环境变量 在ROS的安装过程中,我们执行了如下命令:(此命令就是向当前用户 ...

  4. ROS学习笔记一:ROS安装与测试

    1 Ubuntu和ROS版本的对应关系 Ubuntu 和 ROS 都存在不同的版本,其对应关系如下: 注:如果Ubuntu版本和ROS版本不对应的话,安装就不会成功了- 笔者安装的是Ubuntu14. ...

  5. ROS学习笔记九:ROS工具

    ROS有各种工具可以帮助用户使用ROS.应该指出,这些GUI工具是对输入型命令工具的补充.如果包括ROS用户个人发布的工具,那么ROS工具的数量很庞大.其中,本文讨论的工具是对于ROS编程非常有用的辅 ...

  6. [转]ROS学习笔记十一:ROS中数据的记录与重放

    本节主要介绍如何记录一个正在运行的ROS系统中的数据,然后在一个运行的系统中根据记录文件重新产生和记录时类似的运动情况.本例子还是以小海龟例程为例. 记录数据(创建一个bag文件) 首先运行小海龟例程 ...

  7. ROS学习笔记七:在ROS中使用USB摄像头

    下面是一些USB摄像头的驱动(大多数摄像头都支持uvc标准): 1 使用软件库里的uvc-camera功能包 1.1 检查摄像头 lsusb ----------------------------- ...

  8. ROS学习手记 - 8 编写ROS的Publisher and Subscriber

    上一节我们完成了 message & srv 文件的创建和加入编译,这次我们要玩简单的Publisher 和 Subscriber 要玩 Publisher 和 Subscriber, 需要具 ...

  9. Java学习笔记-多线程-创建线程的方式

    创建线程 创建线程的方式: 继承java.lang.Thread 实现java.lang.Runnable接口 所有的线程对象都是Thead及其子类的实例 每个线程完成一定的任务,其实就是一段顺序执行 ...

随机推荐

  1. Centos610安装MVN

    1.下载mav安装 下载免安装版上传linux cd /opt/maven mkdir repository cd apche-maven-3.3.9/conf vi settings.xml  设置 ...

  2. oracle查询表统计行数与注释

    SELECT TABLE_NAME,NUM_ROWS,(select COMMENTS from user_tab_comments WHERE TABLE_NAME=C.TABLE_NAME) FR ...

  3. C/C++程序从文本文件中读取(保存)数据

    :本文仅供初学者参阅,解惑 在C程序中: 与程序代码外的数据(文件)打交道,我们使用到流(stream)这个概念,实现进程的虚拟内存与文件之间的数据交换. ——文件流:C标准库提供了FILE(之所以命 ...

  4. cmd添加管理员账号

    net user 用户名 密码 /add net localgroup Administrators 用户名 /add

  5. laravel 动态属性

    我们在 User 模型里定义了关联方法 followings() 关联关系定义好后,我们就可以通过访问 followings 属性直接获取到关注用户的 集合.这是 Laravel Eloquent 提 ...

  6. 二叉树性质 n0=n2+1

    假设树的节点个数为n,那么n=n0+n1+n2,并且边的个数等于n-1,那么 n-1=n22+n1 则 n0+n1+n2-1=n22+n1,即n0=n2+1.

  7. 【渗透测试】Squirrelmail远程代码执行漏洞+修复方案

    最近网上有点不太平,爆出各种漏洞,等下会把近期的漏洞复现一下,发出来.安全圈的前辈总是默默的奉献,在这里晚辈们只能站在巨人的肩膀上,跟紧前辈们的步伐,走下去. -------------------- ...

  8. Jmeter在windows系统下的安装

    一.工具描述 apache jmeter是100%的java桌面应用程序,它被设计用来加载被测试软件功能特性.度量被测试软件的性能.设计jmeter的初衷是测试web应用, 后来又扩充了其它的功能.j ...

  9. Spring Boot 2.x 入门前的准备-IntelliJ IDEA 开发工具的安装与使用

    常用的用于开发 spring boot 项目的开发工具有 eclipse 和 IntelliJ IDEA 两种,最近有声音提出 visual code 也开始流行开发 java,而且确实如此, vs ...

  10. vPC配置

    1.vPC概述 如下图所示,在传统网络中,出于冗余考虑,汇聚层往往由2台设备构成,一台接入层交换机使用2根上联链路,分别连接汇聚层2台设备. 这种拓扑所带来的问题是:受制于STP,对于同一个VLAN的 ...