diff --git a/src/GUI/PANEL_MAP_UPDATE.md b/src/GUI/PANEL_MAP_UPDATE.md deleted file mode 100644 index cad76c4..0000000 --- a/src/GUI/PANEL_MAP_UPDATE.md +++ /dev/null @@ -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