Измерение скорости с помощью iPhone SDK

Мне нужно реализовать собственное приложение для iPhone, чтобы измерить скорость телефона (в основном спидометр). Я знаю, что вы можете сделать это через CoreLocation API довольно легко, но я обеспокоен расходом батареи, поскольку это измерение в режиме реального времени, которое можно использовать в течение нескольких часов за раз. Насколько я понимаю, в то время как вы активно отслеживаете события из LocationManager (хотя на самом деле я не забочусь о местоположении GPS), он потребляет много энергии.

Другой очевидный вариант для изучения - использование акселерометров для расчета скорости, но в API нет ничего, что могло бы вам помочь. Основываясь на моих исследованиях, это должно быть возможно сделать, но кажется чрезвычайно сложным и подверженным ошибкам. Перевод с ускорения на скорость может быть сложным для начала, плюс данные акселерометра iPhone могут быть "шумными". Я знаком с примером SDK, который демонстрирует использование фильтрации нижних / верхних частот и т. Д., Но я не видел ни одного хорошего примера, где бы можно было рассчитать скорость.

У кого-нибудь есть реальный опыт с этим, которым он может поделиться? Код был бы фантастическим, но на самом деле я просто хочу знать, успешно ли кто-нибудь сделал это (для долгоживущего приложения) и какой подход они выбрали.

РЕДАКТИРОВАТЬ: у меня есть рабочий прототип, который использует LocationManager API. Он работает нормально, но цикл обновления далек от идеального для измерения скорости в режиме реального времени. В зависимости от обстоятельств обновление может занять до 4-5 секунд. Крейсерская с заданной скоростью, как правило, работает нормально, но ускорение / замедление имеют тенденцию сильно отставать с точки зрения взаимодействия с пользователем. Кроме того, мне нужно указать скорость в некоторых других вычислениях, которые я делаю, и точность не совсем то, что мне нужно.

Это кажется возможным на основе (очень немногих) других приложений, которые я видел, особенно gMeter, который утверждает, что не использует GPS, но точно рассчитывает скорость. Я действительно удивлен, что нет ссылок или примеров кода, который демонстрирует это где-либо, что я могу найти. Я понимаю, что это сложно, но наверняка есть что-то там.

5 ответов

Решение

Поскольку у GPS и акселерометра есть разные слабые стороны, ваш лучший вариант, вероятно, - комбинированный подход: измеряйте данные GPS каждую минуту или около того, затем добавляйте изменения в реальном времени от акселерометра.

С практической точки зрения вы не получите точную скорость от сил, действующих на акселерометр.

Используйте GPS с показаниями, снятыми с интервалом в 1 минуту, и переведите GPS в режим ожидания.

Вот пример:

SpeedViewController.h

CLLocationManager *locManager;
CLLocationSpeed speed;
NSTimer *timer;

@property (nonantomic,retain) NSTimer *timer;

SpeedViewController.m

#define kRequiredAccuracy 500.0 //meters
#define kMaxAge 10.0 //seconds

- (void)startReadingLocation {
    [locManager startUpdatingLocation];
}

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {

    NSTimeInterval ageInSeconds = [newLocation.timestamp timeIntervalSinceNow];

    //ensure you have an accurate and non-cached reading
    if( newLocation.horizontalAccuracy > kRequiredAccuracy || fabs(ageInSeconds) > kMaxAge )
        return;

    //get current speed    
    currentSpeed = newLocation.speed;

    //this puts the GPS to sleep, saving power
    [locManager stopUpdatingLocation]; 

    //timer fires after 60 seconds, then stops
    self.timer = [NSTimer scheduledTimerWithTimeInterval:60.0 target:self selector:@selector(timeIntervalEnded:) userInfo:nil repeats:NO];
}

//this is a wrapper method to fit the required selector signature
- (void)timeIntervalEnded:(NSTimer*)timer {
    [self startReadingLocation];
}

Ошибка в ускорении будет накапливаться со временем. Лучше всего получить точную скорость от GPS, возможно, раз в минуту или меньше:

distanceTravelled = sqrt( (position2.x-position1.x)^2 + (position2.y-position1.y)^2 )
velocity = distanceTravelled/timeBetweenGPSReadings

(где ^2 значит в квадрате)

Затем проведите частые измерения акселерометра:

newVelocity = oldVelocity + accelerometer*timeBetweenAccelerometerReadings

Я не уверен, что вы будете очень далеко пытаться отслеживать скорость с помощью акселерометра. Чтобы сделать это, вам нужно убедиться, что вы зафиксировали КАЖДОЕ ускорение, поскольку любые пропущенные точки данных будут указывать неправильную скорость (это, конечно, при условии, что вы можете преобразовать сообщенные значения акселерометра в стандартные единицы). Таким образом, вам придется постоянно запускать акселерометр, который впитывает в себя немало сока (и, опять же, вам не будут гарантированы все ускорения). Я бы порекомендовал использовать CoreLocation.

Хотя я не знаю iPhone API, я кое-что знаю о GPS и инерциальной навигации. Это может быть полезно.

Приемники GPS, с которыми я работал, могут обеспечить прямое измерение скорости по полученным сигналам GPS. Эти измерения являются более точными, чем даже данные о местоположении. Я не знаю, предоставляет ли Apple API доступ, или даже если Apple настроил свой приемник для предоставления этих данных. Это был бы более эффективный путь к измерению скорости.

Следующий путь, учитывая, что у вас есть данные акселерометра и GPS, состоит в том, чтобы объединить их, как упоминалось ранее другими авторами и комментариями. Использование GPS для периодической коррекции накопленных измерений интервала по данным акселерометра очень хорошо работает на практике. Это обеспечивает преимущество более частых измерений акселерометра и точность измерений GPS. Обычно используется фильтр Калмана. Но, учитывая точность и временные ограничения выбранной вами платформы, фильтр Калмана может оказаться излишним, и что-то более простое в реализации и запуске должно работать нормально.

Во всяком случае, просто некоторые вещи, чтобы подумать.

Другие вопросы по тегам