跳至内容

PX4 ROS 2 控制界面

主页(PX4 v1.15) 实验性

实验性

在撰写本报告时,PX4 ROS 2 控制界面的部分内容还处于试验阶段,因此可能会发生变化:

  • ROS 2 模式中定义模式的架构和核心接口已基本稳定,并已在 CI 中进行了测试。与目前使用的离板模式相比,该库具有明显优势。
  • 只有少数设定点类型已经确定(其他类型仍在开发中)。您可能需要使用内部 PX4 主题,而这些主题可能无法长期保持向后兼容。
  • 应用程序接口没有完整的文档。

PX4 ROS 2 接口库 是一个 C++ 库,可简化 ROS 2 对 PX4 的控制。

开发人员使用该库创建并动态注册使用 ROS 2 编写的模式。这些模式与 PX4 一起动态注册,在地面站或其他外部系统看来是 PX4 的一部分。开发人员甚至可以用增强的 ROS 2 版本替换 PX4 中的默认模式,如果 ROS 2 模式失效,则返回到原始版本。

该库还提供了用于发送不同类型设定点的类,从高级导航任务一直到直接执行器控制。这些类抽象了 PX4 使用的内部设定点,因此可用于为未来的 PX4 和 ROS 版本提供一致的 ROS 2 接口。

概述

该图从概念上概述了控制界面模式和模式执行器如何与 PX4 交互。

ROS2 模式概览图

下文将对图表中使用的术语进行定义和解释。

定义

模式

使用接口库定义的模式具有以下属性:

  • 模式是一个可以向载具发送设定点以控制其运动(如速度或直接执行器指令)的组件。
  • 模式选择一种设定点类型,并在激活时发送。它可以在多个设定点类型之间切换。
  • 一种模式不能激活其他模式,必须由用户(通过遥控/监控系统)、飞行控制器在故障安全情况下、飞行控制中心(通过遥控/监控系统)、飞行控制中心(通过遥控器)、飞行控制中心(通过飞行控制中心)、飞行控制中心(通过飞行控制中心)、飞行控制中心(通过飞行控制中心)激活。 模式执行器或其他外部系统。
  • 有一个由 GCS 显示的名称。
  • 可以配置其模式要求(例如,它需要有效的位置估计)。
  • 一种模式可以执行不同的任务,例如飞向目标、放下绞盘、释放有效载荷,然后再飞回来。
  • 一个模式可以取代 PX4 中定义的一个模式。

模式执行器

模式执行器是调度模式的可选组件。例如,自定义有效载荷交付或勘测模式的模式执行器可能首先触发起飞,然后切换到自定义模式,并在完成后触发 RTL。

具体来说,它具有以下特性:

  • 模式执行器是比模式高一级的可选组件。它是一个状态机,可以激活模式并等待模式完成。
  • 它只能在自己负责的时候这样做。为此,执行者正好有一个 自有模式 (一个模式最多只能被一个执行器拥有)。该模式可作为执行器的激活模式:当用户选择该模式时,拥有该模式的执行器将被激活,并可选择任何模式。在用户切换模式(通过 RC 或 GCS)或故障安全触发模式切换之前,执行器将一直负责。如果故障安全解除,执行器将重新激活。
  • 这使得多个执行器可以共存。
  • 执行者不能激活其他执行者。
  • 在程序库中,模式执行器总是与自定义模式结合使用。

信息

  • 这些定义保证了用户可以在任何时候通过 RC 或 GCS 发出模式切换命令,从自定义模式或执行器中夺走控制权。
  • 模式执行器对用户是透明的。它通过所拥有的模式被间接选择和激活,因此模式也应相应命名。

配置重写

模式和执行器都可以定义配置重载,允许在模式或执行器处于活动状态时自定义某些行为。

目前正在实施这些计划:

  • 禁用自动撤膛.这样就可以着陆,然后再次起飞(例如释放有效载荷)。
  • 推迟非必要故障保险的能力.这样,执行器就可以在不被非关键故障保护中断的情况下运行操作。例如,忽略低电池故障安全保护,以便完成绞盘操作。

与机外控制比较

与传统方法相比,上述概念具有以下优势 车载控制:

  • 多个节点或应用程序可以共存,甚至可以同时运行。但只有一个节点可以 控制载具 这个节点的定义非常明确。
  • 模式有一个独特的名称,并可在全球控制系统中显示/选择。
  • 模式与故障安全状态机和上膛检查集成在一起。
  • 可发送的设定点类型已明确定义。
  • ROS 2 模式可取代飞行控制器内部模式(如 返回模式).

安装和首次测试

