2013-05-25 148 views
2

我已經爲Android安裝了GPS追蹤器。到目前爲止,它工作得相當不錯,但我在計算軌道的高度差時遇到問題。我想總結一下所有儀表的「爬升」和「下降」。我在後臺服務中執行此操作,將當前位置對象與前一個位置對象進行比較,並將差異直接作爲列存儲在數據庫中。如果我在軌道完成後對此進行總結,我會得到一個大約是使用氣壓計的自行車車速表測量值的2.5倍(1500米對650米)的值。GPS軌道,計算高度差

我知道GPS設備的測量高度不準確。有什麼辦法可以使測量的高度「正常化」嗎?例如,我是否應該忽略低於2米的所有高度變化?另一種可能性是使用附加的傳感器,因爲一些設備也具有氣壓計。但是這隻對某些設備有幫助。

感謝您對此問題的任何建議或提示!

編輯28.05.2013: 布萊斯的答案讓我走上了正軌。我開始搜索網絡,發現一個非常簡單的低通濾波器,易於實現。 我在C + +

表示一個路點的節點類這樣做:

class Node { 
private: 
    double distance; 
    double altitude; 
    double altitudeup; 
    double altitudedown; 
    double latitude; 
    double longitude; 
    long timestamp; 

public: 
    Node(double dist, double alti, double altiup, double altidown, double lat, double lon, long ts); 
    double getAltitude(); 
    double getAltitudeup(); 
    double getAltitudedown(); 
}; 

這裏是執行實際工作和計算值總上升和功能下降:

void SimpleLowPass::applySLP() 
{ 
    double altiUp = 0; 
    double altiDown = 0; 
    double prevAlti = this->nodeList[0]->getAltitude(); 
    double newAlti = prevAlti; 
    for (auto n : this->nodeList) 
    { 
     double cur = n->getAltitude(); 
//  All the power of the filter is in the line 
//  newAlti += (cur - newAlti)/smoothing. 
//  This finds the difference between the new value and the current (smoothed) 
//  value, shrinks it based on the strength of the filter, and then adds it 
//  to the smoothed value. You can see that if smoothing is set to 1 then the 
//  smoothed value always becomes the next value. If the smoothing is set to 
//  2 then the smoothed value moves halfway to each new point on each new 
//  frame. The larger the smoothing value, the less the smoothed line is 
//  perturbed by new changes. 
     newAlti += (cur - newAlti)/20.0; 
     std::cout << "newAlti: " << newAlti << std::endl; 
     if (prevAlti > newAlti) 
     { 
      altiDown += prevAlti - newAlti; 
     } 
     if (newAlti > prevAlti) 
     { 
      altiUp += newAlti - prevAlti; 
     } 
     prevAlti = newAlti; 

    } 
    std::cout << "Alti UP total: " << altiUp << std::endl; 
    std::cout << "Alti DOWN total: " << altiDown << std::endl; 
} 

這是一個快速和骯髒的實現。但用平滑值爲20,我獲得了相當不錯的結果。我仍然需要記錄更多曲目並比較結果。此外,網站上還有幀率獨立實現,我發現這個低通濾波器,我想用移動平均實現。

simple low-pass filter

感謝您的答案!

+0

我會建議氣壓計比GPS精確得多。此外,你確定你的自行車高度表跟蹤所有提升/下降的總和,而不僅僅是起點和終點之間的高程差異嗎? – 323go

+0

@ 323go晴雨表如果準確得多,但只適用於三角洲。 – Bryce

+0

我用一個在線地圖服務創建的軌道檢查了deltas。上下有720米,所以我的自行車高度表的值應該相當不錯 –

回答

0

使用氣壓計,如果設備有它,但無論哪種方式,你將不得不應用某種平滑過濾器。在不查看收集的數據的情況下,我只能推測原因,但這可能是由於與衛星失去同步時引起的。

+0

我認識到我的數據是有很多條目差異很小。正如我所見,這是由於GPS設備的不準確性。你會推薦什麼樣的過濾/平滑處理數據?我已經使用Douglas-Peucker來平滑我的軌跡(基於緯度/經度) –

+0

我已經嘗試過幾種過濾器,但是我還沒有找到「殺手」過濾器。最簡單的實現仍然有不錯的結果是低通濾波器和盒式濾波器。另一種選擇,而不是過濾是某種曲線近似。曲線近似會高估一點,而過濾會低估一點。 – Bryce

+0

您能否提供一些低通或箱式過濾器的例子? –

0

當使用不精確測量的總和時,您總是會遇到大量的錯誤。這是一個基本的統計確定性。

而不是存儲一個測量和下一個測量之間的差異,而應該將每個測量視爲一個獨立的數據點。例如,取所有點的最小高度,並從所有測量值中減去該值。

+1

我的高度測量值在350米至800米之間。如果我從海拔三角洲的所有航點減去350米,我會得到什麼? –

+0

我只是想強調,你不應該存儲單個不精確的樣本之間的差異。但是,您想對您的數據進行後分析取決於您,但請記住,每個樣本都應該是一個獨立的數據點。 –

2

GPS高度反彈很多,這些反彈看起來像是上升或下降。根據我的經驗,氣壓計傳感器在更窄的範圍內反彈。

你想要做的是測量每次爬升(爬升定義爲高度的不斷增加),然後求和爬升以確定爬升的總高度。

使用任何傳感器(GPS或巴洛),高度會反彈一點,我們不希望這些小反彈被記錄爲短下降和爬升。所以當我們攀登的時候,我們想忽略海拔高度的小凹陷。

double THRESHOLD = 10; 
Direction climbingOrDescending = Direction.NONE; 

double totalAscent = 0; 
double totalDescent = 0; 

double climbStart; 
double maxAltitude; 

double descentStart; 
double minAltitude; 

public void onSample(double sample) { 
    if (climbingOrDescending == Direction.NONE) { 
     // First sample 
     climbingOrDescending = Direction.CLIMBING; // Arbitrary 
     climbStart = sample; 
     maxAltitude = sample; 
    } else if (climbingOrDescending == Direction.CLIMBING) { 
     if (sample > maxAltitude) { 
      maxAltitude = sample; 
     } else if (sample < (maxAltitude - THRESHOLD)) { 
      // bounces in sample that are smaller than THRESHOLD are ignored. If 
      // the sample is far below maxAltitude... it is not a bounce, record 
      // the climb and move to a descending state 
      double altitudeGainedThisClimb = maxAltitude - climbStart; 
      totalAscent += altitudeGainedThisClimb; 
      // Prepare for descent. 
      climbingOrDescending = Direction.DESCENDING; 
      descentStart = maxAltitude; 
      minAltitude = sample; 
     } 
    } else { // climbingOrDescending == DESCENDING 
     // similar code goes here to measure descents 
    } 
} 

public double getTotalAscent() { 
    if (climbingOrDescending == Direction.CLIMBING) { 
     return totalAscent + (maxAltitude - climbStart); 
    } else { 
     return totalAscent; 
    } 
} 
+0

我很難理解你的答案:)你能提供一個真實世界的例子,一些任意的數據。我不需要任何代碼就可以幫助理解您的想法 –