Skip to content

ROS 2 用户指南

ROS 2-PX4 架构在ROS 2和PX4之间进行了深度整合。 允许 ROS 2 订阅或发布节点直接使用 PX4 uORB 话题。

本指南介绍了系统架构和应用程序流程,并解释了如何与PX4一起安装和使用ROS2。

综述

PX4 supports two middleware options for bridging uORB topics to ROS 2: uXRCE-DDS (DDS) and Zenoh. You must select which middleware to use and build your firmware accordingly (see Installation & Setup). DDS is currently recommended for most users, as it is more established and has been more thoroughly tested with PX4.

If you want to command the vehicle and create custom flight behaviours using ROS 2 (rather than just reading telemetry), you can create external modes using the PX4 ROS 2 Interface Library, a ROS 2 native C++ library that works on top of either middleware.

INFO

The instructions below target simulation using Gazebo. The same concepts translate directly to real hardware: the middleware client, which bridges the uORB topics, runs on the flight controller, while the agent/router runs on your companion computer. See Using Flight Controller Hardware for the hardware-specific differences.

DDS

PX4 v1.14

The uXRCE-DDS communications middleware is a large part of what makes the application pipeline for ROS 2 very straightforward.

Architecture uXRCE-DDS with ROS 2

uXRCE-DDS 中间件由两部分组成:一部分是运行在 PX4 上的客户端,另一部分是运行在机载计算机上的代理;二者之间通过串口、UDP、TCP或自定义链路进行双向数据交换。 代理充当客户端的代理角色,以便在全局 DDS 数据空间中发布和订阅主题。

PX4 uxrce_dds_client 是在构建时生成,并且默认包含在 PX4 固件中。 它包含“通用”XRCE-DDS客户端代码和它用来发布到来自uORB主题的 PX4 特定转换代码。 生成到客户端中的 uORB 消息子集在 dds_topics.yaml中说明。 生成器使用源代码树中的 uORB 消息定义:PX4-Autopilot/msg 用于生成发送 ROS 2 消息的代码。

ROS 2 应用程序需要在一个工作空间中构建,该工作空间需包含与 PX4 固件中创建 uXRCE-DDS 客户端模块时所用完全相同的消息定义。 您可以通过克隆接口包PX4/px4_msgs将这些内容纳入您的 ROS 2 工作空间(repo 中的范围与不同的 PX4 版本的消息相对应)。

从 PX4 v1.16 版本开始message versioning,ROS 2 应用程序所使用的消息定义版本,可与构建 PX4 时所用的消息定义版本不同。 这需要ROS 2 Message Translation Node运行ROS 2 消息转换节点,以确保消息能够正确转换和交互。

需要注意的是,微型XRCE-DDS agent 本身并不依赖客户端代码。 它可以从 source 中单独构建,或者作为ROS构建的一部分,或者作为snap包安装。

在使用 ROS 2 时,您通常需要同时启动客户端和代理。 需要注意的是,uXRCE-DDS 客户端默认已内置到固件中,但除仿真器构建版本外,不会自动启动。

See uXRCE-DDS > Version selection to check which Micro XRCE-DDS version to use for your ROS 2 distribution.

Zenoh

PX4 v1.17 Experimental

PX4 supports Zenoh as an alternative middleware for bridging uORB topics to ROS 2, via the ROS 2 rmw_zenoh middleware. It provides a fast and lightweight way to connect PX4 to ROS 2.

Architecture PX4 Zenoh-Pico with ROS 2

The Zenoh-based middleware consists of a client running on PX4 (the PX4 zenoh module, based on Zenoh-Pico) and a Zenoh router (typically zenohd) running on the companion computer, with bi-directional data exchange between them over a UART, TCP, UDP, or multicast-UDP link. The router acts as a broker and discovery service, enabling PX4 to publish and subscribe to topics in the global Zenoh data space, and integrates seamlessly with ROS 2 nodes using rmw_zenoh.

See the Zenoh middleware page for full architecture and configuration details.

安装与设置

The supported and recommended ROS 2 platform for working with PX4 is ROS 2 "Jazzy" LTS on Ubuntu 24.04.

TIP

If you're working on Ubuntu 22.04 you can use ROS 2 "Humble" LTS instead.

安装使用 PX4 的 ROS 2:

该架构中会自动安装的其他依赖项(如 Fast DDS)未在此处提及。

安装PX4

若要使用该仿真器,你需要安装 PX4 开发工具链。

INFO

唯一依赖于ROS2的 PX4 是一组信息定义,它从px4_msgs获取。 您只需要安装 PX4 当您需要模拟器时(如我们在本指南中所做的那样), 或者如果您正在创建一个发布自定义uORB主题的构建。

通过以下方式在 Ubuntu 上配置一个 PX4 开发环境:

