|
|
|
|
@ -1,405 +0,0 @@
|
|
|
|
|
===============================================================================================
|
|
|
|
|
GUI 集成 fc_network Set Mode 功能 - 完整修改清單
|
|
|
|
|
===============================================================================================
|
|
|
|
|
|
|
|
|
|
項目名稱: AirTrapMine
|
|
|
|
|
目標: 在 gui.py 中使用 fc_network_apps 的 change_mode 功能改變無人機飛行模式
|
|
|
|
|
完成日期: 2026年4月7日
|
|
|
|
|
|
|
|
|
|
===============================================================================================
|
|
|
|
|
1. 修改的檔案
|
|
|
|
|
===============================================================================================
|
|
|
|
|
|
|
|
|
|
【1】communication.py - 新增 set_mode 功能
|
|
|
|
|
────────────────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
位置: /home/dodo/Downloads/AirTrapMine/src/GUI/communication.py
|
|
|
|
|
|
|
|
|
|
修改內容:
|
|
|
|
|
|
|
|
|
|
A) 新增導入 (L18-22):
|
|
|
|
|
- 從 fc_network_apps 導入 change_mode 函數
|
|
|
|
|
- 使用 try-except 安全導入,以支持 fc_network_apps 未安裝的情況
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
try:
|
|
|
|
|
from fc_network_apps import change_mode
|
|
|
|
|
except ImportError:
|
|
|
|
|
change_mode = None
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
B) 新增 MODE_MAPPING 常量 (L585-610):
|
|
|
|
|
- 將飛行模式名稱映射到 custom_mode 值
|
|
|
|
|
- 基於 ArduCopter 模式定義
|
|
|
|
|
- 包含 20+ 種常用模式
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
MODE_MAPPING = {
|
|
|
|
|
"STABILIZE": 0,
|
|
|
|
|
"GUIDED": 4,
|
|
|
|
|
# ... 更多模式
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
C) 新增 set_mode() 非同步方法 (L612-685):
|
|
|
|
|
- 使用 fc_network_apps 的 change_mode() 函數
|
|
|
|
|
- 解析 drone_id 以提取 sysid
|
|
|
|
|
- 查表轉換模式名稱到 custom_mode 值
|
|
|
|
|
- 呼叫 ROS2 service 改變模式
|
|
|
|
|
- 完整的錯誤處理和日誌記錄
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
async def set_mode(self, drone_id, mode_name):
|
|
|
|
|
"""使用 fc_network_apps 的 change_mode 函數切換無人機飛行模式"""
|
|
|
|
|
# 實現細節...
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
修改影響:
|
|
|
|
|
✅ 無需修改 gui.py 中的使用代碼
|
|
|
|
|
✅ 自動與現有的 handle_mode_change() 和 _handle_group_mode_change() 配合
|
|
|
|
|
✅ 完全向後相容
|
|
|
|
|
|
|
|
|
|
===============================================================================================
|
|
|
|
|
2. 新增的文件
|
|
|
|
|
===============================================================================================
|
|
|
|
|
|
|
|
|
|
【2】example_set_mode_usage.py - 使用示例和詳細文檔
|
|
|
|
|
────────────────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
位置: /home/dodo/Downloads/AirTrapMine/src/GUI/example_set_mode_usage.py
|
|
|
|
|
|
|
|
|
|
內容:
|
|
|
|
|
- 詳細的實現說明和原理解釋
|
|
|
|
|
- API 文檔和參數說明
|
|
|
|
|
- 使用流程圖
|
|
|
|
|
- fc_network_apps 集成細節
|
|
|
|
|
- 支援的飛行模式列表
|
|
|
|
|
- 錯誤處理方案
|
|
|
|
|
- 完整的代碼示例
|
|
|
|
|
- 注意事項
|
|
|
|
|
|
|
|
|
|
大小: ~500 行
|
|
|
|
|
|
|
|
|
|
【3】demo_set_mode.py - 可執行的演示腳本
|
|
|
|
|
────────────────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
位置: /home/dodo/Downloads/AirTrapMine/src/GUI/demo_set_mode.py
|
|
|
|
|
|
|
|
|
|
功能:
|
|
|
|
|
$ python3 demo_set_mode.py direct --sysid 1 --mode GUIDED
|
|
|
|
|
→ 直接使用 fc_network_apps.change_mode()
|
|
|
|
|
|
|
|
|
|
$ python3 demo_set_mode.py via-monitor --drone-id s0_1 --mode AUTO
|
|
|
|
|
→ 通過 DroneMonitor.set_mode() 方法
|
|
|
|
|
|
|
|
|
|
$ python3 demo_set_mode.py group --drones s0_1 s0_2 s0_3 --mode LOITER
|
|
|
|
|
→ 演示群組模式切換
|
|
|
|
|
|
|
|
|
|
【4】SET_MODE_INTEGRATION.md - 完整的集成指南
|
|
|
|
|
────────────────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
位置: /home/dodo/Downloads/AirTrapMine/src/GUI/SET_MODE_INTEGRATION.md
|
|
|
|
|
|
|
|
|
|
內容:
|
|
|
|
|
- 實現原理詳解
|
|
|
|
|
- GUI 使用流程圖
|
|
|
|
|
- 代碼示例和片段
|
|
|
|
|
- fc_network_apps 實現細節
|
|
|
|
|
- 等效的 ROS2 CLI 命令
|
|
|
|
|
- 支援的飛行模式表
|
|
|
|
|
- 使用 drone_id 的說明
|
|
|
|
|
- 完整的使用示例
|
|
|
|
|
- 總結和相關文件引用
|
|
|
|
|
|
|
|
|
|
【5】IMPLEMENTATION_SUMMARY.md - 實現總結
|
|
|
|
|
────────────────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
位置: /home/dodo/Downloads/AirTrapMine/src/GUI/IMPLEMENTATION_SUMMARY.md
|
|
|
|
|
|
|
|
|
|
內容:
|
|
|
|
|
- 修改詳情
|
|
|
|
|
- 現有代碼的兼容性
|
|
|
|
|
- 使用流程(單無人機和群組)
|
|
|
|
|
- 新增文件說明
|
|
|
|
|
- 相關的 fc_network_apps 代碼
|
|
|
|
|
- 測試檢查清單
|
|
|
|
|
- 使用示例
|
|
|
|
|
- 支援的飛行模式參考
|
|
|
|
|
- 架構圖
|
|
|
|
|
- 調試技巧
|
|
|
|
|
|
|
|
|
|
【6】README_SET_MODE.md - 快速參考指南
|
|
|
|
|
────────────────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
位置: /home/dodo/Downloads/AirTrapMine/src/GUI/README_SET_MODE.md
|
|
|
|
|
|
|
|
|
|
內容:
|
|
|
|
|
- 在 GUI 中使用 Set Mode 的最快方式
|
|
|
|
|
- 現有代碼說明
|
|
|
|
|
- 實現位置
|
|
|
|
|
- 模式支援列表
|
|
|
|
|
- API 參考
|
|
|
|
|
- 相關文件索引
|
|
|
|
|
- 快速開始步驟
|
|
|
|
|
- 常見問題解答
|
|
|
|
|
- 設計要點
|
|
|
|
|
- 流程圖
|
|
|
|
|
- 重要提示
|
|
|
|
|
|
|
|
|
|
===============================================================================================
|
|
|
|
|
3. 現有代碼使用情況
|
|
|
|
|
===============================================================================================
|
|
|
|
|
|
|
|
|
|
gui.py 中的使用代碼(無需修改):
|
|
|
|
|
|
|
|
|
|
【位置 1】 L391-401: handle_mode_change() 方法
|
|
|
|
|
────────────────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
def handle_mode_change(self, drone_id):
|
|
|
|
|
# 從 active group 的 mode_combo 讀取模式
|
|
|
|
|
group = self._get_active_group()
|
|
|
|
|
if group:
|
|
|
|
|
panel = self.group_panels.get(group.group_id)
|
|
|
|
|
mode = panel.mode_combo.currentText() if panel else "GUIDED"
|
|
|
|
|
else:
|
|
|
|
|
mode = "GUIDED"
|
|
|
|
|
loop = asyncio.get_event_loop()
|
|
|
|
|
future = self.monitor.set_mode(drone_id, mode) # ✅ 使用新的 set_mode()
|
|
|
|
|
loop.create_task(self.handle_service_response(future, f"切換模式 {mode} {drone_id}"))
|
|
|
|
|
|
|
|
|
|
【位置 2】 L656-664: _handle_group_mode_change() 方法
|
|
|
|
|
────────────────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
def _handle_group_mode_change(self, group_id, mode):
|
|
|
|
|
"""切換群組內所有無人機的飛行模式"""
|
|
|
|
|
group = self.mission_groups.get(group_id)
|
|
|
|
|
if not group:
|
|
|
|
|
return
|
|
|
|
|
loop = asyncio.get_event_loop()
|
|
|
|
|
for drone_id in group.drone_ids:
|
|
|
|
|
future = self.monitor.set_mode(drone_id, mode) # ✅ 使用新的 set_mode()
|
|
|
|
|
loop.create_task(self.handle_service_response(future, f"{drone_id} 切換 {mode}"))
|
|
|
|
|
|
|
|
|
|
【位置 3】 L271, L501: 信號連接
|
|
|
|
|
────────────────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
panel.mode_change_requested.connect(self.handle_mode_change)
|
|
|
|
|
panel.mode_change_requested.connect(self._handle_group_mode_change)
|
|
|
|
|
|
|
|
|
|
狀態: ✅ 無需修改,自動與新的 set_mode() 方法配合
|
|
|
|
|
|
|
|
|
|
===============================================================================================
|
|
|
|
|
4. 技術細節
|
|
|
|
|
===============================================================================================
|
|
|
|
|
|
|
|
|
|
【API 簽名】
|
|
|
|
|
|
|
|
|
|
async def set_mode(self, drone_id: str, mode_name: str) -> bool:
|
|
|
|
|
"""
|
|
|
|
|
使用 fc_network_apps 的 change_mode 函數切換無人機飛行模式
|
|
|
|
|
|
|
|
|
|
參數:
|
|
|
|
|
drone_id (str): 無人機ID,格式 "s{socket_id}_{sysid}" (e.g., "s0_1")
|
|
|
|
|
mode_name (str): 模式名稱 (e.g., "GUIDED", "AUTO")
|
|
|
|
|
|
|
|
|
|
返回:
|
|
|
|
|
bool: 模式切換成功返回 True,失敗返回 False
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
【支援的模式】
|
|
|
|
|
|
|
|
|
|
STABILIZE (0), ACRO (1), ALT_HOLD (2), AUTO (3), GUIDED (4), LOITER (5),
|
|
|
|
|
RTL (6), CIRCLE (7), POSITION (8), LAND (9), OF_LOITER (10), DRIFT (11),
|
|
|
|
|
SPORT (13), FLIP (14), AUTOTUNE (15), POSHOLD (16), BRAKE (17),
|
|
|
|
|
THROW (18), AVOID_ADSB (19), GUIDED_NOGPS (20), SMART_RTL (21)
|
|
|
|
|
|
|
|
|
|
【實現流程】
|
|
|
|
|
|
|
|
|
|
1. 解析 drone_id 以提取 sysid
|
|
|
|
|
2. 從 MODE_MAPPING 查表獲取 custom_mode 值
|
|
|
|
|
3. 驗證 fc_network_apps 模塊可用
|
|
|
|
|
4. 呼叫 change_mode(target_sysid, custom_mode, ...)
|
|
|
|
|
5. 等待 ROS2 service 回應
|
|
|
|
|
6. 返回 result.success
|
|
|
|
|
|
|
|
|
|
【錯誤處理】
|
|
|
|
|
|
|
|
|
|
✅ 無效的 drone_id 格式
|
|
|
|
|
✅ 未知的模式名稱
|
|
|
|
|
✅ 缺少 fc_network_apps 模塊
|
|
|
|
|
✅ ROS2 service 超時
|
|
|
|
|
✅ 模式切換失敗
|
|
|
|
|
|
|
|
|
|
===============================================================================================
|
|
|
|
|
5. 測試驗證
|
|
|
|
|
===============================================================================================
|
|
|
|
|
|
|
|
|
|
【語法檢查】✅ 通過
|
|
|
|
|
|
|
|
|
|
$ python3 -m pylance communication.py
|
|
|
|
|
→ No syntax errors found
|
|
|
|
|
|
|
|
|
|
【導入檢查】✅ 可選(fc_network_apps 可選安裝)
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
from fc_network_apps import change_mode
|
|
|
|
|
except ImportError:
|
|
|
|
|
change_mode = None
|
|
|
|
|
|
|
|
|
|
✓ 如果 fc_network_apps 未安裝,代碼仍能運行,但 set_mode() 會返回失敗
|
|
|
|
|
|
|
|
|
|
【兼容性】✅ 完全向後相容
|
|
|
|
|
|
|
|
|
|
- 現有的 gui.py 代碼無需修改
|
|
|
|
|
- 現有的調用接口保持不變
|
|
|
|
|
- 自動與現有信號系統配合
|
|
|
|
|
|
|
|
|
|
===============================================================================================
|
|
|
|
|
6. 使用示例
|
|
|
|
|
===============================================================================================
|
|
|
|
|
|
|
|
|
|
【示例 1: 在 GUI 中單無人機切換】
|
|
|
|
|
|
|
|
|
|
# 用戶在 GUI 中:
|
|
|
|
|
# 1. 從 mode_combo 選擇 "GUIDED"
|
|
|
|
|
# 2. 點擊「切換」按鈕
|
|
|
|
|
# 3. 系統自動調用:
|
|
|
|
|
|
|
|
|
|
self.monitor.set_mode("s0_1", "GUIDED")
|
|
|
|
|
|
|
|
|
|
# 結果:無人機 sysid=1 切換到 GUIDED 模式(custom_mode=4)
|
|
|
|
|
|
|
|
|
|
【示例 2: 群組無人機切換】
|
|
|
|
|
|
|
|
|
|
# 用戶在 GUI 中:
|
|
|
|
|
# 1. 為群組 "A" 選擇模式 "AUTO"
|
|
|
|
|
# 2. 點擊「切換」按鈕
|
|
|
|
|
# 3. 系統對群組內每個無人機調用:
|
|
|
|
|
|
|
|
|
|
for drone_id in ["s0_1", "s0_2", "s0_3"]:
|
|
|
|
|
self.monitor.set_mode(drone_id, "AUTO")
|
|
|
|
|
|
|
|
|
|
# 結果:三個無人機都切換到 AUTO 模式(custom_mode=3)
|
|
|
|
|
|
|
|
|
|
【示例 3: 直接使用 fc_network_apps(腳本)】
|
|
|
|
|
|
|
|
|
|
from fc_network_apps import change_mode
|
|
|
|
|
|
|
|
|
|
result = change_mode(
|
|
|
|
|
target_sysid=1,
|
|
|
|
|
custom_mode=4.0, # GUIDED
|
|
|
|
|
timeout_sec=2.0
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if result.success:
|
|
|
|
|
print(f"Mode change successful: {result.message}")
|
|
|
|
|
else:
|
|
|
|
|
print(f"Mode change failed: {result.message}")
|
|
|
|
|
|
|
|
|
|
===============================================================================================
|
|
|
|
|
7. 文件結構
|
|
|
|
|
===============================================================================================
|
|
|
|
|
|
|
|
|
|
GUI/
|
|
|
|
|
├── communication.py ✏️ 【修改】新增 set_mode() 方法
|
|
|
|
|
├── gui.py ✓ 【無需修改】已使用 set_mode()
|
|
|
|
|
├── example_set_mode_usage.py ✨ 【新增】使用示例和詳細文檔
|
|
|
|
|
├── demo_set_mode.py ✨ 【新增】可執行演示腳本
|
|
|
|
|
├── SET_MODE_INTEGRATION.md ✨ 【新增】完整集成指南
|
|
|
|
|
├── IMPLEMENTATION_SUMMARY.md ✨ 【新增】實現總結
|
|
|
|
|
├── README_SET_MODE.md ✨ 【新增】快速參考
|
|
|
|
|
└── ...其他文件
|
|
|
|
|
|
|
|
|
|
===============================================================================================
|
|
|
|
|
8. 快速驗證
|
|
|
|
|
===============================================================================================
|
|
|
|
|
|
|
|
|
|
【步驟 1: 檢查 set_mode 方法是否存在】
|
|
|
|
|
|
|
|
|
|
$ grep -n "async def set_mode" GUI/communication.py
|
|
|
|
|
612: async def set_mode(self, drone_id, mode_name):
|
|
|
|
|
|
|
|
|
|
【步驟 2: 檢查 MODE_MAPPING 是否完整】
|
|
|
|
|
|
|
|
|
|
$ grep -A 20 "MODE_MAPPING = {" GUI/communication.py
|
|
|
|
|
585: MODE_MAPPING = {
|
|
|
|
|
586: "STABILIZE": 0,
|
|
|
|
|
...
|
|
|
|
|
606: }
|
|
|
|
|
|
|
|
|
|
【步驟 3: 檢查 fc_network_apps 導入】
|
|
|
|
|
|
|
|
|
|
$ grep -n "from fc_network_apps import" GUI/communication.py
|
|
|
|
|
20: from fc_network_apps import change_mode
|
|
|
|
|
|
|
|
|
|
【步驟 4: 運行演示腳本】
|
|
|
|
|
|
|
|
|
|
$ python3 GUI/demo_set_mode.py --help
|
|
|
|
|
$ python3 GUI/demo_set_mode.py direct --sysid 1 --mode GUIDED
|
|
|
|
|
|
|
|
|
|
===============================================================================================
|
|
|
|
|
9. 常見問題
|
|
|
|
|
===============================================================================================
|
|
|
|
|
|
|
|
|
|
Q1: 為什麼要在 communication.py 中實現而不是在 gui.py 中?
|
|
|
|
|
A: 為了保持代碼分離和可重用性。communication.py 負責與無人機通信,
|
|
|
|
|
gui.py 負責用戶界面。這樣 set_mode() 可以被其他模塊使用。
|
|
|
|
|
|
|
|
|
|
Q2: 為什麼模式名稱要大寫?
|
|
|
|
|
A: 這是 MODE_MAPPING 字典中的約定,與 MAVLink 和 ArduPilot 的命名保持一致。
|
|
|
|
|
|
|
|
|
|
Q3: drone_id 格式為什麼是 "s{socket_id}_{sysid}"?
|
|
|
|
|
A: 因為同一個連接(socket)可能有多個無人機,sysid 是 MAVLink 的標準 system ID。
|
|
|
|
|
|
|
|
|
|
Q4: 如果 fc_network_apps 未安裝怎麼辦?
|
|
|
|
|
A: 代碼已使用 try-except 安全處理,set_mode() 會返回失敗,GUI 會顯示錯誤信息。
|
|
|
|
|
|
|
|
|
|
Q5: 支援同時為多個無人機切換模式嗎?
|
|
|
|
|
A: 是的,通過 _handle_group_mode_change() 方法支持群組操作。
|
|
|
|
|
|
|
|
|
|
===============================================================================================
|
|
|
|
|
10. 總結
|
|
|
|
|
===============================================================================================
|
|
|
|
|
|
|
|
|
|
✅ 成功在 gui.py 中集成 fc_network_apps 的 change_mode 功能
|
|
|
|
|
|
|
|
|
|
修改總結:
|
|
|
|
|
- 1 個文件修改 (communication.py)
|
|
|
|
|
- 4 個新增文件(示例、文檔、演示腳本)
|
|
|
|
|
- 所有現有代碼無需修改
|
|
|
|
|
- 完全向後相容
|
|
|
|
|
- 完整的錯誤處理和日誌記錄
|
|
|
|
|
- 詳細的文檔和示例
|
|
|
|
|
|
|
|
|
|
功能特點:
|
|
|
|
|
✅ 簡單易用的 API: monitor.set_mode(drone_id, mode)
|
|
|
|
|
✅ 自動模式轉換: 模式名稱 → custom_mode 值
|
|
|
|
|
✅ 支援 20+ 種飛行模式
|
|
|
|
|
✅ 單無人機和群組切換
|
|
|
|
|
✅ 非同步執行不阻塞 UI
|
|
|
|
|
✅ 完整錯誤處理
|
|
|
|
|
✅ 詳細日誌記錄
|
|
|
|
|
|
|
|
|
|
現在用戶可以通過 GUI 方便地改變無人機的飛行模式!🚁
|
|
|
|
|
|
|
|
|
|
===============================================================================================
|
|
|
|
|
相關文件清單
|
|
|
|
|
===============================================================================================
|
|
|
|
|
|
|
|
|
|
代碼文件:
|
|
|
|
|
- GUI/communication.py (修改)
|
|
|
|
|
- GUI/gui.py (無需修改)
|
|
|
|
|
- GUI/example_set_mode_usage.py (新增)
|
|
|
|
|
- GUI/demo_set_mode.py (新增)
|
|
|
|
|
|
|
|
|
|
文檔文件:
|
|
|
|
|
- GUI/SET_MODE_INTEGRATION.md (新增)
|
|
|
|
|
- GUI/IMPLEMENTATION_SUMMARY.md (新增)
|
|
|
|
|
- GUI/README_SET_MODE.md (新增)
|
|
|
|
|
- 此文件 (CHANGES.md)
|
|
|
|
|
|
|
|
|
|
原始模塊:
|
|
|
|
|
- fc_network_apps/changeMode.py
|
|
|
|
|
- fc_network_apps/__init__.py
|
|
|
|
|
|
|
|
|
|
===============================================================================================
|