Core Motion с постоянным изменением рыскания

У меня есть менеджер Core Motion в моем приложении для iOS:

motionManager = [[CMMotionManager alloc] init];
motionManager.deviceMotionUpdateInterval = 1.0 / 60.0;
if ([motionManager isDeviceMotionAvailable]) {
    [motionManager startDeviceMotionUpdates];
}

и в методе обновления (я использую cocos3d, но это не беда) у меня есть это:

-(void) updateBeforeTransform:(CC3NodeUpdatingVisitor *)visitor
{
    if (motionManager.deviceMotionActive)
    {
        CMDeviceMotion *deviceMotion = motionManager.deviceMotion;
        CMAttitude *attitude = deviceMotion.attitude;

        NSLog(@"%f, %f, %f", attitude.yaw, attitude.pitch, attitude.roll);

    }
}

Кладу прибор на стол и начинаю смотреть значения рыскания, тангажа и крена, а рыскание постоянно меняется! она меняется примерно на 10 градусов за пару минут, что абсолютно недопустимо в моем приложении. В чем причина этого изменения и как я могу этого избежать? Я начал думать, что это происходит из-за вращения Земли, но скорость слишком большая :)

Заранее спасибо!


person medvedNick    schedule 26.07.2012    source источник
comment
У вас есть компас в устройстве? Если вы этого не сделаете, то это имеет смысл.   -  person Ali    schedule 26.07.2012
comment
Сейчас я использую iPad 3, кажется, в нем есть компас. На самом деле, это приложение дополненной реальности, и я уже сделал сцену с вращением cocos3d с вращением устройства, все отлично работает, кроме этого медленно, но постоянно меняющегося угла рыскания.   -  person medvedNick    schedule 26.07.2012
comment
Пожалуйста, убедитесь, что у вас есть компас. Гироскопы могут позаботиться о вращении в краткосрочной перспективе и для быстрых вращений. То, что вы описываете, характерно для устройств без компаса.   -  person Ali    schedule 26.07.2012
comment
@ Кей, ты знаешь, как я могу получить доступ к северному заголовку независимо от моего Core Motion Manager? Я пробовал менеджер CLLocation и заголовок его свойства, но он не менялся так быстро, как угол рыскания.   -  person medvedNick    schedule 26.07.2012
comment
@medvedNick Посмотрите на Какой класс/код iOS возвращает магнитный Север?   -  person Kay    schedule 26.07.2012


Ответы (2)


Попробую выстрелить в темноте. В iOS 5 данные магнитометра являются частью алгоритма объединения датчиков Core Motion. Для многих приложений, таких как игры, в этом нет необходимости или, что еще лучше, это опасно из-за повышенного потребления энергии и возможной необходимости калибровать компас, вынуждая пользователя делать это как движение.

Поэтому я предполагаю, что данные компаса учитываются при объединении датчиков, только если это явно указано с помощью startDeviceMotionUpdatesUsingReferenceFrame вместо startDeviceMotionUpdates. Попробуйте CMATtitudeReferenceFrameXMagneticNorthZVertical и проверьте, уменьшается ли эффект дрейфа.

person Kay    schedule 26.07.2012
comment
ну, это почти решило проблему... Теперь это выглядит так: рыскание медленно меняется, как обычно, но через 5 или около того секунд оно прыгает до нужного значения. Затем он снова начинает меняться и через 5 секунд снова переходит к правильному значению... Я видел это в документации Apple: CMAttitudeReferenceFrameXArbitraryCorrectedZVertical Описывает ту же систему отсчета, что и CMAttitudeReferenceFrameXArbitraryZVertical, за исключением того, что магнитометр, когда он доступен и откалиброван, используется для улучшить долгосрочную точность рыскания, это похоже на то, что я хотел, но это не уменьшает дрейф. - person medvedNick; 27.07.2012
comment
PS: CMAttitudeReferenceFrameXArbitraryCorrectedZVertical работает так же, как CMAttitudeReferenceFrameXMagneticNorthZVertical — рысканье изменяется, а затем переходит к правильному значению - person medvedNick; 27.07.2012
comment
@medvedNick Попробуйте другое место для тестирования, просто чтобы убедиться, что вокруг нет мешающих магнитных полей. Возможно, вам поможет Sensor Monitor (это бесплатно). чтобы проверить, в порядке ли ваши датчики. - person Kay; 27.07.2012
comment
хм, попробую.. я заметил, что через какое-то время рысканье уменьшается.. может быть, ему нужно время, чтобы откалибровать себя. Спасибо за помощь, в любом случае! :) - person medvedNick; 27.07.2012

То, что вы испытываете, называется дрейфом, и вы мало что можете с этим поделать.

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

Если у устройства есть датчик, который может измерять мгновенные ориентации, например магнитометр, то алгоритм слияния датчиков может исправить дрейф, сравнивая/объединяя входные данные датчика, отсюда и вариант системы отсчета Apple: CMATtitudeReferenceFrameXArbitraryCorrectedZVertical.

Но реализация Apple не идеальна, поэтому вы видите массовые скачки назад и вперед, чтобы исправить нарастание ошибки, когда CMAttitudeReferenceFrameXArbitraryCorrectedZVertical включен. Лучшим алгоритмом может быть тот, который, по крайней мере, сглаживает исправление ошибок с течением времени.

person Colin    schedule 12.11.2013