三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

XTDrone2配置的一些问题

XTDrone2配置的一些问题

本人基于XTDrone2的基础上写了一个项目代码如下:

Px4_Servo_Force-controlled_Throwing/
├── build.sh # 首次编译(新电脑只需运行一次)
├── sim.sh # 终端1:启动仿真
├── fly.sh # 终端2:键盘控制
├── config/
│ ├── cyclonedds.xml # DDS 网络配置
│ ├── px4-rc.params # PX4 参数(免GPS、禁止预解锁超时等)
│ └── ros_log_config.yaml # 日志配置
├── xtd2_ws/
│ └── src/ # 所有 XTDrone2 源码包
│ ├── px4_msgs/
│ ├── xtd2_communication/
│ ├── xtd2_control/
│ ├── xtd2_gz_sim/
│ ├── xtd2_launch/
│ ├── xtd2_msgs/
│ ├── xtd2_test/
│ ├── xtd2_third_party_pkgs/
│ └── xtdrone2/
└── ...(你原有的文件不变)

---

换到新电脑后:
cd ~/Px4_Servo_Force-controlled_Throwing
./build.sh # 首次:编译工作区 + 安装 PX4 参数

每次飞行:
- 终端1:./sim.sh
- 终端2:./fly.sh

所有环境变量、DDS 配置、日志抑制都已内置在脚本里,一行命令搞定。本机也可以直接测试。

但是遇到了一些问题:

## PX4 v1.15.3 → v1.17.0 升级 & 磁力计问题修复记录

### 日期:2026-08-10

### 一、PX4 版本升级

```bash
cd ~/PX4-Autopilot
git fetch --tags
# 修复 Gitee 子模块 fetch 失败
git checkout tags/v1.17.0 -- .gitmodules
git submodule sync
git submodule update --init --recursive
# 保存本地修改后切换版本
git stash push -m "save local changes before switching to v1.17.0"
git checkout tags/v1.17.0
```

### 二、更新项目模型 SDF 文件

将 PX4 v1.17.0 的模型文件复制到项目,使模型包含新版传感器定义(特别是 magnetometer_sensor):

```bash
cp ~/PX4-Autopilot/Tools/simulation/gz/models/x500_base/model.sdf \
xtd2_ws/src/xtd2_gz_sim/models/x500_base/model.sdf
cp ~/PX4-Autopilot/Tools/simulation/gz/models/x500/model.sdf \
xtd2_ws/src/xtd2_gz_sim/models/x500/model.sdf
cp ~/PX4-Autopilot/Tools/simulation/gz/worlds/aruco.sdf \
xtd2_ws/src/xtd2_gz_sim/worlds/aruco.sdf
```

### 三、清理旧参数,触发 AUTOCNF 重新初始化

v1.15.3 的 parameters.bson 中磁力计校准数据与 v1.17.0 的设备 ID 不兼容,必须清除:

```bash
rm -rf ~/PX4-Autopilot/build/px4_sitl_default/
cd ~/PX4-Autopilot
make px4_sitl gz_x500 # 重建,AUTOCNF 自动设置 CAL_MAG0_ID=197388
```

### 四、修复 sim.sh 启动时的 compass 报错

问题:`make px4_sitl gz_x500` 直接运行正常,但通过 `./sim.sh` 启动报 `Found 0 compass`。

#### 根因 1:px4_launch.py 缺少 PX4 路径环境变量

**文件**:`xtd2_ws/src/xtd2_launch/xtd2_launch/utils/px4_launch.py`

在 standalone 模式下,PX4 的 rcS 不 source gz_env.sh,导致 PX4_GZ_MODELS 和 PX4_GZ_WORLDS 为空,模型 spawn 路径错误。同时 PX4_PARAM_* 环境变量用于替代旧版 px4-rc.params 文件(v1.17.0 rcS 不再 source 该文件)。

**修改**:在 px4_cmd 前增加:
```python
px4_params = (
"PX4_PARAM_COM_ARM_WO_GPS=1 " # 室内无 GPS 允许解锁
"PX4_PARAM_COM_DISARM_PRFLT=0 " # 禁用 SITL 时间跳变自动上锁
"PX4_PARAM_UXRCE_DDS_PTCFG=1 " # UXRCE-DDS 仅本地通信
"PX4_PARAM_CBRK_SUPPLY_CHK=894281 " # 跳过电源模块检查(SITL 无此硬件)
)
px4_gz_models = f"{args.px4_dir}/Tools/simulation/gz/models"
px4_gz_worlds = f"{args.px4_dir}/Tools/simulation/gz/worlds"
```

并在 px4_cmd 中加入:
```
PX4_GZ_MODELS={px4_gz_models} PX4_GZ_WORLDS={px4_gz_worlds}
GZ_SIM_RESOURCE_PATH=$GZ_SIM_RESOURCE_PATH:{px4_gz_models}:{px4_gz_worlds}
{px4_params}PX4_GZ_STANDALONE=1
```

以上的操作都没有解决最主要的问题“ 四、修复 sim.sh 启动时的 compass 报错。”

最后的解决办法是:

#### 根因 2:Gazebo 缺少 Magnetometer 系统插件

**文件**:`xtd2_ws/src/xtd2_gz_sim/worlds/aruco.sdf`

项目 aruco.sdf 有显式插件列表(23 个),Gazebo 遇到显式插件列表时会忽略 server.config,只加载 SDF 中列出的插件。但列表中缺失了 `gz-sim-magnetometer-system`,导致磁力计传感器虽在模型 SDF 中定义了,但永远不产生数据。

**修改**:在 `<plugin name="gz::sim::systems::Sensors" ...>` 之后添加:
```xml
<plugin name="gz::sim::systems::Magnetometer" filename="gz-sim-magnetometer-system"/>
<plugin name="gz::sim::systems::AirSpeed" filename="gz-sim-air-speed-system"/>
```

