臭蟲 #130
進行中速度高度資訊不正常
100%
概述
在 QGC 顯示的高速,速度是正確的。但是在 SkySharpGCS 中顯示不對。
是由 Peter Sun 於 2 個月 前更新
- 狀態 從 新建立 變更為 已解決
一、 問題描述 (Symptoms)
在開發 SkySharp GCS 過程中,發現無人機高度與速度顯示出現以下異常:
數值「打折」:實際高度為 20m 時,UI 僅顯示約 10m;RTL 高度 30m 時,UI 僅顯示約 15m。
數值抖動:顯示數值在兩個區間內劇烈跳動,不穩定。
負值誤差:降落鎖定(Disarm)後,高度出現 -8m 等不合理的誇張誤差。
二、 根本原因分析 (Root Cause)
問題核心在於 「數據源污染 (Data Contamination)」 與 「C# 濾波器特性」 的連鎖反應。
1. C++ DLL 的數據衝突 (The Logic Bug)
MAVLink 協議會同時發送多種包含導航資訊的封包,而 DLL 中的處理邏輯存在缺陷:
VFR_HUD (ID 74):提供地速與空速,但原程式碼將其中的「相對高度」欄位寫死為 0。
GLOBAL_POSITION_INT (ID 33):提供準確的「相對高度」。
在舊版代碼中,C++ 每收到一個封包就創建一個全新的 VehicleNavInfo 對象傳給 C#。這導致 C# 在極短時間內交替收到:
來自 ID 33 的正確高度(例如:20m)
來自 ID 74 的錯誤高度(固定為:0m)
2. C# 濾波器的平均效應 (The Averaging Trap)
在 MainWindowViewModel 中,為了平滑數據使用了濾波係數(FilterAlpha = 0.2)。 當濾波器不斷接收到 20, 0, 20, 0 這種震盪數據時,其數學特性會趨向兩者的平均值,因此高度變成了 10m 左右,且因為數據權重不斷切換而產生劇烈跳動。
三、 來龍去脈 (Sequence of Events)
數據產生:無人機發送遙測封包。
數據傳遞:C++ DLL 攔截封包,但因為沒有「記憶」功能,導致 VFR_HUD 封包不斷用 0 去覆蓋正確的高度數據。
數據融合錯誤:C# 端的濾波演算法將「正確值」與「歸零值」進行加權平均,產生了數值減半的假象。
降落偏差:降落時,由於濾波器內仍殘留被污染的數據權重,加上氣壓計微小飄移,最終導致計算結果偏向負值(-8m)。
四、 解決方案 (The Final Solution)
1. C++ 端:實施「靜態快取機制 (Static Caching)」
核心改動:在 DLL 中建立一個全域/靜態變數 g_latestNavInfo。
當 VFR_HUD 進來時,只更新速度欄位,保留高度。
當 GLOBAL_POSITION_INT 進來時,只更新高度欄位,保留速度。
結果:傳給 C# 的結構體永遠包含所有欄位的最新「正確值」,不再包含寫死的 0。
2. C# 端:實施「數據合法性過濾」
核心改動:
零值過濾:如果高度與速度同時為 0,視為無效數據不予處理。
冷啟動同步:第一個封包直接賦值(跳過濾波),避免從 0 開始爬升產生的初始延遲。
鎖定重置:當飛機 Disarmed 且高度接近地面時,強制歸零,消除氣壓計殘留偏差。
五、 結論與建議
遙測數據處理應遵循 「各司其職、狀態保留」 的原則。不同協議封包之間應該是互補關係,而非覆蓋關係。未來增加新的 MAVLink 訊息時(如風速、電池狀態),也應採用此「快取合併」模式,以確保數據的連貫性。