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 members
  using _distance_type =
    float;
  _distance_type distance;

  // setters for named parameter idiom
  Type & 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 members
  using _pose_type =
    float;
  _pose_type pose;

  // setters for named parameter idiom
  Type & 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 members
  using _distance_type =
    float;
  _distance_type distance;

  // setters for named parameter idiom
  Type & 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 members
  using _pose_type =
    float;
  _pose_type pose;

  // setters for named parameter idiom
  Type & 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 members
  using _status_type =
    float;
  _status_type status;
  using _pose_type =
    uint32_t;
  _pose_type pose;

  // setters for named parameter idiom
  Type & set__status(
    const float & _arg)
  {
    this->status = _arg;
    return *this;
  }
  Type & set__pose(
    const uint32_t & _arg)
  {
    this->pose = _arg;
    return *this;
  }

  // constant declarations
  static 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中的脚本使新生成的脚本发挥作用。

  • 18
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: ROS2 Web Bridge是一个开源的软件包,旨在使ROS2(Robot Operating System 2)与Web端进行通信和交互。它提供了一种简单而强大的方式,通过WebSocket协议将ROS2系统中的数据传输到Web浏览器。 ROS2 Web Bridge允许Web开发人员使用常见的Web技术(例如JavaScript)直接与ROS2系统进行交互。它提供了一个轻量级的接口,可以订阅和发布ROS2主题,并在Web浏览器中实时显示传感器数据、控制机器人等。 此外,ROS2 Web Bridge还支持ROS2服务和动作。它允许Web应用程序在Web端调用ROS2服务,从而实现与ROS2节点的双向通信。通过一个用户友好的Web界面,用户可以发送控制命令给机器人,执行任务并获得实时反馈。 ROS2 Web Bridge的主要优点之一是其跨平台性。它基于WebSocket协议,因此可以在不同的操作系统和设备上使用,无论是在PC端还是移动设备上。 此外,ROS2 Web Bridge还支持认证和授权机制,以确保通信安全。这对于确保只有被授权的用户可以访问和控制ROS2系统非常重要。 总的来说,ROS2 Web Bridge为ROS2系统提供了一种简便而强大的方式,使Web开发人员能够与ROS2系统进行交互。它扩展了ROS2的功能,使得机器人开发更加灵活和可视化。 ### 回答2: ros2-web-bridge是一种用于在ROS 2和Web应用程序之间进行通信的桥接工具。ROS 2是机器人操作系统的第二代版本,而Web应用程序是通过Web浏览器访问的应用程序。 ros2-web-bridge有几个主要功能。首先,它允许ROS 2中的节点直接与通过Web浏览器访问的Web应用程序进行通信。这使得在Web界面上实时监控和控制ROS 2系统变得更加容易。例如,可以使用ros2-web-bridge将传感器数据从ROS 2节点发送到Web应用程序,以便在Web界面上实时显示传感器数据。同时,还可以将来自Web界面的用户输入发送到ROS 2节点,以便远程控制机器人或系统。 其次,ros2-web-bridge还提供了一些工具和API,用于将ROS 2中的消息和服务转换为Web格式。这使得可以轻松地在ROS 2和Web应用程序之间进行数据传输和交互。它支持使用ROS 2的套接字和JSON进行通信,并提供了将消息和服务转换为JSON格式以及反向转换的功能。这样,ROS 2节点可以与通过Web浏览器访问的Web应用程序进行无缝通信。 总而言之,ros2-web-bridge为ROS 2和Web应用程序之间的通信提供了一个便捷的桥梁。它简化了ROS 2系统与Web界面之间的集成,并提供了实时数据传输和远程控制的能力。这对于构建基于ROS 2的机器人或系统的开发者和使用者来说是非常方便的工具。 ### 回答3: ros2-web-bridge是一个用于将ROS 2和Web技术进行连接的工具。它提供了一个桥接器,使得可以通过Web浏览器与ROS 2通信。这个工具是建立在ROS 2和Web Socket之间的通信基础上的。 通过ros2-web-bridge,我们可以在Web浏览器中实时地订阅和发布ROS 2的消息。这使得我们可以通过Web界面来控制ROS 2的机器人,或者将ROS 2的数据可视化展示出来。这对于远程监控、远程操作和数据可视化都非常有用。 ros2-web-bridge使用ROS 2提供的接口来与ROS 2系统进行通信。它将ROS 2的消息转换为适用于Web Socket的格式,并在浏览器和ROS 2之间建立起适配的连接。通过这种方式,Web界面就能够与ROS 2系统进行实时的双向通信。 ROS 2中的消息传递方式是异步的,而Web浏览器通常使用同步的方式进行通信。ros2-web-bridge通过在ROS 2和Web Socket之间进行适配和转换,使得二者能够协同工作。这意味着ROS 2中的数据可以通过ros2-web-bridge传输到Web浏览器,并在该浏览器中进行处理和展示。 总的来说,ros2-web-bridge是一个功能强大的工具,它架起了ROS 2和Web技术之间的桥梁。它使得我们可以通过Web浏览器来与ROS 2进行通信,进而实现远程操作和数据可视化的目的。通过ros2-web-bridge,我们可以更加灵活和方便地利用ROS 2的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值