ROS学习笔记9-创建ros消息和服务

2023-05-16

该节内容主要来自于官方文档的两个小节:
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
    

    还是挺复杂的。

转载于:https://www.cnblogs.com/spyplus/p/11544359.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐

  • 串口通信——写串口(C语言)

    C语言程序 xff0c 将一个文件中保存的控制LED的十六进制数读取 xff0c 并写入串口由433M发送至连接有另一433M的MSP430单片机 C语言程序 xff1a include lt stdio h gt include lt w
  • Keil 官网下载PACK包的地址

    转至 xff1a http www keil com dd2 Pack eula container 下载Pack包什么的有点用啊 xff0c 希望网址不要变了 截图如下 xff1a ARM公司的支持包下载地址 xff1a Common M
  • reStructuredText 表格快速生成

    reStructuredText 是个好东西 xff0c 但是如果要编写的表格里面包含中文实在是太蛋疼了 网上找了半天都没有找到一个合理的工具 xff0c 索性自己就写了个工具 xff0c 工具如下图 xff0c 简单的很 运行效果图如下
  • STM32CUBEMX使用PWM+DMA驱动WS2812

    STM32CUBEMX使用PWM 43 DMA驱动WS2812 首先在stm32cubemx中设置pwm和dma 我设置了TIM1的CH1为PWM引脚编写DMA响应函数 xff0c 即PWM DMA完成数据发送后的回调函数 PWM DMA
  • Arduino IDE配置STM32开发环境和程序烧录

    Arduino IDE配置STM32开发环境和烧录 前言 xff1a 最近在制作3D打印机 xff0c 自己画了一块STM32F446的3D打印机板子 xff08 RUMBA32 xff09 xff0c 但是在Arduino编译Marlin
  • Altium Designer 20(AD20)的PCB文件在嘉立创下单显示无外型文件解决方法

    Altium Designer 20 AD20 的PCB文件在嘉立创下单显示无外型文件解决方法 如上图 xff0c 在机械层1中生成外形 xff0c 勾选最后两个 如果不行 xff0c 修改宽度为10mil试一下
  • CH552 USB HID键盘

    客制化键盘制作V1 CH552工程 目前正在客制化一个小键盘 xff0c 计划8月中旬在咸鱼上售卖 xff0c 功能包括 xff1a 蓝牙有线双模 xff0c 蓝牙 5 0 xff08 nrf52810 xff09 xff0c 低功耗模式按
  • [pixhawk笔记]5-uORB消息传递

    本文主要内容翻译自官方文档 xff1a https dev px4 io en middleware uorb html 在前一篇笔记中使用uORB完成消息传递 xff0c 实现了一个简单示例程序 xff0c 本文将对uORB进行系统学习
  • 2019全国电赛总结

    准备阶段 xff1a 赛前大约一个星期就开始全力备战电赛 xff0c 由于学校条件不算太好 xff0c 所以选题上就不选放大器设计之类的题目 xff0c 只能选择一些电源题 xff0c 控制题 xff0c 造飞机题 技术准备 xff1a 这
  • UBUNTU使用RTL8811CU网卡(包含树莓派)

    8811cu 8821 github链接 一 普通的Ubuntu系统 xff0c 测试的是ubuntu18 04 下载驱动 从绿联中下载 xff1a 链接 下载解压后 xff0c chmod Linux文件夹 sudo chmod R 77
  • XTDrone ROS安装

    XTDrone ROS安装 本博客是参考XTDrone内容 xff0c 进行ROS安装和配置 参考连接 xff1a XTDrone 梗概ubuntu18的源 xff0c 并更新 参考 xff1a 更改ubunut源 sudo apt upd
  • PX4 GAZEBO无人机添加相机并进行图像识别

    PX4 GAZEBO无人机添加摄像头并进行图像识别 在之前完成了ROS的安装和PX4的安装 xff0c 并可以通过roslaunch启动软件仿真 接下来为无人及添加相机 xff0c 并将图像用python函数读取 xff0c 用于后续操作
  • XTDrone 视觉SLAM环境配置

    基于XTDrone的视觉SLAM章节 xff0c 进行环境配置 中途遇到了一些问题 xff0c 一一解决后成功完成了 xff0c 记录该流程 一 遇到的问题与参考链接 XTDrone相关参考连接 xff1a 链接依赖安装教程 xff1a O
  • XTDrone 视觉惯性里程计(VIO)配置

    XTDrone 视觉惯性里程计 xff08 VIO xff09 配置 参考XTDron进行配置 xff0c 对于依赖的配置写成文档 xff0c 参考主要为 xff1a XTDrone Ceres Solver 2 0 0 1 下载2 0 0
  • ros realsense D435i摄像头配置

    ros realsense D435i摄像头配置 之前在ubunut18中配置了ROS环境 xff0c 现在需要在此基础上 xff0c 配置D435i相机的SDK和ROS包 一 参考 https github com IntelRealSe
  • 树莓派4B(ubuntu mate系统)使用d435i运行vins

    树莓派4B xff08 ubuntu mate系统 xff09 使用d435i运行vins 提示本文为随手笔记 xff0c 并不严谨 xff0c 可参考 xff1a 博客和博客进行配置 树莓派 ubuntu mate 20系统安装ros的步
  • 树莓派3B+增加虚拟内存

    普通ubuntu系统增加虚拟内存参考 xff1a https blog csdn net weixin 42405819 article details 117886557 编译opencv时 xff0c 卡在了91 不动 xff0c 按照
  • ROS主机从机设置

    ROS主机从机设置 在ROS基础上 xff0c 配置主机和从机 xff0c 实现主机和从机的话题联通 配置hosts 在主机和从机的 etc hosts文件中 xff0c 配置如下内容 xff08 也许主机只需要写入 master xff1
  • VINS、MAVROS等的坐标系统一(草稿,未得出明确结果)

    由于不同算法之间的坐标系不同 xff0c 导致计算的结果混乱 xff0c 该博客的目的是记录和统一不同算法之间的坐标系 xff0c 保证坐标系的统一 一 VINS算法 vins算法 xff0c 使用D435I相机 该坐标方向为 xff1a
  • ROS学习笔记9-创建ros消息和服务

    该节内容主要来自于官方文档的两个小节 xff1a 1 使用rosed来编辑 2 创建ros消息的服务 先来看rosed xff1a rosed rosed命令是rosbash的一部分 xff0c 使用rosed可以直接编辑包中的一个文件 x