|
|
|
|
|
# GUI Set Mode 功能 - 快速參考
|
|
|
|
|
|
|
|
|
|
|
|
## 📍 在 GUI 中使用 Set Mode 的最快方式
|
|
|
|
|
|
|
|
|
|
|
|
### 現有代碼(無需修改)
|
|
|
|
|
|
|
|
|
|
|
|
gui.py 中已經在使用 set_mode 功能:
|
|
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
|
def handle_mode_change(self, drone_id):
|
|
|
|
|
|
"""單個無人機模式切換"""
|
|
|
|
|
|
mode = panel.mode_combo.currentText() # 從下拉列表獲取模式
|
|
|
|
|
|
future = self.monitor.set_mode(drone_id, mode)
|
|
|
|
|
|
loop.create_task(self.handle_service_response(future, ...))
|
|
|
|
|
|
|
|
|
|
|
|
def _handle_group_mode_change(self, group_id, mode):
|
|
|
|
|
|
"""群組模式切換"""
|
|
|
|
|
|
for drone_id in group.drone_ids:
|
|
|
|
|
|
future = self.monitor.set_mode(drone_id, mode)
|
|
|
|
|
|
loop.create_task(self.handle_service_response(future, ...))
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 實現位置
|
|
|
|
|
|
|
|
|
|
|
|
- **核心實現**:[`communication.py`](communication.py#L585-L685)
|
|
|
|
|
|
- `DroneMonitor.MODE_MAPPING` - 模式映射表
|
|
|
|
|
|
- `DroneMonitor.set_mode()` - 非同步方法
|
|
|
|
|
|
|
|
|
|
|
|
- **使用位置**:[`gui.py`](gui.py#L391-L401)
|
|
|
|
|
|
- `handle_mode_change()` - 單個無人機
|
|
|
|
|
|
- `_handle_group_mode_change()` - 群組無人機
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🎮 模式支援列表
|
|
|
|
|
|
|
|
|
|
|
|
| 模式名稱 | custom_mode | 備註 |
|
|
|
|
|
|
|---------|-----------|------|
|
|
|
|
|
|
| STABILIZE | 0 | 自穩定 |
|
|
|
|
|
|
| ACRO | 1 | 特技 |
|
|
|
|
|
|
| ALT_HOLD | 2 | 保持高度 |
|
|
|
|
|
|
| AUTO | 3 | 自動任務 |
|
|
|
|
|
|
| GUIDED | 4 | 引導(常用) |
|
|
|
|
|
|
| LOITER | 5 | 盤旋 |
|
|
|
|
|
|
| RTL | 6 | 返回起點 |
|
|
|
|
|
|
| CIRCLE | 7 | 圓形飛行 |
|
|
|
|
|
|
| POSITION | 8 | 位置保持 |
|
|
|
|
|
|
| LAND | 9 | 著陸 |
|
|
|
|
|
|
| SMART_RTL | 21 | 智能返回 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🔧 API 參考
|
|
|
|
|
|
|
|
|
|
|
|
### DroneMonitor.set_mode()
|
|
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
|
async def set_mode(self, drone_id, mode_name) -> bool:
|
|
|
|
|
|
"""
|
|
|
|
|
|
改變無人機飛行模式
|
|
|
|
|
|
|
|
|
|
|
|
參數:
|
|
|
|
|
|
drone_id: str - 無人機ID (如: "s0_1", "s1_11")
|
|
|
|
|
|
mode_name: str - 模式名稱 (如: "GUIDED", "AUTO")
|
|
|
|
|
|
|
|
|
|
|
|
返回:
|
|
|
|
|
|
bool - 成功返回 True,失敗返回 False
|
|
|
|
|
|
"""
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 使用示例
|
|
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
|
# 單個無人機
|
|
|
|
|
|
success = await self.monitor.set_mode("s0_1", "GUIDED")
|
|
|
|
|
|
|
|
|
|
|
|
# 或在 asyncio 中
|
|
|
|
|
|
loop = asyncio.get_event_loop()
|
|
|
|
|
|
future = self.monitor.set_mode("s0_1", "GUIDED")
|
|
|
|
|
|
loop.create_task(handle_result(future))
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 📂 相關文件
|
|
|
|
|
|
|
|
|
|
|
|
### 文檔
|
|
|
|
|
|
- [`IMPLEMENTATION_SUMMARY.md`](IMPLEMENTATION_SUMMARY.md) - 完整實現總結
|
|
|
|
|
|
- [`SET_MODE_INTEGRATION.md`](SET_MODE_INTEGRATION.md) - 詳細集成指南
|
|
|
|
|
|
- [`example_set_mode_usage.py`](example_set_mode_usage.py) - 使用示例和文檔
|
|
|
|
|
|
- 此文件:`README_SET_MODE.md` - 快速參考
|
|
|
|
|
|
|
|
|
|
|
|
### 代碼
|
|
|
|
|
|
- [`communication.py`](communication.py) - DroneMonitor 實現 (L585-L685)
|
|
|
|
|
|
- [`gui.py`](gui.py) - GUI 中的使用 (L391-L401, L656-L664)
|
|
|
|
|
|
- [`demo_set_mode.py`](demo_set_mode.py) - 可執行的演示腳本
|
|
|
|
|
|
|
|
|
|
|
|
### 原始模塊
|
|
|
|
|
|
- `fc_network_apps/changeMode.py` - change_mode() 函數
|
|
|
|
|
|
- `fc_network_apps/__init__.py` - 模塊導出
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🚀 快速開始
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 檢查實現
|
|
|
|
|
|
|
|
|
|
|
|
查看 communication.py 中的 MODE_MAPPING 和 set_mode() 方法是否存在:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
grep -n "MODE_MAPPING\|async def set_mode" GUI/communication.py
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
✓ 應該能看到相關代碼
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 驗證 fc_network_apps 可用
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
python3 -c "from fc_network_apps import change_mode; print('OK')"
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
✓ 輸出 "OK" 表示模塊可用
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 在 GUI 中使用
|
|
|
|
|
|
|
|
|
|
|
|
直接點擊 GUI 中的模式選擇器和「切換」按鈕即可。
|
|
|
|
|
|
|
|
|
|
|
|
### 4. 查看日誌
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 在 GUI 終端查看日誌輸出
|
|
|
|
|
|
# [INFO]: Changing mode for drone s0_1 to GUIDED (custom_mode=4)
|
|
|
|
|
|
# [INFO]: Mode change successful for s0_1: Success
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🐛 常見問題
|
|
|
|
|
|
|
|
|
|
|
|
### Q1: 模式切換失敗
|
|
|
|
|
|
**A:** 檢查以下事項:
|
|
|
|
|
|
- ✓ 無人機是否已連接到 fc_network
|
|
|
|
|
|
- ✓ 模式名稱是否正確(區分大小寫)
|
|
|
|
|
|
- ✓ drone_id 格式是否正確 (格式:`s{socket_id}_{sysid}`)
|
|
|
|
|
|
- ✓ 查看 ROS2 日誌了解詳細錯誤信息
|
|
|
|
|
|
|
|
|
|
|
|
### Q2: "Unknown mode" 錯誤
|
|
|
|
|
|
**A:**
|
|
|
|
|
|
- 檢查模式名稱的大小寫
|
|
|
|
|
|
- 確保模式在 MODE_MAPPING 中
|
|
|
|
|
|
- 參考上面的 "模式支援列表"
|
|
|
|
|
|
|
|
|
|
|
|
### Q3: "fc_network_apps is not available" 錯誤
|
|
|
|
|
|
**A:**
|
|
|
|
|
|
- 確保在 ROS2 workspace 中安裝了 fc_network_apps
|
|
|
|
|
|
- 運行 `colcon build --packages-select fc_network_apps`
|
|
|
|
|
|
- 重新 source setup 文件
|
|
|
|
|
|
|
|
|
|
|
|
### Q4: Service call timeout
|
|
|
|
|
|
**A:**
|
|
|
|
|
|
- 檢查 fc_network 節點是否運行
|
|
|
|
|
|
- 檢查無人機連接狀態
|
|
|
|
|
|
- 增加 timeout 值(在 set_mode() 中修改)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 💡 設計要點
|
|
|
|
|
|
|
|
|
|
|
|
### 為什麼使用 fc_network_apps.change_mode()?
|
|
|
|
|
|
|
|
|
|
|
|
✅ **優點**:
|
|
|
|
|
|
- 經過驗證的 MAVLink 實現
|
|
|
|
|
|
- 統一的 ROS2 service interface
|
|
|
|
|
|
- 自動錯誤處理
|
|
|
|
|
|
- 支持多個無人機系統
|
|
|
|
|
|
|
|
|
|
|
|
❌ **直接使用 MAVLink 的缺點**:
|
|
|
|
|
|
- 需要管理連接
|
|
|
|
|
|
- 錯誤處理複雜
|
|
|
|
|
|
- 與 fc_network 架構不一致
|
|
|
|
|
|
|
|
|
|
|
|
### drone_id 格式設計
|
|
|
|
|
|
|
|
|
|
|
|
`s{socket_id}_{sysid}` 的含義:
|
|
|
|
|
|
- `s` - 前綴,表示 socket 連接
|
|
|
|
|
|
- `socket_id` - 連接序號(0, 1, 2...)
|
|
|
|
|
|
- `_` - 分隔符
|
|
|
|
|
|
- `sysid` - MAVLink system ID
|
|
|
|
|
|
|
|
|
|
|
|
例如 `s0_1`:
|
|
|
|
|
|
- socket_id = 0(第一個連接)
|
|
|
|
|
|
- sysid = 1(該連接上的第一個無人機)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 📊 流程圖
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
GUI 用戶界面
|
|
|
|
|
|
│
|
|
|
|
|
|
├─ 單無人機流程 ─────────────────────────┐
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ 1. 選擇模式 │
|
|
|
|
|
|
│ 2. 點擊「切換」 │
|
|
|
|
|
|
│ 3. handle_mode_change(drone_id) │
|
|
|
|
|
|
│ 4. monitor.set_mode(drone_id, mode) │
|
|
|
|
|
|
│ 5. change_mode(sysid, custom_mode) │
|
|
|
|
|
|
│ 6. ROS2 service call │
|
|
|
|
|
|
│ 7. 無人機執行模式切換 │
|
|
|
|
|
|
│ 8. 返回結果並更新 UI │
|
|
|
|
|
|
│ │
|
|
|
|
|
|
└─────────────────────────────────────────┘
|
|
|
|
|
|
|
|
|
|
|
|
├─ 群組流程 ────────────────────────────┐
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ 1. 為群組選擇模式 │
|
|
|
|
|
|
│ 2. 點擊群組「切換」 │
|
|
|
|
|
|
│ 3. _handle_group_mode_change() │
|
|
|
|
|
|
│ 4. For each drone_id in group: │
|
|
|
|
|
|
│ monitor.set_mode(drone_id, mode) │
|
|
|
|
|
|
│ 5. 並行發送多個 ROS2 service calls │
|
|
|
|
|
|
│ 6. 所有無人機執行模式切換 │
|
|
|
|
|
|
│ 7. 返回結果並更新 UI │
|
|
|
|
|
|
│ │
|
|
|
|
|
|
└────────────────────────────────────────┘
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🔗 相關資源
|
|
|
|
|
|
|
|
|
|
|
|
- **ArduCopter 模式文檔**: https://ardupilot.org/copter/docs/flight-modes.html
|
|
|
|
|
|
- **MAVLink 文檔**: https://mavlink.io/en/
|
|
|
|
|
|
- **fc_network_adapter**: 本項目中的 `fc_network_adapter/` 目錄
|
|
|
|
|
|
- **fc_network_apps**: 本項目中的 `fc_network_apps/` 目錄
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 📌 重要提示
|
|
|
|
|
|
|
|
|
|
|
|
1. **模式名稱必須大寫**
|
|
|
|
|
|
- `"GUIDED"` ✅
|
|
|
|
|
|
- `"guided"` ❌
|
|
|
|
|
|
|
|
|
|
|
|
2. **drone_id 格式固定**
|
|
|
|
|
|
- 必須包含 `_` 分隔符
|
|
|
|
|
|
- `"s0_1"` ✅
|
|
|
|
|
|
- `"s01"` ❌
|
|
|
|
|
|
|
|
|
|
|
|
3. **async/await 模式**
|
|
|
|
|
|
- `set_mode()` 是 async 函數
|
|
|
|
|
|
- 必須通過 `await` 或 asyncio 調用
|
|
|
|
|
|
|
|
|
|
|
|
4. **超時設定**
|
|
|
|
|
|
- 預設 2.0 秒
|
|
|
|
|
|
- 無響應時返回 False
|
|
|
|
|
|
|
|
|
|
|
|
5. **日誌記錄**
|
|
|
|
|
|
- 所有操作都記錄在 ROS2 日誌中
|
|
|
|
|
|
- 便於調試和監控
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
**最後更新**: 2026年4月7日
|
|
|
|
|
|
**版本**: 1.0
|
|
|
|
|
|
**作者**: GUI 團隊
|