#### 根因 3:gz_launch.py 覆盖 GZ_SIM_RESOURCE_PATH

**文件**:`xtd2_ws/src/xtd2_launch/launch/gz_launch.py`

原代码用 `SetEnvironmentVariable` 直接覆盖 GZ_SIM_RESOURCE_PATH,导致 sim.sh 中预设的 PX4 路径被清除。

**修改**:
- 添加 `import os`
- 将 `SetEnvironmentVariable('GZ_SIM_RESOURCE_PATH', gz_model_path)` 改为追加模式

#### 根因 4:sim.sh 未设置 Gazebo 服务器配置路径

**文件**:`sim.sh`

添加:
```bash
export GZ_SIM_SERVER_CONFIG_PATH="$HOME/PX4-Autopilot/src/modules/simulation/gz_bridge/server.config"
export GZ_SIM_RESOURCE_PATH="${GZ_SIM_RESOURCE_PATH:+${GZ_SIM_RESOURCE_PATH}:}$HOME/PX4-Autopilot/Tools/simulation/gz/models:$HOME/PX4-Autopilot/Tools/simulation/gz/worlds"
```

#### sim.sh 额外改进:启动前清理残留进程

```bash
pkill -f "px4_sitl_default/bin/px4" 2>/dev/null || true
pkill -f "MicroXRCEAgent" 2>/dev/null || true
pkill -f "ros2 launch.*xtd2" 2>/dev/null || true
pkill -f "ros_gz_bridge.*x500" 2>/dev/null || true
pkill -f "gz sim.*aruco" 2>/dev/null || true
```

### 五、修改文件汇总

| 文件 | 改动说明 |
|------|----------|
| `sim.sh` | 新增残留进程清理 + GZ_SIM_SERVER_CONFIG_PATH + GZ_SIM_RESOURCE_PATH |
| `config/px4-rc.params` | v1.17.0 不再使用此文件(参数改用 PX4_PARAM_* 环境变量) |
| `xtd2_ws/src/xtd2_launch/xtd2_launch/utils/px4_launch.py` | 新增 PX4_GZ_MODELS/WORLDS + GZ_SIM_RESOURCE_PATH + PX4_PARAM_* 参数 |
| `xtd2_ws/src/xtd2_launch/launch/gz_launch.py` | GZ_SIM_RESOURCE_PATH 从覆盖改为追加 + import os |
| `xtd2_ws/src/xtd2_gz_sim/worlds/aruco.sdf` | 新增 Magnetometer + AirSpeed 系统插件 |
| `xtd2_ws/src/xtd2_gz_sim/models/x500_base/model.sdf` | 替换为 PX4 v1.17.0 版本(含 magnetometer_sensor) |
| `xtd2_ws/src/xtd2_gz_sim/models/x500/model.sdf` | 替换为 PX4 v1.17.0 版本 |
| `~/PX4-Autopilot/build/px4_sitl_default/` | 删除后重建(清除旧 parameters.bson) |

### 六、关键技术要点

1. **PX4 v1.17.0 rcS 不再 source px4-rc.params**,参数必须通过 `PX4_PARAM_<参数名>=<值>` 环境变量传入。
2. **AUTOCNF** 机制:首次启动时自动设置 CAL_MAG0_ID=197388(对应 gz_bridge 设备 ID),后续启动检测到 SYS_AUTOSTART 匹配则跳过。
3. **Gazebo 插件加载规则**:世界 SDF 有显式 `<plugin>` 列表时,server.config 被忽略,只加载 SDF 中列出的插件。
4. **PX4 standalone 模式**(PX4_GZ_STANDALONE=1):PX4 不启动 Gazebo,而是等待外部 Gazebo 就绪后 spawn 模型并启动 gz_bridge。此模式下 rcS 不 source gz_env.sh。
5. **gz_bridge 设备 ID 编码**:bus_type=SIMULATION, devtype=MAGSIM, bus=1, address=3 → 197388。

可以根据以上这些内容提示输入给AI进行问题解决!

后来进行室外飞行时又遇到一个问题:“气压计读数没有”
EKF2_HGT_MODE,的值为Ranger sensor

Thought for 7s (ctrl+o to expand)

● 找到根因了。EKF2_HGT_MODE = Ranger sensor(测距仪) 就是问题所在——EKF 被配置成用测距仪做高度源,而你的 x500 大概率没接/没配置测距仪,所以高度永远融不出来 →
alt_valid=false。气压计本身没问题(读数正常),只是 EKF 没在用气压计。

修复步骤

1. QGC → Vehicle Setup(齿轮) → Parameters
2. 搜 EKF2_HGT_MODE
3. 改成 0 = Barometric pressure(气压计)
4. 点 Write / 写入 保存
5. 重启飞控(这个参数需要重启才生效)
6. 静置等 30~60s
7. 复查:

export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
source /opt/ros/jazzy/setup.bash
source ~/Px4_Servo_Force-controlled_Throwing/xtd2_ws/install/setup.bash
ros2 topic echo /uav_0/fmu/out/vehicle_global_position --once --no-daemon --spin-time 5 --qos-reliability best_effort 2>/dev/null | grep -E
'lat_lon_valid|alt_valid|reset_counter'

alt_valid: true 之后,键盘 t 解锁就能过 AUTO_LOITER 的 global position 检查了。

---
顺带说明为什么 QGC 能解锁、键盘不能:
- QGC 在 MANUAL/STAB 解锁,不要求高度;
- 键盘强制切 AUTO_LOITER,要求 global_position(lat_lon + alt 都有效)。

现在高度源改回气压计就对齐了

← 返回列表