开始操作需要以下步骤:

  1. 确保您的 ROS 2 设置px4_msgs 在 ROS 2 工作区中。

  2. 将版本库克隆到工作区:

    CD $ros_workspace/src
    Git 复制 --递归 https://github.com/Auterion/px4-ros2-interface-lib

    信息

    为确保兼容性,请使用最新的 主要 PX4 的分支、 px4_msgs 和图书馆。参见 这里.

  3. 建立工作区:

    CD ..
    胶管 构建
    消息来源 install/setup.bash
  4. 在另一个外壳中,启动 PX4 SITL:

    CD $px4-自动驾驶仪
    生产 px4_sitl 古董

    (这里我们使用的是 Gazebo-Classic,但您也可以使用任何模型或模拟器)。

  5. 在新的 shell 中运行 micro XRCE 代理(之后可以继续运行):

    MicroXRCEAgent udp4 -p 8888
  6. 启动 QGroundControl。

    信息

    使用 QGroundControl Daily,它支持动态更新模式列表。

  7. 回到 ROS 2 终端,运行其中一个示例模式:

    玫瑰2 运行 示例模式手册_cpp 手动模式示例

    您应该会得到这样的输出结果,显示'我的手动模式'模式已注册:

    [DEBUG] [example_mode_manual]:检查消息兼容性...
    [DEBUG] [example_mode_manual]:找到订阅者,继续
    [DEBUG] [example_mode_manual]:找到发布者,继续
    [DEBUG] [example_mode_manual]:注册 '我的手动模式'; (上膛 检查: 1, 模式: 1, 模式 执行人: 0)
    [DEBUG] [example_mode_manual]:找到订阅者,继续
    [DEBUG] [example_mode_manual]:找到发布者,继续
    [DEBUG] [example_mode_manual]:得到 RegisterExtComponentReply
    [DEBUG] [example_mode_manual]:启动检查请求(id=1, 只是 印刷的 一次)
  8. 在 PX4 外壳上,可以检查 PX4 是否注册了新模式:

    司令员 地位

    输出结果应包括

    平实
    INFO [指挥官] 解除警报
    INFO [指令长] 导航模式:位置
    INFO [指令长] 用户预定导航模式:位置
    INFO [commander] in failsafe: no
    INFO [指令长] 外部模式 1:Nav_state:23,名称:我的手动模式
  9. 此时,您应该也能在 QGroundControl 中看到该模式:

    QGC 模式

  10. 选择模式,确保有手动控制源(物理或虚拟操纵杆),然后启动载具。然后激活模式,并打印以下输出:

    [DEBUG] [example_mode_manual]:模式 '我的手动模式'; 激活
  11. 现在,您可以创建自己的模式了。

如何使用图书馆

下文将介绍该库提供的具体功能。此外,还可以订阅或发布任何其他 PX4 主题。

模式类别定义

本节将举例说明如何为自定义模式创建类。

如需完整的申请表,请查看 中的例子 Auterion/px4-ros2-interface-lib 知识库例如 示例/cpp/modes/manual.

cpp
 我的模式 :  px4_ros2::模式基础 // [1]
{
公众:
  不含糊 我的模式(rclcpp::节点 及样品; 网站)
  : 模式基础(节点、设置{"我的模式";}) // [2]
  {
    // [3]
    手动控制输入 = 标准::共享<;px4_ros2::手动控制输入>(*);
    setpoint_速率 = 标准::共享<;px4_ros2::RatesSetpointType>(*);
  }

  空白 激活() 否决
  {
    // 每当我们的模式被选中时都会调用
  }

  空白 激活() 否决
  {
    // 当我们的模式被停用时调用
  }

  空白 更新设置点( rclcpp::持续时间 及样品; dt) 否决
  {
    // [4]
 本征::Vector3f thrust_sp{0.F, 0.F, -_manual_control_input->;扼杀()};
 本征::Vector3f rates_sp{
      _manual_control_input->;滚动() * 150.F * M_PI / 180.F,
      -_manual_control_input->;沥青() * 150.F * M_PI / 180.F,
      _manual_control_input->;打呵欠() * 100.F * M_PI / 180.F
    };
    _rates_setpoint->;更新(率_sp,推力_sp);
  }

私人
  标准::shared_ptr<;px4_ros2手动控制输入>; 手动控制输入;
  标准::shared_ptr<;px4_ros2::RatesSetpointType>; _rates_setpoint;
};
  • [1]:首先,我们创建一个继承自 px4_ros2::ModeBase.
  • [2]:在构造函数中,我们传递模式名称。这也允许我们配置其他一些东西,比如替换飞行控制器的内部模式。
  • [3]:在这里我们创建以后要使用的所有对象。可以是遥控输入、设定点类型或遥测。 *这 作为 背景 将对象与模式关联起来。
  • [4]:只要模式处于活动状态,该方法就会被定期调用(更新率取决于设定点类型)。我们可以在这里完成工作并生成新的设定点。

