【ROS2】 核心概念6——通信接口语法(Interfaces)+ 信息发布实战

 古月21讲/2.6_通信接口

官方文档:Interfaces — ROS 2 Documentation: Humble documentation

官方接口代码实战:https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Single-Package-Define-And-Use-Interface.html

 ROS 2使用简化的描述语言,即接口定义语言( interface definition language,IDL)来描述这些接口。此描述使ROS工具可以轻松地以几种目标语言为接口类型生成源代码 (自动跨语言)。。不同通信接口,接口文件后缀不同

话题(.msg),

服务(.srv),

动作(.action)

接口语言定义语法

所有的语言,都有统一的内置类型(built-in-type)表示

可单独定义类型名称,例如“ geometry_msgs/posestamped”

内部固有类型 (与跨语言对应关系)

Type name

C++

Python

DDS type

bool

bool

builtins.bool

boolean

byte

uint8_t

builtins.bytes*

octet

char

char

builtins.int*

char

float32

float

builtins.float*

float

float64

double

builtins.float*

double

int8

int8_t

builtins.int*

octet

uint8

uint8_t

builtins.int*

octet

int16

int16_t

builtins.int*

short

uint16

uint16_t

builtins.int*

unsigned short

int32

int32_t

builtins.int*

long

uint32

uint32_t

builtins.int*

unsigned long

int64

int64_t

builtins.int*

long long

uint64

uint64_t

builtins.int*

unsigned long long

string

std::string

builtins.str

string

wstring

std::u16string

builtins.str

wstring

话题(topics  发布/订阅信息模型)

消息是ROS 2节点将网络上的数据发送到其他ROS节点的一种方式,而没有响应(单向信息传递)。例如,如果一个ROS 2节点从传感器读取温度数据,则可以使用温度消息在ROS 2网络上发布该数据。 ROS 2网络上的其他节点可以订阅该数据并接收温度消息。

每个字段由一个类型名称组成,被空格隔开,即

fieldtype1 fieldname1
fieldtype2 fieldname2

例如

int32 my_int
string my_string
带有默认值的示例
uint8 x 42
int16 y -2000
string full_name "John Doe"
int32[] samples [-200, -100, 0, 100, 200]

 常数示例,无法更改(有=号)

int32 X=123
int32 Y=-123
string FOO="foo"
string EXAMPLE='bar'

服务接口

在ROS软件包的 srv/ 路径中,在.srv文件中描述和定义了服务。

服务描述文件由请求和响应MSG类型组成,该类型由使用 --- 区分

语法

string str
---
string str

示例

# request constants
int8 FOO=1
int8 BAR=2
# request fields
int8 foobar
another_pkg/AnotherMessage msg
---
# response constants
uint32 SECRET=123456
# response fields
another_pkg/YetAnotherMessage val
CustomMessageDefinedInThisPackage value
uint32 an_integer

动作通信接口 

有三个参数需要定义

使用2个 ---  --- 区分

<request_type> <request_fieldname>
---
<response_type> <response_fieldname>
---
<feedback_type> <feedback_fieldname>

示例

int32 order
---
int32[] sequence
---
int32[] sequence

二、创建接口代码

Creating custom msg and srv files — ROS 2 Documentation: Humble documentation

创建工程空间

mkdir -p learn_ws/src  
cd learn_ws/src 

创建名字为tutorial_inferfaces软件包

ros2 pkg create --build-type ament_cmake  tutorial_interfaces

创建接口 

接口文件,要求单独放在 msg srv的文件夹

mkdir msg srv

ws_zxy/src/tutorial_interfaces/msg/Num.msg

int64 num

cmake

ws_zxy/src/tutorial_interfaces/CMakeLists.txt

cmake_minimum_required(VERSION 3.8)
project(tutorial_interfaces)


find_package(geometry_msgs REQUIRED)              # geometry_msgs 是 ROS 的标准几何消息包,提供如 Point、Pose 等预定义消息类型
find_package(rosidl_default_generators REQUIRED)  # rosidl_default_generators 包提供了从 .msg、.srv 等文件生成 C++/Python 代码的功能
find_package(tutorial_interfaces REQUIRED)                      # CHANGE


rosidl_generate_interfaces(${PROJECT_NAME}
  "msg/Num.msg"
  #"msg/Sphere.msg"
  #"srv/AddThreeInts.srv"
  #DEPENDENCIES geometry_msgs   #声明自定义接口依赖的外部包(例如 Sphere.msg 可能引用了 geometry_msgs/Point 类型)
)


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)

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # the following line skips the linter which checks for copyrights
  # comment the line when a copyright and license is added to all source files
  set(ament_cmake_copyright_FOUND TRUE)
  # the following line skips cpplint (only works in a git repo)
  # comment the line when this package is in a git repo and when
  # a copyright and license is added to all source files
  set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()

ament_package()

package

ws_zxy/src/tutorial_interfaces/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>tutorial_interfaces</name>
  <version>0.0.0</version>
  <description>TODO: Package description</description>
  <maintainer email="452366037@qq.com">zengxy</maintainer>
  <license>TODO: License declaration</license>

  <buildtool_depend>ament_cmake</buildtool_depend>

  <test_depend>ament_lint_auto</test_depend>
  <test_depend>ament_lint_common</test_depend>

  <export>
    <build_type>ament_cmake</build_type>
  </export>


  <depend>geometry_msgs</depend> 
  <buildtool_depend>rosidl_default_generators</buildtool_depend>
  <exec_depend>rosidl_default_runtime</exec_depend>
  <member_of_group>rosidl_interface_packages</member_of_group>