sh
cd
git clone https://github.com/PX4/PX4-Autopilot.git --recursive
bash ./PX4-Autopilot/Tools/setup/ubuntu.sh
cd PX4-Autopilot/
make px4_sitl

请注意,上述命令将为您的Ubuntu版本安装推荐的模拟器。 如果您想要安装 PX4,但保留您现有的模拟器安装,请使用 "--no-sim-tools" 标志运行 ubuntu.sh

欲了解更多信息和故障排除,请参阅:Ubuntu 开发环境下载 PX4 源

安装 ROS 2

安装 ROS 2 及其依赖:

  1. 安装 ROS 2.

:::

::::

  1. 一些Python 依赖关系也必须安装 (使用 pipapt):

    sh
    pip install --user -U empy==3.3.4 pyros-genmsg setuptools

Setup Middleware

This section explains how to set up either the DDS or Zenoh middleware.

TIP

DDS is recommended for most users, as it is more established and has been more thoroughly tested with PX4.

Make sure that your firmware has the corresponding module enabled: the uxrce_dds_client module is included by default in most builds, while the zenoh module must be explicitly enabled.

DDS

要实现 ROS 2 与 PX4 的通信,uXRCE-DDS client必须在 PX4 上运行,且需与运行在机载计算机上的微型 XRCE-DDS 代理建立连接。

设置代理(Agent)

代理可以安装在机载计算机上 number of ways。 下文将介绍如何从源代码 “独立” 构建代理,并连接到运行在 PX4 仿真器上的客户端。

设置并启动代理:

  1. 打开一个终端。

  2. 输入以下命令从仓库获取源代码并构建代理(Agent):

    sh
    git clone -b v2.4.3 https://github.com/eProsima/Micro-XRCE-DDS-Agent.git
    cd Micro-XRCE-DDS-Agent
    mkdir build
    cd build
    cmake ..
    make
    sudo make install
    sudo ldconfig /usr/local/lib/
  3. 启动代理并设置以连接运行在模拟器上的 uXRCE-DDS客户端(Client):

    sh
    MicroXRCEAgent udp4 -p 8888

代理现已启动,但在我们启动 PX4(下一步) 之前,你不会看到太多。

INFO

你可以让代理在这个终端中保持运行状态! 需注意,每个连接通道仅允许运行一个代理

Start the DDS Client

PX4 仿真器会自动启动 uXRCE-DDS 客户端,并连接到本地主机上的 UDP 8888 端口。

启动模拟器(和客户端):

  1. 在之前安装好的 PX4 自动驾驶仪 代码仓库的根目录下,打开一个新的终端。

    使用 PX4 Gazebo 模拟:

    sh
    make px4_sitl gz_x500

代理和客户端现已运行并二者应已建立连接。

PX4 终端会显示 NuttShell/PX4 System Console 系统控制台 的输出内容,该输出会在 PX4 启动和运行过程中实时呈现。 代理一建立连接,输出内容中就应包含 INFO 级别的消息,这些消息会显示数据撰写器的创建情况:

sh
...
INFO  [uxrce_dds_client] synchronized with time offset 1675929429203524us
INFO  [uxrce_dds_client] successfully created rt/fmu/out/failsafe_flags data writer, topic id: 83
INFO  [uxrce_dds_client] successfully created rt/fmu/out/sensor_combined data writer, topic id: 168
INFO  [uxrce_dds_client] successfully created rt/fmu/out/timesync_status data writer, topic id: 188

微型 XRCE-DDS 代理终端也应开始显示输出内容,因为在 DDS 网络中会创建对应的主题:

sh
...
[1675929445.268957] info     | ProxyClient.cpp    | create_publisher         | publisher created      | client_key: 0x00000001, publisher_id: 0x0DA(3), participant_id: 0x001(1)
[1675929445.269521] info     | ProxyClient.cpp    | create_datawriter        | datawriter created     | client_key: 0x00000001, datawriter_id: 0x0DA(5), publisher_id: 0x0DA(3)
[1675929445.270412] info     | ProxyClient.cpp    | create_topic             | topic created          | client_key: 0x00000001, topic_id: 0x0DF(2), participant_id: 0x001(1)

Zenoh

PX4 v1.17 Experimental

For ROS 2 to communicate with PX4 via Zenoh, the PX4 Zenoh-Pico Node must be running on PX4, connected to a Zenoh router (zenohd) running on the companion computer.

Setup the Router

Install and start the Zenoh router using ROS 2:

sh
export RMW_IMPLEMENTATION=rmw_zenoh_cpp
ros2 run rmw_zenoh_cpp rmw_zenohd

For more information about the Zenoh Router see the rmw_zenoh documentation.

INFO

You can leave the router running in this terminal!

Start the Zenoh Client

