ros2--接口

什么是接口

这里的接口不是编程语言中的函数接口。而是应该理解为在ros2中进行数据通信的接口;这些接口在ros2中使用时必须有统一的标准,就像陷淖USB接口一样有着统一的通信协议。所以这里的接口更好的理解是:ros2数据通信的统一接口。

我们创建话题的时候,需要指定话题的类型,创建服务的时候也需要指定客户端和服务端服务的类型,不管是话题还是服务,这些类型都是结构体。

而这些通信的对象,不管是发起端还是接收端,都要指定数据通信的接口类型,而且只有发起端和接收端的接口类型一致,才能进行正常的数据通信。

接口的作用

指定数据通信两端使用的统一协议(统一数据格式--本质上就是统一结构体类型)。

ros2的四种通信方式和3中接口

链接

ros2原生的接口

查看ros2中所有接口

ros2 interface list

包括ros2原生的,以及后续添加的。

查看某个接口的定义

ros2 interface show 接口的完整路径(功能包/目录/接口名)

接口文件定义

msg,srv,action文件中都可以定义哪些类型的变量?

小鱼教程

1,9个基础数据类型;

2,自定义类型;

定义数组类型

只需要在类型的后面加上[ ]就是定义数组;

uint32 data

构建之后生成的数组是std::vector类型。

自定义接口

1,创建功能包及接口类别目录

在功能包目录下创建msg(话题),或者srv(服务),或者action(动作)功能包;

2,创建接口文件

在msg目录下创建xxx.msg话题接口文件,在srv目录下创建xxx.srv服务文件,在action目录下创建xxx.action动作文件;

3,定义接口文件

话题接口--msg

话题是单项传输,所以只需要描述一次传输的数据有哪些即可;

一个msg中的所有变量就是一次传输的所有数据。

int32 x

int32 y

一次需要传输的消息对象的数据有这些成员。

服务接口--srv

服务需要包含请求和应答数据;

srv文件中需要定义请求和应答两个部分的数据,这两个部分需要以三个横线分割;

#请求数据

int64 a int64 b

---

#响应的数据

int64 sum

动作接口--action

动作接口文件需要三个部分组成:

目标+结果+之间状态反馈;

中间还是以三个横线分割;

# Goal: 要移动的距离
float32 distance
---
# Result: 最终的位置
float32 pose
---
# Feedback: 中间反馈的位置和状态
float32 pose
uint32 status
uint32 STATUS_MOVEING = 3
uint32 STATUS_STOP = 4

4,cmake增加接口路径

(1)添加生成接口的cmake接口库:

find_package(rosidl_default_generators REQUIRED)

(2)添加接口文件中依赖的其他接口库:

eg:

uint32 STATUS_MOVEING = 1
uint32 STATUS_STOP = 2
uint32  status
geometry_msgs/Pose pose

cmake:

find_package(geometry_msgs REQUIRED)

(3)利用cmake的接口将指定的接口文件生成接口

rosidl_generate_interfaces(${PROJECT_NAME} "msg/RobotPose.msg" "msg/RobotStatus.msg" "srv/MoveRobot.srv" DEPENDENCIES geometry_msgs )

注意:rosidl_generate_interface后有s.

5,package声明依赖

需要声明哪些依赖:

(1)接口文件需要依赖的包:

<depend>rosidl_default_generators</depend>

(2)声明这个包所属的组:

<member_of_group>rosidl_interface_packages</member_of_group>

表示该ROS2包是roidl_interface_packages组的成员,该组用于标识包含ROS2消息和服务定义的包。这样可以方便地将包分类和组织起来。

6,colcon构建生成接口文件

colcon build --package-select 功能包名

生成的文件位于:

工作空间的install/功能包/includ/功能包/功能包  下。

生成的接口的本质

colcon构建生成接口之后,使用:

ros2 interface package 功能包名称

可以查看功能包中定义的接口。

msg--结构体定义

使用以下案例来说明接口的定义和生成:

功能包和接口文件:

robot_move_interface/msg/RobotPose.msg

文件名:

RobotPose.msg

文件内容:

uint32 STATUS_MOVING=1

uint32 STATUS_STOP=2

uint32 status

geometry_msgs/Pose pose

concol构建:

colcon build --package-select robot_move_interface

构建之后会在工作目录下的install下生成robot_move_interface功能包,功能包中的include目录下会生成接口文件对应的c++代码文件。也就是构建之后,cmake 将我们在msg文件中对接口内容的描述生成了对应的c++代码文件。

重点:

(1)接口头文件和源文件格式。

colcon生成的c++接口头文件和源文件会以我们定义msg,srv,action文件时大写字母为分割,使用下划线连接,生成接口文件。

