【问题标题】:GPS Track, computing height differenceGPS Track,计算高差
【发布时间】:2013-05-25 20:45:28
【问题描述】:

我已经为 Android 实现了 GPS 追踪器。到目前为止,它工作得很好,但我在计算轨道的 right 高度差时遇到了问题。我想总结设备“爬升”和“下降”的所有仪表。我在后台服务中执行此操作,将当前位置对象与前一个位置对象进行比较,并将差异直接存储为数据库中的列。如果我在赛道完成后总结这一点,我得到的值大约是使用气压计的自行车速度计测量的 2.5 倍(1500m 对 650m)。

我知道 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

感谢您的所有回答!

【问题讨论】:

  • 我建议气压计的准确度远低于 GPS。此外,您确定您的自行车高度计跟踪所有上升/下降的总和,而不仅仅是起点和终点之间的整体海拔差异?
  • @323 如果要准确得多,请使用气压计,但仅适用于增量。
  • 我使用在线地图服务上创建的轨迹检查了增量。上下有720m,所以我的自行车高度计的值应该还不错

标签: android c++ gps android-sensors lowpass-filter


【解决方案1】:

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;
    }
}

【讨论】:

  • 我很难理解你的答案 :) 你能否提供一个带有一些任意数据的真实示例。我不需要任何代码,只需要一些有助于理解您的想法的数字
【解决方案2】:

如果设备有气压计,请使用气压计,但无论哪种方式,您都必须应用某种平滑过滤器。在不查看您收集的数据的情况下,我只能推测原因,但这可能是由于您与卫星失去同步时的尖峰造成的。

【讨论】:

  • 我从我的数据中认识到,有许多条目的差异很小。正如我所见,这是因为 GPS 设备不准确。对于高程数据,您会推荐哪种过滤/平滑处理?我已经使用 Douglas-Peucker 来平滑我的轨迹(基于纬度/经度)
  • 我已经尝试了几个过滤器,但我还没有找到“杀手”过滤器。仍然有不错结果的最容易实现的是低通滤波器和盒式滤波器。另一种选择,而不是过滤是某种曲线近似。曲线近似会高估一点上升,而过滤会低估一点。
  • 您能否提供一些低通或盒式滤波器的示例?
  • 对不起,意思是 boxcar 过滤器 (en.wikipedia.org/wiki/Boxcar_function)。您可以将其实现为移动平均线,其中窗口大小定义为距离。我会先尝试一下,如果结果仍然不够好,可以考虑寻找一个提供 FIR(有限脉冲响应)过滤器的 java 库。
  • 我接受了你的回答,因为它让我走上了正轨,谢谢!
【解决方案3】:

在使用不精确测量值的总和时,您总是会遇到很大的误差。这是一个基本的统计确定性。

您不应存储一次测量与下一次测量之间的差异,而应将每次测量视为一个独立的数据点。例如,取所有点的最小高度,然后从所有测量值中减去该值。

【讨论】:

  • 我的海拔测量值介于 350m 到 800m 之间。如果我从关于海拔增量的所有航路点中减去 350m,我会得到什么?
  • 我只是想强调您不应该存储单个不精确样本之间的差异。但是,您要对数据进行后分析取决于您自己,但请记住,每个样本都应该是一个独立的数据点。
猜你喜欢
  • 2016-07-02
  • 1970-01-01
  • 2014-05-06
  • 1970-01-01
  • 2012-01-19
  • 1970-01-01
  • 2013-08-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多