启动模拟器(和客户端):

  1. 在之前安装好的 PX4 自动驾驶仪 代码仓库的根目录下,打开一个新的终端。

    Start a Zenoh-enabled PX4 Gazebo simulation using:

    sh
    make px4_sitl_zenoh gz_x500
  2. In the PX4 shell, enable Zenoh and reboot to apply the change:

    sh
    param set ZENOH_ENABLE 1
    reboot

The default Zenoh daemon address for the px4_sitl_zenoh target is localhost, so no further network configuration is needed for simulation. See Zenoh > Configure Zenoh Network if you need to connect to a router at a different address (such as on real hardware).

Once the client and router are connected, you can inspect the available topics using standard ROS 2 CLI tools, e.g. ros2 topic list.

构建ROS 2 工作空间

本节介绍如何在你的主目录中创建一个 ROS 2 工作空间(可根据需要修改命令,将源代码放置到其他位置)。

px4_ros_compx4_msgs 这两个功能包会被克隆到工作空间文件夹中,之后使用 colcon 工具对该工作空间进行构建 此示例使用 "ros2 launch" 运行。

您应该使用一个 px4msgs 包的版本与 _same 消息定义作为您已经安装在上面步骤中的 PX4 固件。 px4_msgs 代码仓库中的分支均以特定名称命名,这些名称与不同 PX4 版本的消息定义一一对应。 如果出于任何原因,您不能确保您的 PX4 固件和 ROS 2 px4_msgs 包之间具有相同的消息定义。 您还需要 start the message translation node,作为您设置过程的一部分。

INFO

该示例会构建 ROS 2 Listener 示例应用程序,该程序位于 px4_ros_com中。 px4_msgs 也是需要的,以便示例能够解释PX4 ROS 2 主题。

构建工作空间

要创建和构建工作空间:

  1. 打开一个新的终端。

  2. 使用以下方式创建并进入一个新的工作空间目录:

    sh
    mkdir -p ~/ws_sensor_combined/src/
    cd ~/ws_sensor_combined/src/

    INFO

    一个为工作空间文件夹制定命名规范,有助于更轻松地管理工作空间。

:::

  1. 将示例代码仓库和 px4_msgs 克隆到 /src 目录下(默认克隆 main 分支,该分支与我们当前运行的 PX4 版本相对应):

    sh
    git clone https://github.com/PX4/px4_msgs.git
    git clone https://github.com/PX4/px4_ros_com.git
  2. 在当前终端中加载 ROS 2 开发环境,并使用 colcon 工具编译工作空间:

:::

::::

该操作会使用已加载的工具链对 /src 目录下的所有文件夹进行构建。

运行示例

要运行你刚刚构建好的可执行文件,需加载local_setup.bash 。 这提供了当前工作空间的 "environment hooks"访问权限。 换句话说,它会让刚刚构建好的可执行文件在当前终端中可用。

INFO

ROS2 初学者教程建议您_打开一个新的终端来运行您的可执行文件。

在新终端中:

  1. Navigate into the top level of your workspace directory and source the ROS 2 environment (in this case "Jazzy"):

:::

::::

  1. 加载 local_setup.bash

    sh
    source install/local_setup.bash
  2. 现在启动示例。 请注意,此处我们使用的是 ros2 launch,其相关说明如下。

    sh
    ros2 launch px4_ros_com sensor_combined_listener.launch.py

若此功能正常运行,你应能在启动 ROS 监听器的终端 / 控制台上看到数据正在打印输出

sh
RECEIVED DATA FROM SENSOR COMBINED
================================
ts: 870938190
gyro_rad[0]: 0.00341645
gyro_rad[1]: 0.00626475
gyro_rad[2]: -0.000515705
gyro_integral_dt: 4739
accelerometer_timestamp_relative: 0
accelerometer_m_s2[0]: -0.273381
accelerometer_m_s2[1]: 0.0949186
accelerometer_m_s2[2]: -9.76044
accelerometer_integral_dt: 4739

(可选) 启动转化节点

PX4 v1.16 Experimental

此示例由 PX4 和ROS 2 版本构建,它们使用相同的消息定义。 若你要使用不兼容的 message versions,则在运行示例之前,还需要安装并运行Message Translation Node

  1. 通过运行以下脚本,将 Message Translation Node 纳入示例工作空间或单独的工作空间中

    sh
    cd /path/to/ros_ws
    /path/to/PX4-Autopilot/Tools/copy_to_ros_ws.sh .
  2. 构建并运行转化节点:

    sh
    colcon build
    source install/local_setup.bash
    ros2 run translation_node translation_node_bin

控制机体

要控制应用,ROS 2 应用程序:

  • 订阅 (聆听) PX4 发布的数传主题
  • 发布到导致PX4执行某些操作的主题。

您可以使用的主题定义在dds_topics.yaml, 并且您可以在 uORB Message Reference获取更多关于他们数据的信息。 例如,VehicleGlobalPosition 可以用来获得机体的全局位置。 VehicleCommand 可以用于命令诸如起飞和降落等操作。