eg:

msg:

RobotPose.msg

c++:

robot_pose.h

robot_pose.hpp

(2)生成的内容

msg目录和srv目录下主要有一个detail目录和一些头文件,这些头文件中就包含我们使用时需要引用的头文件,比如:

robot_pose.hpp

(3)被引用头文件内容:

// generated from rosidl_generator_cpp/resource/idl.hpp.em
// generated code does not contain a copyright notice#ifndef ROBOT_MOVE_INTERFACE__MSG__ROBOT_POSE_HPP_
#define ROBOT_MOVE_INTERFACE__MSG__ROBOT_POSE_HPP_#include "robot_move_interface/msg/detail/robot_pose__struct.hpp"
#include "robot_move_interface/msg/detail/robot_pose__builder.hpp"
#include "robot_move_interface/msg/detail/robot_pose__traits.hpp"#endif  // ROBOT_MOVE_INTERFACE__MSG__ROBOT_POSE_HPP_

被引用的头文件只是简单的引用了detail目录中的三个头文件。

而detail目录下的三个头文件,我们在msg,srv,action中描述的内容转化为struct.hpp中的结构体类型。

(4)detail中的结构体文件。

文件内容:

namespace robot_move_interface

{

namespace msg

{

// message struct

template<class ContainerAllocator>

struct RobotPose_

{

......

// field types and members

using _status_type =

uint32_t;

_status_type status;

using pose_type =

_ geometry_msgs::msg::Pose_<ContainerAllocator>;

_pose_type pose;

// setters for named parameter idiom

Type & set__status(

const uint32_t & _arg)

{

this->status = arg;

return *this;

}

Type & set__pose(

_ const geometry_msgs::msg::Pose_<ContainerAllocator> & _arg)

{

this->pose = _arg;

return *this;

}

// constant declarations

static constexpr uint32_t STATUS_MOVING =

1u;

static constexpr uint32_t STATUS_STOP =

2u;

......

};

重点在于:

【1】以功能包/msg/msg文件名_的格式定义结构体;

注意:这里是以“消息文件的文件名+下划线”的方式生成结构体。

【2】结构体内定义我们描述的变量,常量,在构造函数内有对变量的初始化;

【3】对于变量有如同protobuf一样的set_变量名的设置函数;

我们最终使用的结构体不是:

robot_move_interface::msg::RobotPose_  

的格式,而是:

robot_move_interface::msg::RobotPose

这种没有下划线的格式。

所以在xxx_struct.hpp中有如下声明:

using RobotPose =

robot_move_interface::msg::RobotPose_<std::allocator<void>>;

这就是我们最终使用的结构体的声明。

srv--结构体定义

.srv描述:

#请求数据

float32 distance

---

#响应数据

float32 pose

.hpp中的结构体定义:

请求结构体:

namespace robot_move_interface
{namespace srv
{// message struct
template<class ContainerAllocator>
struct MoveRobot_Request_
{......// field types and membersusing _distance_type =float;_distance_type distance;// setters for named parameter idiomType & set__distance(const float & _arg){this->distance = _arg;return *this;}
};  // struct MoveRobot_Request_
// alias to use template instance with default allocator
using MoveRobot_Request =robot_move_interface::srv::MoveRobot_Request_<std::allocator<void>>;
}
}

响应结构体:

namespace robot_move_interface
{namespace srv
{// message struct
template<class ContainerAllocator>
struct MoveRobot_Response_
{......// field types and membersusing _pose_type =float;_pose_type pose;// setters for named parameter idiomType & set__pose(const float & _arg){this->pose = _arg;return *this;}
};  // struct MoveRobot_Response_// alias to use template instance with default allocator
using MoveRobot_Response =robot_move_interface::srv::MoveRobot_Response_<std::allocator<void>>;// constant definitions
}  // namespace srv
}  // namespace robot_move_interface

接口结构体:

namespace robot_move_interface
{namespace srv
{struct MoveRobot
{using Request = robot_move_interface::srv::MoveRobot_Request;using Response = robot_move_interface::srv::MoveRobot_Response;
};}  // namespace srv}  // namespace robot_move_interface

重要的就是接口中只有两个请求和响应结构体对象。

action--结构定义

action构建下会构建一个action目录和一个msg目录;

action目录下的detail:

(1)目标结构体定义:

namespace action_interface
{namespace action
{// message struct
template<class ContainerAllocator>
struct MoveRobot_Goal_
{......// field types and membersusing _distance_type =float;_distance_type distance;// setters for named parameter idiomType & set__distance(const float & _arg){this->distance = _arg;return *this;}......
};  // struct MoveRobot_Goal_// alias to use template instance with default allocator
using MoveRobot_Goal =action_interface::action::MoveRobot_Goal_<std::allocator<void>>;// constant definitions}  // namespace action}  // namespace action_interface

(2)结果结构体的定义:

namespace action_interface
{namespace action
{// message struct
template<class ContainerAllocator>
struct MoveRobot_Result_
{......// field types and membersusing _pose_type =float;_pose_type pose;// setters for named parameter idiomType & set__pose(const float & _arg){this->pose = _arg;return *this;}......
};  // struct MoveRobot_Result_// alias to use template instance with default allocator
using MoveRobot_Result =action_interface::action::MoveRobot_Result_<std::allocator<void>>;// constant definitions}  // namespace action}  // namespace action_interface

(3)反馈结构体的定义:

namespace action_interface
{namespace action
{// message struct
template<class ContainerAllocator>
struct MoveRobot_Feedback_
{......// field types and membersusing _status_type =float;_status_type status;using _pose_type =uint32_t;_pose_type pose;// setters for named parameter idiomType & set__status(const float & _arg){this->status = _arg;return *this;}Type & set__pose(const uint32_t & _arg){this->pose = _arg;return *this;}// constant declarationsstatic constexpr uint32_t STATUS_MOVING =3u;static constexpr uint32_t STATUS_STOP =4u;......
};  // struct MoveRobot_Feedback_// alias to use template instance with default allocator
using MoveRobot_Feedback =action_interface::action::MoveRobot_Feedback_<std::allocator<void>>;
}  // namespace action}  // namespace action_interface

太多了,看源码。

我们如何在c++文件中引用自定义功能包中的接口文件?

需要在CMakeLists.txt文件中find_package()找到我们自定义的功能包的配置文件,在通ament_target_dependencies()和项目建立链接关系。

find_package(robot_move_interface REQUIRED)

add_executable(robot_move src/robot_move_server.cpp)

ament_target_dependencies(robot_move rclcpp robot_move_interface)

这样就可以使用自定义的接口文件中我定义的接口(结构体)了。

接口的命令

查看功能包中定义了哪些接口

ros2 interface package 功能包名称

生成的接口包不能引用

如果没有配置shell脚本,生成的接口包在构建之后需要执行以下install中的脚本使新生成的脚本发挥作用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/49224.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JAVA中的输入输出流

FileInputStream、FileOutputStream&#xff08;字节流&#xff09; 字节输入流InputStream主要方法&#xff1a; read() &#xff1a;从此输入流中读取一个数据字节。 read(byte[] b) &#xff1a;从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。 read(b…

单例模式懒汉模式和饿汉模式

线程安全 单例模式在单线程中&#xff0c;当然是安全的。但是如果在多线程中&#xff0c;由于并行判断&#xff0c;可能会导致创建多个实例。那么如何保证在多线程中单例还是只有一个实例呢? 常见的三种方式: 局部静态变量 原理和饿汉模式相似&#xff0c;利用static只会初始…

cURL自动读取小工具

做自动化测试的时候Postman判断数据什么的太麻烦&#xff0c;做个脚本代替一下 curl_parser.py import redef parse_curl(curl_command):# 匹配所有的 -H "key: value"header_pattern re.compile(r-H "([^:]): ([^"])")headers dict(header_patte…

Redis系列命令更新--Redis有序集合命令

Redis有序集合&#xff08;sorted set&#xff09; &#xff08;1&#xff09;说明&#xff1a; A、Redis有序集合和集合一样也是string类型元素的集合&#xff0c;且不允许重复的成员&#xff1b;不同的是每个元素都会关联一个double类型的分数&#xff1b;redis正式通过分数…

Web开发:元素

元素 基础结构元素文本内容元素列表元素多媒体元素表格元素表单元素语义元素示例结构分析基础结构元素头部和导航主页部分关于部分服务部分联系部分侧边栏页脚 基础结构元素 <!DOCTYPE html>&#xff1a;声明文档类型&#xff0c;告诉浏览器使用HTML5标准解析文档。它必…

MongoDB 文档存储

安装 下载&#xff1a; Download MongoDB Community Server | MongoDB 说明&#xff1a; 现在基本都安装的是4.4以后的版本。安装完成后使用 mongod 来查看是否安装成功 会输出一堆内容 而如果想要操作数据库&#xff0c;则需要安装一个工具&#xff0c;mongosh-2.2.12-x64.m…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 堆内存申请(100分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,支持题目在线…

linux(CentOS、Ubuntu)安装python3.12.2环境

1.下载官网Python安装包 wget https://www.python.org/ftp/python/3.12.2/Python-3.12.2.tar.xz 1.1解压 tar -xf Python-3.12.2.tar.xz 解压完后切换到Python-3.12.2文件夹(这里根据自己解压的文件夹路径) cd /usr/packages/Python-3.12.2/ 1.2升级软件包管理器 CentOS系…

微信小程序canvas 使用案例(一)

一、cavans 对象获取、上线文创建 1.wxml <!-- canvas.wxml --><canvas type"2d" id"myCanvas"></canvas> 2.js /*** 生命周期函数--监听页面加载*/onLoad(options) {const query wx.createSelectorQuery()query.select(#myCanvas).f…

mysql练习3

1.修改student 表中年龄(sage)字段属性&#xff0c;数据类型由int 改变为smallint 2.为Course表中Cno 课程号字段设置索引,并查看索引 3.为SC表建立按学号(sno)和课程号(cno)组合的升序的主键索引&#xff0c;索引名为SC_INDEX 4.创建一视图 stu info,查询全体学生的姓名&#…

IDEA的APIPost接口测试插件详解

APIPOST官方网址 一、安装APIPost插件 打开IntelliJ IDEA&#xff1a; 启动您的IntelliJ IDEA开发环境。 导航到插件设置&#xff1a; 在Windows或Linux上&#xff0c;点击 File > Settings。在macOS上&#xff0c;点击 IntelliJ IDEA > Preferences。 搜索并安装APIPo…

前端:上传2进制图片

1、let formData new FormData(); 2、添加要传的字段&#xff1a;formData.append("avatarfile", data); &#xff08;key,value&#xff09; 3、上传文件 function uploadImg() {// 1定义FormDatalet formData new FormData();// 2添加字段formData.append("…

安装好anaconda,打开jupyter notebook,新建 报500错

解决办法&#xff1a; 打开anaconda prompt 输入 jupyter --version 重新进入jupyter notebook&#xff1a; 可以成功进入进行代码编辑

建筑工程企业项目管理系统哪个好?试试企智汇工程项目管理系统

在建筑工程行业中&#xff0c;项目管理的复杂性和挑战性是众所周知的。随着项目规模的扩大和技术的不断进步&#xff0c;传统的管理方法已经难以满足现代建筑工程的需求。企智汇工程项目管理系统应运而生&#xff0c;为建筑工程企业提供了一个全面、智能、高效的解决方案。 一…

[mmdetection]Faster-RCNN模型断点训练方法

断电等问题时常发生&#xff0c;因此我们会对模型进行断点训练。 如mmdetection项目中的FasterRCNN模型训练时出现训练突然中断&#xff0c;我们将使用如下命令从中断的epochs继续训练。 首先我们来看看模型训练时会生成的的文件&#xff1a; 接下来我们将使用如下命令进行断…

【深大计算机系统(2)】实验一 实验环境配置与使用 附常用指令

目录 一、 实验目标&#xff1a; 二、实验环境与工件&#xff1a; 三、实验内容与步骤 1. 学习并熟悉Linux基本操作&#xff0c;按照要求创建用户。&#xff08;30分&#xff09; 2.新建用户主目录下创建子目录&#xff1a;gdbdebug&#xff0c;并进入gdbdebug子目录。将过程和…

Golang | Leetcode Golang题解之第241题为运算表达式设计优先级

题目&#xff1a; 题解&#xff1a; const addition, subtraction, multiplication -1, -2, -3func diffWaysToCompute(expression string) []int {ops : []int{}for i, n : 0, len(expression); i < n; {if unicode.IsDigit(rune(expression[i])) {x : 0for ; i < n &…

C语言——详解结构体内字符型数据定义与初始化

在C语言中&#xff0c;结构体内的字符型数据可以通过多种方式进行定义&#xff0c;并且每种定义方式都有其对应的初始化方法。这些定义方式包括直接定义字符数组、使用字符指针以及结合结构体的不同定义风格。理解这些定义方式及其初始化方法对于编写高效、可维护的C语言程序至…

leetcode日记(47)螺旋矩阵Ⅱ

这题思路不难&#xff0c;就是找规律太难了。 我首先的思路是一行一行来&#xff0c;根据规律填入下一行的数组&#xff0c;第i行是由前i个数字&#xff08;n-2*i&#xff09;个增序数列后i个数字组成&#xff0c;后来觉得太难找规律了就换了一种思路。 思路大致是先计算出需…

googleTest 源码主线框架性分析

TDD&#xff0c;测试驱动开发&#xff0c;英文全称Test-Driven Development&#xff0c;简称TDD&#xff0c;是一种不同于传统软件开发流程的新型的开发方法。它要求在编写某个功能的代码之前先编写测试代码&#xff0c;然后只编写使测试通过的功能代码&#xff0c;通过测试来推…