Delete 'src/GUI/PANEL_MAP_UPDATE.md'

This commit is contained in:
2026-04-01 14:41:14 +08:00
parent b4fb0ccaaa
commit 1de7f5fb9c
-189
View File
@@ -1,189 +0,0 @@
# Panel 和 Map 10Hz 更新機制
## 概述
Panel(DronePanel)和 Map(DroneMap)的更新率已優化為 **10Hz(每 100ms 更新一次)**,同時其他 UI 元素保持更快的更新速率。這確保了地圖和面板在資訊流量大時不會過度刷新,同時保持流暢的用戶體驗。
## 架構
### 資料流
```
接收執行緒 (高頻)
↓
monitor.latest_data
↓
spin_ros() [10ms] - 發送信號
↓
update_ui() [快速更新]
├─ State, Battery, Altitude, etc. → 直接更新 (快速)
└─ GPS, HUD → 快取到 _message_cache
↓
_update_panel_and_map() [100ms / 10Hz]
├─ 讀取 _message_cache 的 GPS 資料
│ └─ 更新經緯度表格
├─ 讀取 _message_cache 的 HUD 資料
│ ├─ 更新標題、速度、高度等
│ └─ 更新 Panel 顯示
└─ 更新地圖位置和無人機方向
```
### 關鍵特性
1. **消息快取 (`_message_cache`)**
- GPS 和 HUD 消息被快取而不是立即處理
- 如果在 10Hz 更新週期內沒有收到新消息,使用上一次的值
- 避免因快速連續的消息導致過度刷新
2. **分層更新**
- **快速更新** (on-demand): State, Battery, Altitude, Loss Rate, Ping 等
- **10Hz 更新**: GPS 位置, HUD(標題、速度、高度、爬升率), Panel 和 Map
3. **定時器機制**
```python
# 10Hz 定時器
self.panel_map_timer = QTimer()
self.panel_map_timer.timeout.connect(self._update_panel_and_map)
self.panel_map_timer.start(100) # 100ms = 10Hz
```
## 實現細節
### 步驟 1: 快取消息
在 `update_ui()` 中,GPS 和 HUD 消息被快取:
```python
# 快取 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
```
### 步驟 2: 10Hz 批次更新
每 100ms,`_update_panel_and_map()` 被調用:
```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:
hud_data = cache['hud']
heading = hud_data.get('heading', 0)
# ... 更新 panel 和 map
self.drone_map.update_drone_position(drone_id, lat, lon, heading)
```
### 步驟 3: 持久化數據
即使沒有新消息,先前快取的值仍然存在於 `_message_cache` 中,所以 `_update_panel_and_map()` 將在下一個 10Hz 周期使用它:
```python
# 第一個週期:GPS 消息到達
_message_cache = {
'drone_0': {'gps': {'lat': 23.123, 'lon': 120.456, ...}}
}
# 第二個週期:沒有新 GPS 消息,但仍使用前一個值
_update_panel_and_map() 會使用 'drone_0' 的上一個 GPS 位置
```
## 性能影響
### 優點
- **降低 Map 更新頻率**: 避免過度繪製導致 CPU 負荷
- **更流暢的 UI**: 批次更新減少了視覺閃爍
- **減少同步開銷**: 地圖位置和面板資訊一起批次更新
### 更新頻率對比
| 組件 | 舊速率 | 新速率 | 說明 |
|------|--------|--------|------|
| State/Battery/Altitude | 即時 | 即時 | 保持快速響應 |
| GPS/HUD 消息 | 即時 | 10Hz | 快取並批次更新 |
| Map 更新 | 即時 | 10Hz | 隨 HUD 更新 |
| Panel 顯示 | 即時 | 10Hz | 隨 HUD 更新 |
## 故障排除
### Panel 或 Map 沒有更新
1. 檢查 `panel_map_timer` 是否啟動
```python
print(self.panel_map_timer.isActive()) # 應該是 True
```
2. 驗證 `_update_panel_and_map()` 是否被調用
- 在方法開始添加 `print(f"Panel/Map update: {len(self._message_cache)} drones")`
3. 檢查快取是否有數據
```python
print(self._message_cache) # 應該看到 drone_id 和消息
```
### 數據延遲或重複
如果看到數據延遲(最多 100ms),這是正常的。這就是為什麼我們使用快取 - 確保最新值始終可用。
如果看到重複更新,檢查是否有多個地方在調用 `update_drone_position()`。
## 初始化
在 `__init__` 中添加:
```python
# 初始化 panel 和 map 更新(10Hz)
self.panel_map_timer = QTimer()
self.panel_map_timer.timeout.connect(self._update_panel_and_map)
self.panel_map_timer.start(100) # 10Hz
# 快取消息數據,以便在沒有新消息時使用上一次的值
self._message_cache = {}
```
## 監控與調試
### 列印更新頻率
添加到 `_update_panel_and_map()`:
```python
def _update_panel_and_map(self):
if not hasattr(self, '_map_update_count'):
self._map_update_count = 0
self._map_update_time = time.time()
self._map_update_count += 1
if time.time() - self._map_update_time >= 1.0:
print(f"Panel/Map update frequency: {self._map_update_count} Hz")
self._map_update_count = 0
self._map_update_time = time.time()
# ... 其餘代碼
```
### 快取大小監控
```python
print(f"Cache size: {len(self._message_cache)} drones")
for drone_id, cache in self._message_cache.items():
print(f" {drone_id}: {list(cache.keys())}")
```
---
**更新日期**: 2025-03-25
**版本**: Panel/Map 10Hz 優化 v1.0