跳至内容

PX4 ROS 2 导航界面

主页(PX4 v1.15) 实验性

实验性

在撰写本文档时,PX4 ROS 2 接口库的部分内容还处于试验阶段,因此可能会发生变化。

PX4 ROS 2 接口库 通过导航接口,开发人员可以直接从 ROS 2 应用程序(如 VIO 系统或地图匹配系统)向 PX4 发送位置测量数据。该接口为 PX4 和 uORB 消息传递框架提供了一个抽象层,并对通过接口发送的状态估计更新请求引入了一些正确性检查。然后,这些测量数据会被融合到 EKF 中,就像 PX4 内部测量数据一样。

图书馆提供两种课程、 本地位置测量接口全球位置测量接口它们都暴露了类似的 更新 方法,分别向 PX4 提供局部位置或全局位置更新。位置更新 更新 方法预期位置测量 结构 (本地位置测量全球位置测量),开发人员可以用自己生成的位置测量值填充这些数据。

安装和首次测试

开始操作需要以下步骤:

  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 ..
    胶管 构建
  4. 在另一个外壳中,启动 PX4 SITL:

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

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

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

    MicroXRCEAgent udp4 -p 8888
  6. 回到 ROS 2 终端,将刚刚创建的工作区作为源文件(在步骤 3 中),然后运行 全球导航 例如,它会定期发送虚假的全球位置更新:

    消息来源 install/setup.bash
    玫瑰2 运行 global_navigation_cpp 示例 全球导航示例

    您应该会得到这样的输出结果,显示全局接口已成功发送位置更新:

    [INFO] [1702030701.836897756] [example_global_navigation_node]: example_global_navigation_node 正在运行!
    [DEBUG] [1702030702.837279784] [example_global_navigation_node]: 成功 发送 位置 更新 导航 接口。
    [DEBUG] [1702030703.837223884] [example_global_navigation_node]:成功向导航界面发送位置更新。
  7. 在 PX4 外壳中,可以检查 PX4 是否接收全局位置更新:

    听众 辅助全球位置

    输出结果应该是这样的

    主题: 辅助全球位置
    辅助全球位置
       时间戳: 46916000 (0.528000 秒钟)
       timestamp_sample: 46916000 (0 我们 之前 时戳)
       纬度 12.343210
     23.454320
       备选案文 12.40000
       椭圆体 0.00000
       delta_alt: 0.00000
       以弗所书 0.31623
       epv: 0.44721
       terrain_alt: 0.00000
       lat_lon_reset_counter: 0
       alt_reset_counter: 0
       terrain_alt_valid: 假的
       dead_reckoning: 假的
  8. 现在,您可以使用导航界面发送自己的位置更新信息了。

如何使用图书馆

要发送位置测量结果,需要用测量值填充 position 结构。然后以该结构作为参数调用接口的更新函数。

有关如何使用该界面的基本示例,请查看 例子Auterion/px4-ros2-interface-lib 存储库,如 examples/cpp/navigation/local_navigationexamples/cpp/navigation/global_navigation.

本地定位(POSITION)更新

首先确保 PX4 参数 EKF2_EV_CTRL 通过将相应的位设置为 :

  • 0:水平位置数据
  • 1:垂直位置数据
  • 2:速度数据
  • 3:偏航数据

向 PX4 发送本地位置测量值:

  1. 创建一个 本地位置测量接口 实例,为其提供:一个 ROS 节点,以及测量的姿态和速度参考帧。
  2. 填充一个 本地位置测量 结构 测量值。
  3. 通过 结构本地位置测量接口 更新() 方法。

用于测量的可用姿态和速度参考帧定义如下 枚举:

cpp
枚举 PoseFrame
{
  未知,
  当地 NED,
  本地FRD
};

枚举 速度框架
{
  未知,
  当地 NED,
  本地FRD,
  身体FRD
};

本地位置测量 结构定义如下

cpp
结构 本地位置测量
{
   rclcpp::Time timestamp_sample {};

   标准::optional<;本征::Vector2f>; position_xy {标准::nullopt};
   标准::optional<;本征::Vector2f>; 位置偏差 {标准::nullopt};
   标准::optional<float>; position_z {标准::nullopt};
   标准::optional<float>; 位置 Z 变量 {标准::nullopt};

   标准::optional<;本征::Vector2f>; velocity_xy {标准::nullopt};
   标准::optional<;本征::Vector2f>; 速度_x_方差 {标准::nullopt};
   标准::optional<float>; velocity_z {标准::nullopt};
   标准::optional<float>; 速度 Z 方差 {标准::nullopt};

   标准::optional<;本征四元数f>; 姿态四元数 {标准::nullopt};
   标准::optional<;本征::Vector3f>; 态度变量 {标准::nullopt};
};

更新() 本地接口的方法需要满足以下条件 本地位置测量:

  • 定义了样本时间戳。
  • 值没有 "NAN"。
  • 如果提供了测量值,其相关的方差值就会得到很好的定义(例如,如果 位置位置偏差 必须定义)。
  • 如果提供了测量值,其相关参考框架并非未知(例如,如果 位置 定义,则界面初始化时的姿态帧与 PoseFrame::Unknown).

