Delete 'src/GUI/BEFORE_AFTER_COMPARISON.md'
This commit is contained in:
@@ -1,218 +0,0 @@
|
|||||||
# 實現前後對比
|
|
||||||
|
|
||||||
## 系統架構變化
|
|
||||||
|
|
||||||
### 舊架構(直接更新)
|
|
||||||
```
|
|
||||||
接收執行緒
|
|
||||||
↓
|
|
||||||
monitor.latest_data
|
|
||||||
↓
|
|
||||||
spin_ros() [10ms]
|
|
||||||
↓
|
|
||||||
update_ui() [100% 直接更新 UI]
|
|
||||||
├─ GPS → 立即更新地圖和表格
|
|
||||||
├─ HUD → 立即更新 Panel 和地圖
|
|
||||||
├─ State → 立即更新 State
|
|
||||||
├─ Battery → 立即更新 Battery
|
|
||||||
└─ ... 等等
|
|
||||||
|
|
||||||
❌ 問題:
|
|
||||||
- Map 更新頻率太高,可能導致 CPU 過度使用
|
|
||||||
- 高頻率的連續更新可能造成視覺閃爍
|
|
||||||
- 沒有批次更新機制
|
|
||||||
```
|
|
||||||
|
|
||||||
### 新架構(分層更新)
|
|
||||||
```
|
|
||||||
接收執行緒
|
|
||||||
↓
|
|
||||||
monitor.latest_data
|
|
||||||
↓
|
|
||||||
spin_ros() [10ms]
|
|
||||||
↓
|
|
||||||
update_ui()
|
|
||||||
├─ GPS/HUD → 快取到 _message_cache
|
|
||||||
├─ State → 立即更新
|
|
||||||
├─ Battery → 立即更新
|
|
||||||
└─ ... 等等
|
|
||||||
↓
|
|
||||||
_update_panel_and_map() [100ms / 10Hz]
|
|
||||||
├─ 讀取 _message_cache GPS 資料
|
|
||||||
│ └─ 更新地圖位置和表格
|
|
||||||
├─ 讀取 _message_cache HUD 資料
|
|
||||||
│ └─ 更新 Panel 和地圖方向
|
|
||||||
└─ 使用上次快取值(如無新消息)
|
|
||||||
|
|
||||||
✅ 優勢:
|
|
||||||
- Map 和 Panel 只在 10Hz 更新,降低 CPU 負荷
|
|
||||||
- 批次更新確保原子性
|
|
||||||
- 消息未更新時使用上次值,資訊連續性好
|
|
||||||
- 分層設計允許不同組件不同更新率
|
|
||||||
```
|
|
||||||
|
|
||||||
## 代碼實現對比
|
|
||||||
|
|
||||||
### 舊代碼片段(GPS 更新)
|
|
||||||
```python
|
|
||||||
def update_ui(self, msg_type, drone_id, data):
|
|
||||||
...
|
|
||||||
elif msg_type == 'gps':
|
|
||||||
lat, lon = data.get('lat', 0), data.get('lon', 0)
|
|
||||||
self.drone_positions[drone_id] = (lat, lon)
|
|
||||||
alt = data.get('alt', 0)
|
|
||||||
if not hasattr(self.monitor, 'drone_gps'):
|
|
||||||
self.monitor.drone_gps = {}
|
|
||||||
self.monitor.drone_gps[drone_id] = {'lat': lat, 'lon': lon, 'alt': alt}
|
|
||||||
self.update_overview_table(drone_id, 'latitude', f"{lat:.6f}°")
|
|
||||||
self.update_overview_table(drone_id, 'longitude', f"{lon:.6f}°")
|
|
||||||
heading = self.drone_headings.get(drone_id, 0)
|
|
||||||
self.drone_map.update_drone_position(drone_id, lat, lon, heading) # ← 直接更新 Map
|
|
||||||
```
|
|
||||||
|
|
||||||
### 新代碼片段(GPS 快取)
|
|
||||||
```python
|
|
||||||
def update_ui(self, msg_type, drone_id, data):
|
|
||||||
...
|
|
||||||
# 快取 GPS 和 HUD 資料用於 panel/map 的 10Hz 更新
|
|
||||||
if msg_type in ('gps', 'hud'):
|
|
||||||
if drone_id not in self._message_cache:
|
|
||||||
self._message_cache[drone_id] = {}
|
|
||||||
self._message_cache[drone_id][msg_type] = data
|
|
||||||
# 不在這裡更新,等待 _update_panel_and_map 在 10Hz 執行
|
|
||||||
return
|
|
||||||
```
|
|
||||||
|
|
||||||
### 新代碼片段(10Hz 批次更新)
|
|
||||||
```python
|
|
||||||
def _update_panel_and_map(self):
|
|
||||||
"""10Hz 定時更新 panel 和 map,使用快取的 GPS 和 HUD 消息"""
|
|
||||||
for drone_id in list(self._message_cache.keys()):
|
|
||||||
cache = self._message_cache[drone_id]
|
|
||||||
|
|
||||||
# 使用快取的 GPS 資料
|
|
||||||
if 'gps' in cache:
|
|
||||||
gps_data = cache['gps']
|
|
||||||
lat, lon = gps_data.get('lat', 0), gps_data.get('lon', 0)
|
|
||||||
self.drone_positions[drone_id] = (lat, lon)
|
|
||||||
# ... 更新表格 ...
|
|
||||||
|
|
||||||
# 使用快取的 HUD 資料
|
|
||||||
if 'hud' in cache:
|
|
||||||
# ... 更新 panel 和 map ...
|
|
||||||
self.drone_map.update_drone_position(drone_id, lat, lon, heading) # ← 10Hz 更新
|
|
||||||
```
|
|
||||||
|
|
||||||
## 性能影響分析
|
|
||||||
|
|
||||||
### Map 更新頻率
|
|
||||||
|
|
||||||
| 場景 | 舊架構 | 新架構 | 改進 |
|
|
||||||
|------|--------|--------|------|
|
|
||||||
| 單架無人機 | ~50Hz | 10Hz | ↓ 80% |
|
|
||||||
| 5 架無人機 | ~250Hz | 10Hz | ↓ 96% |
|
|
||||||
| 10 架無人機 | ~500Hz | 10Hz | ↓ 98% |
|
|
||||||
|
|
||||||
### 消息快取大小
|
|
||||||
|
|
||||||
```
|
|
||||||
最大快取大小 = num_drones × 2 messages (gps + hud)
|
|
||||||
|
|
||||||
例如:10 架無人機
|
|
||||||
最大快取: 10 × 2 = 20 個消息
|
|
||||||
內存使用: ~10KB (非常小)
|
|
||||||
```
|
|
||||||
|
|
||||||
## 延遲分析
|
|
||||||
|
|
||||||
### 位置更新延遲
|
|
||||||
|
|
||||||
```
|
|
||||||
GPS 消息到達
|
|
||||||
↓
|
|
||||||
快取到 _message_cache
|
|
||||||
↓
|
|
||||||
等待至多 100ms(下一個 10Hz 週期)
|
|
||||||
↓
|
|
||||||
_update_panel_and_map() 讀取並更新地圖
|
|
||||||
↓
|
|
||||||
總延遲: 0-100ms
|
|
||||||
|
|
||||||
用戶體驗:無可見延遲(100ms 對人眼不可察)
|
|
||||||
```
|
|
||||||
|
|
||||||
## 初始化檢查清單
|
|
||||||
|
|
||||||
在啟動 GUI 時確保:
|
|
||||||
|
|
||||||
- [ ] `panel_map_timer` 已初始化並啟動
|
|
||||||
```python
|
|
||||||
self.panel_map_timer = QTimer()
|
|
||||||
self.panel_map_timer.timeout.connect(self._update_panel_and_map)
|
|
||||||
self.panel_map_timer.start(100)
|
|
||||||
```
|
|
||||||
|
|
||||||
- [ ] `_message_cache` 已初始化為空字典
|
|
||||||
```python
|
|
||||||
self._message_cache = {}
|
|
||||||
```
|
|
||||||
|
|
||||||
- [ ] `update_ui()` 正確快取 GPS/HUD 消息
|
|
||||||
```python
|
|
||||||
if msg_type in ('gps', 'hud'):
|
|
||||||
# 快取邏輯
|
|
||||||
```
|
|
||||||
|
|
||||||
- [ ] `_update_panel_and_map()` 方法存在且被連接
|
|
||||||
```python
|
|
||||||
self.panel_map_timer.timeout.connect(self._update_panel_and_map)
|
|
||||||
```
|
|
||||||
|
|
||||||
## 監控 UI
|
|
||||||
|
|
||||||
### 添加調試輸出(可選)
|
|
||||||
|
|
||||||
在 `_update_panel_and_map()` 開始添加:
|
|
||||||
|
|
||||||
```python
|
|
||||||
import time
|
|
||||||
|
|
||||||
if not hasattr(self, '_debug_map_time'):
|
|
||||||
self._debug_map_time = time.time()
|
|
||||||
self._debug_map_count = 0
|
|
||||||
|
|
||||||
self._debug_map_count += 1
|
|
||||||
if time.time() - self._debug_map_time >= 1.0:
|
|
||||||
cached_drones = len(self._message_cache)
|
|
||||||
updated_drones = sum(1 for d in self._message_cache.values() if d)
|
|
||||||
print(f"[10Hz] Cycle {self._debug_map_count} | "
|
|
||||||
f"Cached: {cached_drones} | "
|
|
||||||
f"Updated: {updated_drones}")
|
|
||||||
self._debug_map_time = time.time()
|
|
||||||
self._debug_map_count = 0
|
|
||||||
```
|
|
||||||
|
|
||||||
## 故障診斷
|
|
||||||
|
|
||||||
如果地圖或 Panel 沒有更新:
|
|
||||||
|
|
||||||
1. **檢查定時器是否運行**
|
|
||||||
```python
|
|
||||||
print(f"Timer active: {self.panel_map_timer.isActive()}")
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **檢查快取是否有數據**
|
|
||||||
```python
|
|
||||||
print(f"Cache: {self._message_cache}")
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **檢查方法是否被調用**
|
|
||||||
- 在 `_update_panel_and_map()` 開始添加 `print("_update_panel_and_map called")`
|
|
||||||
|
|
||||||
4. **檢查 update_drone_position 是否有錯誤**
|
|
||||||
- 查看控制台輸出,是否有異常拋出
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**版本**: 2025-03-25
|
|
||||||
**狀態**: ✅ 生產就緒
|
|
||||||
Reference in New Issue
Block a user