</package>

编译

colcon build --packages-select tutorial_interfaces

三、创建Cpp业务代码,调用编译后接口

Creating custom msg and srv files — ROS 2 Documentation: Humble documentation

创建功能包

ros2 pkg create --build-type ament_cmake  cpp_pubsub

发布者代码 

ws_zxy/src/cpp_pubsub/src/msg_publish.cpp

#include <chrono>      //用于处理时间相关操作(如 500ms 定时器周期) 
#include <memory>

#include "rclcpp/rclcpp.hpp"
#include "tutorial_interfaces/msg/num.hpp"                                            // CHANGE

using namespace std::chrono_literals;

class MinimalPublisher : public rclcpp::Node    // 继承 rclcpp::Node 是 ROS 2 节点的标准实现方式
{
public:
// 构造函数的参数列表,以冒号 : 开头.后跟以逗号分隔的成员变量初始值对
  MinimalPublisher()
  : Node("minimal_publisher"), count_(0)
  {
    //msg 消息类型使用驼峰命名 
    publisher_ = this->create_publisher<tutorial_interfaces::msg::Num>("topic", 10);   // msg  create_publisher
    timer_ = this->create_wall_timer(
      500ms, std::bind(&MinimalPublisher::timer_callback, this));
  }

private:
  void timer_callback()
  { 
    //消息对象应使用栈分配(auto message)避免动态内存开销
    auto message = tutorial_interfaces::msg::Num();                                  
    message.num = this->count_++;                                                     
    RCLCPP_INFO_STREAM(this->get_logger(), "Publishing: '" << message.num << "'");       // msg
    publisher_->publish(message);
  }
  rclcpp::TimerBase::SharedPtr timer_;
  rclcpp::Publisher<tutorial_interfaces::msg::Num>::SharedPtr publisher_;            
  size_t count_;
};

int main(int argc, char * argv[])
{
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<MinimalPublisher>());  // spin 进入事件循环,保持节点活跃
  rclcpp::shutdown();
  return 0;
}

订阅者代码

ws_zxy/src/cpp_pubsub/src/msg_sub.cpp

#include <functional>
#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 & msg) const  // CHANGE
  {
    RCLCPP_INFO_STREAM(this->get_logger(), "I heard: '" << msg.num << "'");     // CHANGE
  }
  rclcpp::Subscription<tutorial_interfaces::msg::Num>::SharedPtr subscription_;  // CHANGE
};

int main(int argc, char * argv[])
{
  // 初始化ROS2节点
  rclcpp::init(argc, argv);
  // 运行节点,直到节点被关闭
  rclcpp::spin(std::make_shared<MinimalSubscriber>());
  // 关闭ROS2节点
  rclcpp::shutdown();
  return 0;
}

Cmakelist

ws_zxy/src/cpp_pubsub/CMakeLists.txt

#...

find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(tutorial_interfaces REQUIRED)                      # 引入接口

add_executable(talker src/msg_publish.cpp)
ament_target_dependencies(talker rclcpp tutorial_interfaces)    # CHANGE

add_executable(listener src/msg_sub.cpp)
ament_target_dependencies(listener rclcpp tutorial_interfaces)  # CHANGE

install(TARGETS
  talker
  listener

  DESTINATION lib/${PROJECT_NAME})

ament_package()

cmake_minimum_required(VERSION 3.8)
project(cpp_pubsub)

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)
find_package(rclcpp REQUIRED)
find_package(tutorial_interfaces REQUIRED)         # interface
# uncomment the following section in order to fill in
# further dependencies manually.
# find_package(<dependency> REQUIRED)


add_executable(talker src/msg_publish.cpp)
ament_target_dependencies(talker rclcpp tutorial_interfaces)    # CHANGE

add_executable(listener src/msg_sub.cpp)
ament_target_dependencies(listener rclcpp tutorial_interfaces)  # CHANGE



if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # the following line skips the linter which checks for copyrights
  # comment the line when a copyright and license is added to all source files
  set(ament_cmake_copyright_FOUND TRUE)
  # the following line skips cpplint (only works in a git repo)
  # comment the line when this package is in a git repo and when
  # a copyright and license is added to all source files
  set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()

#
#  install
#
install(TARGETS
  talker
  listener
  DESTINATION lib/${PROJECT_NAME})

ament_package()

package

<depend>tutorial_interfaces</depend>
<?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_pubsub</name>
  <version>0.0.0</version>
  <description>TODO: Package description</description>
  <maintainer email="452366037@qq.com">zengxy</maintainer>
  <license>TODO: License declaration</license>

  <buildtool_depend>ament_cmake</buildtool_depend>

  <test_depend>ament_lint_auto</test_depend>
  <test_depend>ament_lint_common</test_depend>

  <export>
    <build_type>ament_cmake</build_type>
  </export>

  <depend>tutorial_interfaces</depend>
</package>

编译和添加环境

colcon build --packages-select cpp_pubsub

执行代码

发布者


source install/setup.bash   # ws_zxy
ros2 run cpp_pubsub talker

接受者


source install/setup.bash   # ws_zxy
ros2 run cpp_pubsub listener

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

曾小蛙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值