下面的代码片段是一个 ROS 2 节点的示例,该节点使用本地导航接口向 PX4 发送北-东-下(NED)参照系中的 3D 姿态更新:

cpp
 我的本地测量更新节点 :  rclcpp::节点
{
公众:
   我的本地测量更新节点()
   : 节点("my_node_name";)
   {
      // 将姿势测量参考框架设置为东北-下
 px4_ros2::PoseFrame pose_frame = px4_ros2::PoseFrame::LocalNED;
      // 本例中我们只发送姿势测量值
      // 将速度测量参考帧设置为未知
 px4_ros2::VelocityFrame velocity_frame = px4_ros2::速度框架未知;
      // 初始化本地接口 [1]
      本地位置测量接口 =
         标准::共享<;px4_ros2::本地位置测量接口>(*,pose_frame,velocity_frame);
   }

   空白 发送更新()
   {
      虽然 (运行中) { // 有可能使方法作为回调运行或在定时器上运行
         // 生成本地位置测量值
         rclcpp::Time timestamp_sample  = ...
         本征::Vector2f position_xy = ...
         本征::Vector2f position_xy_variance = ...
         浮动 位置_z = ...
         浮动 位置 Z 变量 = ...

         // 填充本地位置测量结构 [2]
         px4_ros2::LocalPositionMeasurement local_position_measurement{};
         本地位置测量时间戳样本 = timestamp_sample;
         本地位置测量.position_xy = position_xy;
         本地位置测量.位置氧方差 = position_xy_variance;
         本地位置测量.position_z = position_z;
         本地位置测量.位置 Z 方差 = position_z_variance;

         // 使用接口 [3] 将测量结果发送到 PX4
         尝试 {
            _local_position_measurement_interface->;更新(本地位置测量);
         } 捕捉 ( px4_ros2导航接口无效参数 及样品; e) {
            // 处理因本地位置测量定义无效而导致的异常
            RCLCPP_ERROR(get_logger(), "异常捕获: %s";, e.什么());
         }
      }
   }

私人
   标准::shared_ptr<;px4_ros2::LocalPositionMeasurementInterface 本地位置测量接口>; 本地位置测量接口;
};

全球位置更新

首先确保 PX4 参数 EKF2_AGP_CTRL 通过将相应位设置为 :

  • 0:水平位置数据
  • 1:垂直位置数据

向 PX4 发送全局位置测量值:

  1. 创建一个 全球位置测量接口 实例,为其提供一个 ROS 节点。
  2. 填充一个 全球位置测量 结构 测量值。
  3. 将结构体传递给 全球位置测量接口 更新() 方法。

全球位置测量 结构定义如下

cpp
结构 全球位置测量
{
   rclcpp::Time timestamp_sample {};

   标准::optional<;本征::Vector2d>; lat_lon {标准::nullopt};
   标准::optional<float>; 水平方差 {标准::nullopt};

   标准::optional<float>; 海拔高度标准::nullopt};
   标准::optional<float>; 垂直方差 {标准::nullopt};
};

更新() 全局接口的方法希望以下条件成立 全球位置测量:

  • 样本 时间戳样本 的定义。
  • 数值没有 NAN。
  • 如果提供了测量值,其相关的方差值就会得到很好的定义(例如,如果 lat_lon水平方差 必须定义)。

下面的代码片段是一个 ROS 2 节点的示例,它使用全局导航接口向 PX4 发送包含经度、纬度和高度的测量数据:

cpp
 我的全球测量更新节点 :  rclcpp::节点
{
公众:
   我的全球测量更新节点()
   : 节点("my_node_name";)
   {
      // 初始化全局接口 [1]
      全球位置测量接口 =
         标准::共享<;px4_ros2::全球位置测量接口>(*);
   }

   空白 发送更新()
   {
      虽然 (运行中) { // 有可能使方法作为回调运行或在定时器上运行
         // 生成全球位置测量值
         rclcpp::Time timestamp_sample  = ...
         本征::Vector2d lat_lon = ...
         浮动 水平方差 = ...
         浮动 海拔高度 = ...
         浮动 垂直方差 = ...

         // 填充全球位置测量结构 [2]
         px4_ros2全球位置测量 global_position_measurement{};
         全球定位测量时间戳样本 = timestamp_sample;
         global_position_measurement.lat_lon = lat_lon;
         全局位置测量水平方差 = 水平方差;
         global_position_measurement.altitude_msl = 海拔高度
         全球位置测量垂直方差 = 垂直方差;

         // 使用接口 [3] 将测量结果发送到 PX4
         尝试 {
            _global_position_measurement_interface->;更新(全球位置测量);
         } 捕捉 ( px4_ros2导航接口无效参数 及样品; e) {
            // 处理因 global_position_measurement 定义无效而导致的异常
            RCLCPP_ERROR(get_logger(), "异常捕获: %s";, e.什么());
         }
      }
   }

私人
   标准::shared_ptr<;px4_ros2全球位置测量接口>; 全球位置测量接口;
};

接口的多个实例

使用同一接口的多个实例(如本地接口和本地接口)发送估算更新,会将所有更新信息流传到同一主题,从而导致串扰。这应该不会影响 EKF 的测量融合,但不同的测量源将变得难以区分。