美文网首页
ROS2 创建自定义 ROS 2 msg 和 srv 文件

ROS2 创建自定义 ROS 2 msg 和 srv 文件

作者: 寽虎非虫003 | 来源:发表于2021-07-14 16:31 被阅读0次

    零、前情提要

    主要参考 官网:Creating custom ROS 2 msg and srv files

    前置文章ros2 foxy 学写简单的服务

    一、创建文件夹和包

    #dev_ws可以自己命名,但最好保留`_ws`的缩写标志。
    mkdir -p dev_ws/src 
    
    #进入源目录
    cd dev_ws/src 
    
    #创建包
    ros2 pkg create --build-type ament_cmake tutorial_interfaces
    

    tutorial_interfaces 是新包的名称。 注意它是一个 CMake 包; 目前没有办法在纯 Python 包中生成 .msg.srv 文件。 您可以在 CMake 包中创建自定义接口,然后在 Python 节点中使用。

    进入dev_ws/src/tutorial_interfaces并生成.msg.srv 各自独立的文件夹。

    cd tutorial_interfaces
    mkdir msg
    mkdir srv
    

    二、创建自定义文件

    msg文件夹中创建Num.msg文件,创建文件就不写了,并写入如下内容:

    int64 num
    

    srv文件夹中创建AddThreeInts.srv文件,并填入一下内容,分割线前是请求数据,分割线后是响应数据。

    int64 a
    int64 b
    int64 c
    ---
    int64 sum
    

    三、修改CMakeLists.txt

    修改CMakeLists.txt文件,里面添加如下行,注意文件路径名对应。

    find_package(rosidl_default_generators REQUIRED)
    
    rosidl_generate_interfaces(${PROJECT_NAME}
      "msg/Num.msg"
      "srv/AddThreeInts.srv"
     )
    

    四、修改package.xml

    在文件中添加如下行,前两行是添加依赖,后面一行作用暂不清楚。

    <build_depend>rosidl_default_generators</build_depend>
    
    <exec_depend>rosidl_default_runtime</exec_depend>
    
    <member_of_group>rosidl_interface_packages</member_of_group>
    

    五、创建包

    colcon build --packages-select tutorial_interfaces
    

    成功后就可以被其他包调用了。

    六、验证包

    开一个新终端,在dev_ws下激活

    . install/setup.bash
    

    查验文件,先查msg文件

    ros2 interface show tutorial_interfaces/msg/Num
    

    会显示

    int64 num
    

    同理,输入

    ros2 interface show tutorial_interfaces/srv/AddThreeInts
    

    会返回

    int64 a
    int64 b
    int64 c
    ---
    int64 sum
    

    七、测试

    7.1用发布订阅模型测试.msg文件

    dev_ws/src目录下面创建cpp_testmsg_pubsub

    ros2 pkg create --build-type ament_cmake cpp_testmsg_pubsub
    

    添加文件以及文件的意思之类的可以先复习下用colcon和c++写自己的第一个ROS2包
    cpp_testmsg_pubsub/src中添加publisher_member_function.cpp文件如下:

    #include <chrono>
    #include <memory>
    
    #include "rclcpp/rclcpp.hpp"
    #include "tutorial_interfaces/msg/num.hpp"     // CHANGE
    
    using namespace std::chrono_literals;
    
    class MinimalPublisher : public rclcpp::Node
    {
    public:
      MinimalPublisher()
      : Node("minimal_publisher"), count_(0)
      {
        publisher_ = this->create_publisher<tutorial_interfaces::msg::Num>("topic", 10);    // CHANGE
        timer_ = this->create_wall_timer(
          500ms, std::bind(&MinimalPublisher::timer_callback, this));
      }
    
    private:
      void timer_callback()
      {
        auto message = tutorial_interfaces::msg::Num();                               // CHANGE
        message.num = this->count_++;                                        // CHANGE
        RCLCPP_INFO(this->get_logger(), "Publishing: '%d'", message.num);    // CHANGE
        publisher_->publish(message);
      }
      rclcpp::TimerBase::SharedPtr timer_;
      rclcpp::Publisher<tutorial_interfaces::msg::Num>::SharedPtr publisher_;         // CHANGE
      size_t count_;
    };
    
    int main(int argc, char * argv[])
    {
      rclcpp::init(argc, argv);
      rclcpp::spin(std::make_shared<MinimalPublisher>());
      rclcpp::shutdown();
      return 0;
    }
    

    subscriber_member_function.cpp

    #include <memory>
    
    #include "rclcpp/rclcpp.hpp"
    #include "tutorial_interfaces/msg/num.hpp"     // CHANGE
    using std::placeholders::_1;
    
    class MinimalSubscriber : public rclcpp::Node
    {
    public:
      MinimalSubscriber()
      : Node("minimal_subscriber")
      {
        subscription_ = this->create_subscription<tutorial_interfaces::msg::Num>(          // CHANGE
          "topic", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1));
      }
    
    private:
      void topic_callback(const tutorial_interfaces::msg::Num::SharedPtr msg) const       // CHANGE
      {
        RCLCPP_INFO(this->get_logger(), "I heard: '%d'", msg->num);              // CHANGE
      }
      rclcpp::Subscription<tutorial_interfaces::msg::Num>::SharedPtr subscription_;       // CHANGE
    };
    
    int main(int argc, char * argv[])
    {
      rclcpp::init(argc, argv);
      rclcpp::spin(std::make_shared<MinimalSubscriber>());
      rclcpp::shutdown();
      return 0;
    }
    

    CMakeList.txt

    cmake_minimum_required(VERSION 3.5)
    project(cpp_testmsg_pubsub)
    
    # Default to C99
    if(NOT CMAKE_C_STANDARD)
      set(CMAKE_C_STANDARD 99)
    endif()
    
    # Default to C++14
    if(NOT CMAKE_CXX_STANDARD)
      set(CMAKE_CXX_STANDARD 14)
    endif()
    
    if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
      add_compile_options(-Wall -Wextra -Wpedantic)
    endif()
    
    # find dependencies
    find_package(ament_cmake REQUIRED)
    # uncomment the following section in order to fill in
    # further dependencies manually.
    # find_package(<dependency> REQUIRED)
    find_package(rclcpp REQUIRED)
    find_package(tutorial_interfaces REQUIRED)                         # CHANGE
    
    add_executable(talker src/publisher_member_function.cpp)
    ament_target_dependencies(talker rclcpp tutorial_interfaces)         # CHANGE
    
    add_executable(listener src/subscriber_member_function.cpp)
    ament_target_dependencies(listener rclcpp tutorial_interfaces)     # CHANGE
    
    install(TARGETS
      talker
      listener
      DESTINATION lib/${PROJECT_NAME})
    
    if(BUILD_TESTING)
      find_package(ament_lint_auto REQUIRED)
      # the following line skips the linter which checks for copyrights
      # uncomment the line when a copyright and license is not present in all source files
      #set(ament_cmake_copyright_FOUND TRUE)
      # the following line skips cpplint (only works in a git repo)
      # uncomment the line when this package is not in a git repo
      #set(ament_cmake_cpplint_FOUND TRUE)
      ament_lint_auto_find_test_dependencies()
    endif()
    
    ament_package()
    

    package.xml

    <?xml version="1.0"?>
    <?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
    <package format="3">
      <name>cpp_testmsg_pubsub</name>
      <version>0.0.0</version>
      <description>TODO: Package description</description>
      <maintainer email="default@default.com">default</maintainer>
      <license>TODO: License declaration</license>
    
      <buildtool_depend>ament_cmake</buildtool_depend>
      
      <depend>rclcpp</depend>
      <depend>tutorial_interfaces</depend>
    
      <test_depend>ament_lint_auto</test_depend>
      <test_depend>ament_lint_common</test_depend>
    
      <export>
        <build_type>ament_cmake</build_type>
      </export>
    </package>
    

    dev_ws目录下命令行构建

    colcon build --packages-select cpp_testmsg_pubsub
    

    打开两个terminal,并分别source和运行

    . install/setup.bash
    ros2 run cpp_testmsg_pubsub talker
    
    . install/setup.bash
    ros2 run cpp_testmsg_pubsub listener
    

    最后得到如下的图


    测试运行效果

    7.2用服务模型测试.srv文件

    直接参考上一节,以及ros2 foxy 学写简单的服务和官网# Creating custom ROS 2 msg and srv files第7.2节测试吧,我懒得写了,就留个截图。

    服务模型测试

    注意事项

    .msg文件和.srv文件温家明必须首字母大写,按驼峰原则命名,会被自动扩展成.hpp文件,扩展的文件的文件名会自动把大写转换成下划线和小写。

    相关文章

      网友评论

          本文标题:ROS2 创建自定义 ROS 2 msg 和 srv 文件

          本文链接:https://www.haomeiwen.com/subject/dvhspltx.html