下面的 ROS 2 Example applications 示例提供了如何使用这些主题的具体例子。

兼容性问题

本节包含的信息可能会影响你编写 ROS 代码的方式。

ROS 2 订阅者QoS 设置

用于订阅 PX4 发布的话题的 ROS 2 代码,必须指定合适(兼容)的 QoS(服务质量)设置,才能监听这些话题。 具体而言,节点应使用 ROS 2 预定义的 QoS 传感器数据(可参考listener example source code)进行订阅:

cpp
...
rmw_qos_profile_t qos_profile = rmw_qos_profile_sensor_data;
auto qos = rclcpp::QoS(rclcpp::QoSInitialization(qos_profile.history, 5), qos_profile);

subscription_ = this->create_subscription<0>("/fmu/out/sensor_combined", qos,
...

需要这样做的原因是,ROS 2 的默认 Quality of Service (QoS) settings与 PX4 所使用的设置不同。 并非所有发布者 - 订阅者的 Qos settings are possible,而事实证明,ROS 2 默认的订阅者设置就属于不可行的情况!需注意,ROS 代码在发布时无需设置 QoS参数(在此场景下,PX4 的 QoS 设置与 ROS 的默认 QoS 设置是兼容的)。

ROS 2 & PX4 坐标系公约

ROS与 PX4所使用的本地 / 世界坐标系和机体坐标系存在差异。

框架PX4ROS
机体FRD (X Forward, Y Right, Z Down)FLU (X Forward, Y Left, Z Up)
世界坐标系FRD or NED (X North, Y East, Z Down)FLU 或 ENU (X East, Y North, Z Up)

TIP

See REP105: Coordinate Frames for Mobile Platforms for more information about ROS frames.

如果你把机体命名为 robot1,你会得到一个主题,比如 /vrpn_client_node/robot1/pose

Reference frames

除非在相关消息定义中明确指定,否则所有PX4 话题均采用 FRD(即 NED)坐标系约定。 因此,想要与 PX4 进行交互的 ROS 2 节点,必须妥善处理坐标系约定问题。

  • 要将一个向量从ENU坐标系旋转到NED坐标系,必须执行两个基本旋转操作:

    • 首先是绕 Z 轴(朝上方向)旋转 π/2 弧度。
    • 然后是绕 X 轴(原东向 / 新北向)旋转 π 弧度
  • 要将一个向量从NED坐标系旋转到ENU坐标系,必须执行两个基本旋转操作:

    • 首先是绕 Z 轴(朝下方向)旋转 π/2 弧度。
    • 然后是绕 X 轴(原北向 / 新东向)旋转 π 弧度。 需注意,这两种最终得到的操作在数学上是等效的
  • 将向量从 FLU坐标系旋转到 FRD坐标系,仅需绕 X 轴(朝前方向)旋转 π 弧度即可。

  • 将向量从 FRD坐标系旋转到 FLU坐标系,仅需绕 X 轴(朝前方向)旋转 π 弧度即可。

需要进行旋转处理的向量示例包括:

  • TrajectorySetpoint消息中的所有字段;发送这些字段前,需先将其从 ENU坐标系转换为 NED坐标系。
  • VehicleThrustSetpoint消息中的所有字段;发送这些字段前,需先将其从 FLU坐标系转换为 FRD坐标系。

与向量类似,用于表示飞行器(机体坐标系)相对于(w.r.t.)姿态的四元数也是如此。 (相对于)世界坐标系(的四元数)需要进行转换。

PX4/px4_ros_com 提供了名为 frame_transforms的共享库,可便捷地执行此类转换操作。

ROS, Gazebo 和 PX4 时间同步

默认情况下,ROS 2 与 PX4 之间的时间同步由uXRCE-DDS middleware 自动管理;若需查看时间同步统计信息,可监听已桥接的话题 /fmu/out/timesync_status。 当 uXRCE-DDS 客户端运行在飞控器上,且代理运行在机载计算机上时,这便是理想的运行状态 —— 此时时间偏移、时间漂移以及通信延迟会被自动计算并补偿。

在 Gazebo 仿真中,GZBridge 会在每个仿真步长(sim step)为 PX4 设置时间Change simulation speed。 需注意,这与 Gazebo Classic所采用的仿真锁步simulation lockstep流程不同。

对于 ROS 2 用户而言,其节点的time source有两种选择。

ROS2 节点使用操作系统时钟作为时间源

本文档以及offboard_control指南中所采用的便是此场景,同时,该场景也是 ROS 2 节点的标准行为 操作系统时钟作为时间来源,因此它只能在模拟实时系数非常接近时才能使用。 uXRCE-DDS 客户端的时间同步器随后会将 ROS 2 端的操作系统时钟(OS clock)与 PX4 端的 Gazebo 时钟进行桥接同步。 用户不需要进一步操作。

ROS2 节点使用 Gazebo 时钟作为时间源

在这种情况下,ROS2还使用Gazebo`/时钟主题作为时间来源。 若 Gazebo 仿真的实时因子不为 1,或 ROS 2 需直接与 Gazebo 交互,则该方法具有合理性。 在 ROS 2 端,可通过ros_gz代码仓库中的ros_gz_bridge 功能包,实现与 Gazebo 的直接交互。

请使用以下命令,为 PX4 所支持的 ROS 2 和 Gazebo 版本安装正确的 ROS 2/gz 接口功能包(不仅限于桥接功能包)。

INFO

repopackage README显示了需要安装的软件包版本,取决于您的 ROS2 和 Gazebo 版本。

功能包安装并完成环境配置后,parameter_bridge节点会提供桥接能力,可用于创建一个单向的/clock桥接。

sh
ros2 run ros_gz_bridge parameter_bridge /clock@rosgraph_msgs/msg/Clock[gz.msgs.Clock

此时,必须指示每个 ROS 2 节点使用新桥接的/clock话题作为时间源,而非操作系统时钟(OS clock);要实现这一点,需将(每个节点的)use_sim_time参数设置为true(详见ROS clock and Time design)。

至此,ROS 2 端所需的修改已全部完成。 在 PX4 端,你只需停止 uXRCE-DDS 时间同步功能,将参数UXRCE_DDS_SYNCT设置为false即可。 通过此操作,Gazebo 将成为 ROS 2 和 PX4 两者共同的、唯一的主时间源。

ROS 2 示例应用程序

ROS 2 Listener

[px4_ros_com](https://github.com/PX4/px4_ros_com中的 ROS 2 listener examples repo展示了如何编写 ROS 节点,以监听由 PX4 发布的话题

此处我们以 px4_ros_com/src/examples/listeners 路径下的 sensor_combined_listener.cpp 节点为例,该节点会订阅 SensorCombined 消息。

INFO

Build ROS 2 Workspace 显示如何构建和运行这个例子。

代码首先导入了与 ROS 2 中间件进行交互所需的 C++ 库,以及该节点所订阅的SensorCombined消息对应的头部文件:

cpp
#include <rclcpp/rclcpp.hpp>
#include <px4_msgs/msg/sensor_combined.hpp>

随后,代码创建了一个 SensorCombinedListener 类,该类继承自通用的 rclcpp::Node 基类。

cpp
/**
 * @brief Sensor Combined uORB topic data callback
 */
class SensorCombinedListener : public rclcpp::Node
{

这会创建一个回调函数,用于处理SensorCombined uORB 消息(当前以微型 XRCE-DDS 消息格式传输)的接收事件;每当接收到该消息时,该函数会输出消息字段的内容

cpp
public:
  explicit SensorCombinedListener() : Node("sensor_combined_listener")
  {
    rmw_qos_profile_t qos_profile = rmw_qos_profile_sensor_data;
    auto qos = rclcpp::QoS(rclcpp::QoSInitialization(qos_profile.history, 5), qos_profile);

    subscription_ = this->create_subscription<px4_msgs::msg::SensorCombined>("/fmu/out/sensor_combined", qos,
    [this](const px4_msgs::msg::SensorCombined::UniquePtr msg) {
      std::cout << "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
      std::cout << "RECEIVED SENSOR COMBINED DATA"   << std::endl;
      std::cout << "============================="   << std::endl;
      std::cout << "ts: "          << msg->timestamp    << std::endl;
      std::cout << "gyro_rad[0]: " << msg->gyro_rad[0]  << std::endl;
      std::cout << "gyro_rad[1]: " << msg->gyro_rad[1]  << std::endl;
      std::cout << "gyro_rad[2]: " << msg->gyro_rad[2]  << std::endl;
      std::cout << "gyro_integral_dt: " << msg->gyro_integral_dt << std::endl;
      std::cout << "accelerometer_timestamp_relative: " << msg->accelerometer_timestamp_relative << std::endl;
      std::cout << "accelerometer_m_s2[0]: " << msg->accelerometer_m_s2[0] << std::endl;
      std::cout << "accelerometer_m_s2[1]: " << msg->accelerometer_m_s2[1] << std::endl;
      std::cout << "accelerometer_m_s2[2]: " << msg->accelerometer_m_s2[2] << std::endl;
      std::cout << "accelerometer_integral_dt: " << msg->accelerometer_integral_dt << std::endl;
    });
  }

INFO

该订阅会基于 rmw_qos_profile_sensor_data 设置一个 QoS 配置文件。 之所以需要这样做,是因为 ROS 2 订阅者的默认 QoS(服务质量)配置文件,与 PX4 发布者的配置文件不兼容。 欲了解更多信息,请参阅:ROS 2 Subscriber QoS Settings,

以下代码行创建了一个发布者,用于向 SensorCombined uORB 话题发布数据;该发布者可与一个或多个兼容的 ROS 2 订阅者匹配,这些订阅者监听的是 fmu/sensor_combined/out ROS 2 话题。

cpp
private:
 rclcpp::Subscription<px4_msgs::msg::SensorCombined>::SharedPtr subscription_;
};

The instantiation of the SensorCombinedListener class as a ROS node is done on the main function.

cpp
int main(int argc, char *argv[])
{
  std::cout << "Starting sensor_combined listener node..." << std::endl;
  setvbuf(stdout, NULL, _IONBF, BUFSIZ);
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<SensorCombinedListener>());

  rclcpp::shutdown();
  return 0;
}

此特殊示例在launch/sensor_combined_listener.launch.py.有一个相关的启动文件。 这使得它可以通过 ros2 launch 命令启动

ROS 2 发布者

一个 ROS 2 发布者节点会将数据发布到 DDS/RTPS 网络中(进而传递给 PX4 自动驾驶仪)。

以 px4_ros_com/src/advertisers 路径下的 debug_vect_advertiser.cpp(文件)为例,首先我们会导入所需的headers,其中包括 debug_vect msg header。

cpp
#include <chrono>
#include <rclcpp/rclcpp.hpp>
#include <px4_msgs/msg/debug_vect.hpp>

using namespace std::chrono_literals;

随后,代码创建了一个 DebugVectAdvertiser 类,该类继承自通用的 rclcpp::Node 基类。

cpp
class DebugVectAdvertiser : public rclcpp::Node
{

这段代码创建了一个用来发送消息的回调函数。 发送消息的回调函数由定时器触发的,每秒钟发送两次消息。

cpp
public:
  DebugVectAdvertiser() : Node("debug_vect_advertiser") {
    publisher_ = this->create_publisher<px4_msgs::msg::DebugVect>("fmu/debug_vect/in", 10);
    auto timer_callback =
    [this]()->void {
      auto debug_vect = px4_msgs::msg::DebugVect();
      debug_vect.timestamp = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::steady_clock::now()).time_since_epoch().count();
      std::string name = "test";
      std::copy(name.begin(), name.end(), debug_vect.name.begin());
      debug_vect.x = 1.0;
      debug_vect.y = 2.0;
      debug_vect.z = 3.0;
      RCLCPP_INFO(this->get_logger(), "\033[97m Publishing debug_vect: time: %llu x: %f y: %f z: %f \033[0m",
                                    debug_vect.timestamp, debug_vect.x, debug_vect.y, debug_vect.z);
      this->publisher_->publish(debug_vect);
    };
    timer_ = this->create_wall_timer(500ms, timer_callback);
  }

private:
  rclcpp::TimerBase::SharedPtr timer_;
  rclcpp::Publisher<px4_msgs::msg::DebugVect>::SharedPtr publisher_;
};

这段代码在 main 函数中将 DebugVectAdvertiser 类实例化成一个ROS节点。

cpp
int main(int argc, char *argv[])
{
  std::cout << "Starting debug_vect advertiser node..." << std::endl;
  setvbuf(stdout, NULL, _IONBF, BUFSIZ);
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<DebugVectAdvertiser>());

  rclcpp::shutdown();
  return 0;
}

Offboard控制

ROS 2 Offboard control example提供了一个完整的 C++ 参考示例,说明如何使用 PX4 的 offboard control 与 ROS 2。

Python ROS2 offboard examples with PX4 (Jaeyoung-Lim/px4-offboard) 为Python 提供了一个类似的示例,并包含脚本:

  • offboard_control.py: 使用位置设定值进行离板位置控制的示例
  • “visualizer.py`:用于可视化载体状态的 Rviz

使用飞行控制器硬件

在飞行控制器上运行的 PX4 号ROS2与在模拟器上运行的 PX4 几乎相同。 唯一的区别是您需要同时启动agent and the client,并设置适合通信频道。

更多信息详见Starting uXRCE-DDS

自定义 uORB 主题

ROS 2需要有用于在 PX4 固件中创建 uXRCE-DDS客户端模块的 _sam_message 定义,以便解释消息。 这些定义存储在 ROS 2 接口包PX4/px4_msgs中,并且会通过CI在 main(主)分支和发布分支上自动同步。 需要注意的是,PX4 源代码中的所有消息均存在于该代码仓库中,但只有在dds_topics.yaml文件中列出的消息,才会作为 ROS 2 话题可用。 因此

  • 如果您正在使用 PX4 的主要版本或发布版本,您可以通过克隆接口包PX4/px4_msgs获得消息定义。

  • 如果您要创建或修改 uORB 消息,必须从 PX4 源代码树中手动更新工作空间中的消息。 一般来说,这意味着您将更新 dds_topics.yaml,克隆接口包。 然后手动同步,将新的/修改的消息定义从 PX4-Autopilot/msg复制到它的 msg 文件夹。 假定PX4-Autopilot在你的主目录~中,而px4_msgs则在~/ros2_ws/src/中,命令可能是:

    sh
    rm ~/ros2_ws/src/px4_msgs/msg/*.msg
    cp ~/PX4-Autopilot/msg/*.msg ~/ros2_ws/src/px4_msgs/msg/

    INFO

    从技术角度而言,dds_topics.yaml 这个文件完整定义了 PX4 uORB 话题与 ROS 2 消息之间的对应关系。 欲了解更多信息,请参阅uXRCE-DDS > DDS Topics YAML

:::

Customizing the Namespace

自定义主题和服务命名空间可以在构建时间(更改 dds_topics.yaml)或运行时间(对多载体操作有用):

  • 一种可能性是在从命令行启动uxrce_dds_client时使用 "-n" 选项。 这种技术既可用于模拟,也可用于实际机体。
  • 在开始模拟前,可以通过设置环境变量 PX4_UXRCE_DDS_NS来提供自定义命名空间 (仅限)

INFO

更改运行时的命名空间将会将所需的命名空间作为一个前缀附加到 dds_topics.yaml 中所有的 "topic " 字段和所有 service servers。 因此,命令如下:

sh
uxrce_dds_client start -n uav_1

sh
PX4_UXRCE_DDS_NS=uav_1 make px4_sitl gz_x500

将在以下命名空间下生成话题:

sh
/uav_1/fmu/in/  # for subscribers
/uav_1/fmu/out/ # for publishers

PX4 ROS 2 Service Servers

PX4 v1.15

PX4 uXRCE-DDS middleware supports ROS 2 services. 服务(Services)是一种远程过程调用(remote procedure calls),由一个节点发起,向另一个节点请求调用,最终会返回一个结果。

A service server is the entity that will accept a remote procedure request, perform some computation on it, and return the result. They simplify communication between ROS 2 nodes and PX4 by grouping the request and response behaviour, and ensuring that replies are only returned to the specific requesting user. 这比发布请求、订阅回复并过滤掉所有不需要的响应要容易得多。

构建在 PX4 uxrce_dds_client 模块中的服务服务器包括:

所有 PX4 服务名称均遵循 {extra_namespace}/fmu/{server_specific_name} 这一约定,其中 {extra_namespace} 与可分配给 PX4 话题的 custom namespace相同。

具体细节和示例将在以下章节中提供。

载体指挥服务

这可用于向飞行器发送指令(例如 “起飞”“着陆”“切换模式” 和 “盘旋”),并接收响应。

服务类型在 px4_msgs::srv::VehicleCommand 中定义如下:

txt
VehicleCommand request
---
VehicleCommandAck reply

用户可通过发送 VehicleCommand消息发起服务请求,并会收到一条VehicleCommandAck 消息作为响应。 该服务可确保仅将针对用户发起的特定请求所生成的 VehicleCommandAck回复返回。

载体指挥服务离板控制示例

在 px4_ros_com 功能包中,有一个offboard_control_srv 节点,该节点提供了一个完整的、使用 VehicleCommand 服务实现离板控制的示例。

该示例与ROS 2 Offboard Control Example 中描述的离板控制示例高度相似,但使用 VehicleCommand 服务来请求模式切换、飞行器上锁和飞行器解锁。

首先,ROS 2 应用程序会使用 rclcpp::Client() 声明一个类型为 px4_msgs::srv::VehicleCommand 的服务客户端,具体如下(所有 ROS 2 服务客户端均采用此方法)

cpp
rclcpp::Client<0>::SharedPtr vehicle_command_client_;

然后客户端初始化到正确的 ROS 2 服务 (/fmu/vehicle_command )。 当应用程序假设使用标准的 PX4 命名空间时,这样做的代码看起来就像这样:

cpp
vehicle_command_client_{this->create_client<px4_msgs::srv::VehicleCommand>("/fmu/vehicle_command")}

此后,客户可以用来发送任何机体命令请求。 例如,arm()函数用于请求机体放置:

cpp
void OffboardControl::arm()
{
  RCLCPP_INFO(this->get_logger(), "requesting arm");
  request_vehicle_command(VehicleCommand::VEHICLE_CMD_COMPONENT_ARM_DISARM, 1.0);
}

request_vehicle_command处理请求格式化并在_asynchronous_ mode:

cpp
void OffboardControl::request_vehicle_command(uint16_t command, float param1, float param2)
{
  auto request = std::make_shared<px4_msgs::srv::VehicleCommand>();

  VehicleCommand msg{};
  msg.param1 = param1;
  msg.param2 = param2;
  msg.command = command;
  msg.target_system = 1;
  msg.target_component = 1;
  msg.source_system = 1;
  msg.source_component = 1;
  msg.from_external = true;
  msg.timestamp = this->get_clock()->now().nanoseconds() / 1000;
  request->request = msg;

  service_done_ = false;
  auto result = vehicle_command_client_->async_send_request(request, std::bind(&OffboardControl::response_callback, this,
                           std::placeholders::_1));
  RCLCPP_INFO(this->get_logger(), "Command send");
}

最终,响应由 response_callback 方法以异步方式捕获,该方法会检查请求结果:

cpp
void OffboardControl::response_callback(
      rclcpp::Client<0>::SharedFuture future) {
    auto status = future.wait_for(1s);
    if (status == std::future_status::ready) {
      auto reply = future.get()->reply;
      service_result_ = reply.result;
      // make decision based on service_result_
      service_done_ = true;
    } else {
      RCLCPP_INFO(this->get_logger(), "Service In-Progress...");
    }
  }

ros2 CLI

ros2 CLI是一个有用的工具来处理ROS。 例如,您可以使用它快速检查话题是否正在发布;如果您的工作空间中包含 px4_msg,还可以详细查看这些话题的内容。 该命令还允许您通过启动文件(launch file)启动更复杂的 ROS 系统。 下文显示了几种可能性。

ros2 topic list

使用 ros2 topic list 命令列出 ROS 2 可识别的话题:

sh
ros2 topic list

若 PX4 已连接至代理,输出结果将是一份话题类型列表:

sh
/fmu/in/obstacle_distance
/fmu/in/offboard_control_mode
/fmu/in/onboard_computer_status
...

请注意,工作区不需要使用 px4_msgs 构建才能成功;主题类型信息是消息有效载荷的一部分。

ros2 topic echo

使用 ros2 topic echo"来显示特定主题的详细信息。

与 ros2 topic list 命令不同,要让该功能正常工作,你必须处于一个已编译 px4_msgs且已执行 local_setup.bash 脚本的工作空间中,这样 ROS 才能解析相关消息

sh
ros2 topic echo /fmu/out/vehicle_status

该命令将在主题细节更新时响应它们的详细信息。

sh
---
timestamp: 1675931593364359
armed_time: 0
takeoff_time: 0
arming_state: 1
latest_arming_reason: 0
latest_disarming_reason: 0
nav_state_timestamp: 3296000
nav_state_user_intention: 4
nav_state: 4
failure_detector_status: 0
hil_state: 0
...
---

ros2 topic hz

你可以使用 ros2 topic hz 命令获取消息速率相关的统计信息。 例如,获取SensorCombined速率:

sh
ros2 topic hz /fmu/out/sensor_combined

输出会看起来像这样:

sh
average rate: 248.187
min: 0.000s max: 0.012s std dev: 0.00147s window: 2724
average rate: 248.006
min: 0.000s max: 0.012s std dev: 0.00147s window: 2972
average rate: 247.330
min: 0.000s max: 0.012s std dev: 0.00148s window: 3212
average rate: 247.497
min: 0.000s max: 0.012s std dev: 0.00149s window: 3464
average rate: 247.458
min: 0.000s max: 0.012s std dev: 0.00149s window: 3712
average rate: 247.485
min: 0.000s max: 0.012s std dev: 0.00148s window: 3960

ros2 launch

ros2 launch 命令用于启动一个 ROS 2 启动文件 例如,前面我们使用 ros2 launch px4_ros_com sensor_combined_listener.launch.py 命令启动了监听器示例。

你并非必须使用启动文件,但如果你的 ROS 2 系统较为复杂,需要启动多个组件,那么启动文件会非常实用。

关于启动文件的信息,请参阅 ROS 2 Tutorials > Creating launch files

故障处理

缺少依赖项

标准安装应包含 ROS 2 所需的所有工具。

如果有任何缺失,可以单独添加:

  • colcon 构建工具应该在开发工具中。 可以使用以下方式安装它:

    sh
    sudo apt install python3-colcon-common-extensions
  • 变换库(transforms library)所使用的 Eigen3 库,应同时存在于桌面版(desktop)功能包和基础版(base)功能包中。 它应该安装在显示中:

:::

::::

ros_gz_bridge not publishing on the \clock topic

如果你的ROS2 nodes use the Gazebo clock as time sourceros_gz_bridge 节点没有发布任何关于`/时钟' 主题的内容。 您可能安装了错误的版本。 若你在安装 ROS 2 Humble 时,使用的是默认的 “Ignition Fortress” 功能包,而非 PX4 所使用的、适配 “Gazebo Harmonic” 的功能包,就可能出现这种情况。

以下命令会卸载默认的 Ignition Fortress 功能包,并为搭配 ROS 2 Humble 版本的 Gazebo Harmonic 安装正确的桥接功能包及其他接口功能包:

bash
# Remove the wrong version (for Ignition Fortress)
sudo apt remove ros-humble-ros-gz

# Install the version for Gazebo Garden
sudo apt install ros-humble-ros-gzharmonic

更多信息