创建该模式的实例后、 mode->doRegister() 必须调用它来完成与飞行控制器的实际注册,并返回 错误 如果执行失败。如果使用模式执行器、 doRegister() 必须在模式执行器上调用,而不是为模式调用。

模式执行器类定义

本节将举例说明如何创建模式执行器类。

cpp
 我的模式执行器 :  px4_ros2::ModeExecutorBase // [1]
{
公众:
  我的模式执行器(rclcpp::节点 及样品; 网站, px4_ros2::模式基础 及样品; 自有模式) // [2]
  : ModeExecutorBase(节点)、 px4_ros2::ModeExecutorBase::Settings{}, owned_mode)、
    节点(节点)
  { }

  枚举 国家 // [3]
  {
    重置、
    起飞
    我的模式
    RTL、
    等待解除警报、
  };

  空白 激活() 否决
  {
    运行状态(国家::TakingOff、 px4_ros2::结果成功); // [4]
  }

  空白 激活(停用原因 理由) 否决 { }

  空白 运行状态(国家, px4_ros2::结果 上一个结果)
  {
    如果 (上一个结果 != px4_ros2::结果::Success) {
      RCLCPP_ERROR(_节点......)get_logger(), 国家 %i:上一状态失败: %s";, (int)状态、
        resultToString(previous_result));
      返回;
    }

    开关 (州){ // [5]
      个案 国家::Reset:
        断裂;

      个案 国家::TakingOff:
        起飞([](px4_ros2::结果 结果) {运行状态(国家::MyMode, result);});
        断裂;

      个案 国家::MyMode: // [6]
        时间表模式(
          拥有模式().本我(), [](px4_ros2::结果 结果) {
            运行状态(国家::RTL, result);
          });
        断裂;

      个案 国家RTL:
        rtl([](px4_ros2::结果 结果) {运行状态(国家::WaitUntilDisarmed, result);});
        断裂;

      个案 国家等待解除警报:
        等待解除警报([](px4_ros2::结果 结果) {
            RCLCPP_INFO(_节点......)get_logger(), "All states complete (%s)";, resultToString(结果));
          });
        断裂;
    }
  }

私人
  rclcpp节点 及样品; 节点;
};
  • [1]:首先,我们创建一个继承自 px4_ros2::ModeExecutorBase.
  • [2]:构造函数获取与执行器相关联的自定义模式,并将其传递给 ModeExecutorBase.
  • [3]:我们定义了一个枚举来表示我们要运行的状态。
  • [4]: 激活 会在执行器激活时被调用。此时,我们可以开始运行我们的状态。至于如何运行由你自己决定,在本例中,一个方法 运行状态 用于执行下一个状态。
  • [5]:在切换到一个状态时,我们从 ModeExecutorBase 启动所需的模式: 运行, 起飞, rtl等等。这些方法会传递一个函数,该函数会在完成时被调用;回调提供了一个 结果 参数会告诉你操作是否成功。成功时,回调将运行下一个状态。
  • [6]:我们使用 scheduleMode() 方法来启动执行器的自有模式,其模式与其他状态处理程序相同。

设定点类型

一个模式可以选择它想要用来控制载具的设定点类型。所使用的类型也决定了与不同载具类型的兼容性。

以下各节列出了支持的设定点类型:

TIP

其他设置点类型目前还处于试验阶段,可在以下页面找到: px4_ros2/control/setpoint_types/experimental.

您可以通过添加一个继承自 px4_ros2::SetpointBase,根据设定点的要求设置配置标志,然后发布任何包含设定点的主题。

目标设定点(GotoSetpointType)

信息

这种设定点类型目前只支持多旋翼飞行器。

使用该功能可平滑控制位置和(可选)航向设定点。 px4_ros2::GotoSetpointType 设定点类型。设定点类型被传输到基于 FMU 的位置和航向平滑器,该平滑器采用时间最优、最大跃迁轨迹,并带有速度和加速度约束。

最琐碎的用法就是简单地将 3D 位置输入到更新方法中:

cpp
 本征::Vector3f target_position_m{-10.F, 0.F, 3.F};
_gotoo_setpoint->;更新(target_position_m);

在这种情况下,标题将保持 失控.要额外控制标题,请将其指定为第二个输入参数:

cpp
 本征::Vector3f target_position_m{-10.F, 0.F, 3.F};
 浮动 航向_rad = 3.14F;
_gotoo_setpoint->;更新(
  target_position_m、
  heading_rad);

进入设置点的另一个特点是对基本平滑器的速度限制(即最大水平和垂直平移速度以及航向速率)进行动态控制。如上文所述,如果未指定,平滑器将默认为载具的默认最大值(通常设置为物理限制)。平滑器将 只是 降低限速,切勿提高限速。

cpp
_gotoo_setpoint->;更新(
  target_position_m、
  heading_rad、
  max_horizontal_velocity_m_s、
  max_vertical_velocity_m_s、
  max_heading_rate_rad_s);

更新方法中除位置外的所有参数都模板化为 std::optional<float>;也就是说,如果希望限制航向速率,而不是平移速度,可以使用 std::nullopt:

cpp
_gotoo_setpoint->;更新(
  target_position_m、
  heading_rad、
  标准::nullopt、
  标准::nullopt、
  max_heading_rate_rad_s);

直接执行器控制设定点(DirectActuatorsSetpointType)

可使用 px4_ros2::DirectActuatorsSetpointType 设定点类型。电机和舵机可以独立设置。请注意,分配是根据载具和设置而定的。例如,要控制一个四旋翼飞行器,您需要根据它的 输出配置.

信息

如果要控制一个不控制载具运动的执行器,例如有效载荷伺服器,请参见 低于.

控制独立的执行器/伺服器

如果要控制一个独立的执行器(伺服),请按照以下步骤操作:

  1. 配置输出
  2. 创建一个 px4_ros2::PeripheralActuatorControls 外设执行器控件 的构造函数中。
  3. 致电 设置() 方法来控制执行机构。这可以独立于任何活动设定点来完成。

遥测

您可以通过以下类别直接访问 PX4 遥测主题:

例如,您可以按如下方式查询载具的当前位置估计值:

cpp
标准::shared_ptr<;px4_ros2局部位置>; 载具本地位置;
...

// 获取载具最后的本地位置
_vehicle_local_position->;定位();

// 检查最后一个水平位置是否有效
_vehicle_local_position->;positionXYValid();

信息

这些主题为 PX4 内部主题提供了一个封装,允许库在内部主题发生变化时保持兼容性。检查 px4_ros2/odometry 新主题,当然也可以使用 PX4 发布的任何 ROS 2 主题。

故障保险和模式要求

每个模式都有一组需求标志。这些标志通常会自动设置,具体取决于在模式上下文中使用的对象。例如,当使用下面的代码添加手动控制输入时,手动控制的需求标志就会被设置:

cpp
手动控制输入 = 标准::共享<;px4_ros2::手动控制输入>(*);

具体来说,如果不满足条件,设置标志在 PX4 中会产生以下后果:

  • 在选择模式时不允许上膛
  • 如果已经上膛,则无法选择模式
  • 当上膛并选择模式时,将触发相关的故障安全保护(例如,手动控制要求的 RC 丢失)。检查 安全页 了解如何配置故障安全行为。选择模式时,如果模式崩溃或无响应,也会触发故障保护。

这是手动控制标志的相应流程图:

模式要求图

在注册模式后,可以手动更新任何模式要求。例如,添加原点位置作为要求:

cpp
模式要求().home_position =;

旗帜的完整列表见 requirement_flags.hpp.

推迟故障保险

模式或模式执行器可以通过调用 deferFailsafesSync().要在触发故障安全时获得通知,请重载方法 void onFailsafeDeferred().

检查 集成测试 为例。

为遥控开关或操纵杆动作指定模式

外部模式可分配给 RC 开关 或操纵杆操作。为 RC 开关分配模式时,需要知道索引(因为参数元数据不包含动态模式名称)。使用 指挥官身份 模式运行时获取该信息。

例如

平实
   INFO [指令长] 外部模式 1:Nav_state:23,名称:我的手动模式

意味着您将选择 外部模式 1 在 QGC 中:

QGC 模式分配

信息

PX4 通过存储模式名称的哈希值,确保给定模式始终分配给相同的索引。这样,在有多个外部模式的情况下,就不受启动顺序的影响。

更换内部模式

外部模式可以取代现有的内部模式,例如 返回 模式 (RTL)。这样,只要选择了 RTL(通过用户或故障安全情况),就会使用外部模式而不是内部模式。内部模式只在外部模式反应迟钝或崩溃时作为备用模式使用。

更换模式可以在 模式基础 构造函数:

cpp
设置{kName、 错误, 模式基础::kModeIDRtl}