Подтвердить что ты не робот

Гироскоп на iPhone

Мне нужна помощь с помощью гироскопа на iPhone. Я не могу понять показания CMAttitude относительно высоты, валика и рыскания в конкретной ситуации.

Это мой код

- (void)handleDeviceMotion:(CMDeviceMotion*)motion {

   NSLog(@"Yaw   %f ",attitude.yaw * 180 / M_PI);
   NSLog(@"Pitch %f ",attitude.pitch * 180 / M_PI);
   NSLog(@"Roll  %f ",attitude.roll * 180 / M_PI);
}

Предположим, что iPhone укладывается на плоскость, как показано на следующем рисунке:

enter image description here

шаг, рулон и рыскание (почти) 0 градусов, и любой поворот вокруг оси возвращает понятные показания. Например, поворачивая устройство вправо, Yaw уменьшается, а Pitch and Roll остается на 0.

Теперь iPhone находится в следующем положении:

enter image description here

и измерение снова начнется.

Показания: Yaw = 0, Pitch = 90, Roll = 0

Так как устройства повернуты вокруг этой оси, увеличивается Pitch.

Перемещение iPhone в эту позицию:

enter image description here

: Yaw = 30, Pitch = 90, Roll = 0

Опять же, поскольку устройство вращается вокруг оси Yaw, это значение изменяется, а другие нет.

Перемещение устройства вокруг оси Roll:

enter image description here

: Yaw = 0, Pitch = 90, Roll = -20.

Теперь я не могу понять. Перемещение iPhone вокруг круга радиуса R (R > 0), как на этом рисунке:

enter image description here

Изменчивость меняется, пока Pitch и Roll не делают.

Я бы ожидал, что Yaw остался без изменений, и Roll изменился.

Как можно компенсировать это, поскольку меня интересуют исключительно вращения вокруг оси Yaw, сделанные пользователем?

Другая проблема, которую я имею, - это дрейф. IPhone находится в положении, описанном на втором рисунке, которое длительное время удерживается у меня в покое (1 минута или больше). Yaw постоянно увеличивается. Любая идея, как компенсировать дрейф?

Заранее благодарю

UPDATE Я следовал рекомендациям Кей, но ничего не меняется. Еще несколько деталей моего кода. Я хотел бы использовать Yaw для поворота UIImage только тогда, когда пользователь поворачивает устройство вокруг оси Yaw. Это работает, но когда пользователь поворачивается вокруг своей собственной вертикальной оси, изменяется Yaw. Я полагаю, что это неверно, поскольку, когда пользователь перемещается вокруг своей вертикальной оси, устройства не вращаются вокруг собственной оси Yaw. Может быть, я ошибаюсь. Это мой оригинальный код:

- (void)handleDeviceMotion:(CMDeviceMotion*)motion { 

   CMAttitude      *attitude = motion.attitude;

   NSLog(@"Yaw   %f ",attitude.yaw * 180 / M_PI);
   NSLog(@"Pitch %f ",attitude.pitch * 180 / M_PI);
   NSLog(@"Roll  %f ",attitude.roll * 180 / M_PI);

   image.transform = CGAffineTransformMakeRotation(-attitude.yaw);
}

Это код после предложения Kay:

- (void)handleDeviceMotion:(CMDeviceMotion*)motion { 

   CMAttitude      *attitude = motion.attitude;        

   if (startAttitude == 0) {

      startAttitude = attitude;
   }

   [attitude multiplyByInverseOfAttitude:startAttitude];

   NSLog(@"Yaw   %f ",attitude.yaw * 180 / M_PI);
   NSLog(@"Pitch %f ",attitude.pitch * 180 / M_PI);
   NSLog(@"Roll  %f ",attitude.roll * 180 / M_PI);


   image.transform = CGAffineTransformMakeRotation(-attitude.yaw);
}

Я запускаю мониторинг движения устройства с помощью

 [motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXArbitraryZVertical toQueue:[NSOperationQueue currentQueue]
                                                           withHandler: ^(CMDeviceMotion *motion, NSError *error){

                                                               [self performSelectorOnMainThread:@selector(handleDeviceMotion:) withObject:motion waitUntilDone:YES];
                                                           }];
4b9b3361

Ответ 1

[Полностью пересмотренный]

(1) Странные углы

На первый взгляд я принял ситуацию, столкнувшись с некоторыми типичными проблемами, связанными с Euler Angles. Поскольку они близки к этой проблемной области и действительно важно иметь в виду, я оставляю эту часть первоначального ответа. Проблемы с углом Эйлера:

  • Неоднозначность, поскольку соотношение между состоянием вращения и представлением Эйлера не является биективным, т.е. множество углов описывает один вращение, но поворот может быть представлен более чем одним набором углов Эйлера. В вашем вопросе, показанном на рисунке 3, вы можете добиться того же вращения с помощью 1: Yaw=30°, 2: Pitch=90° или 1: Pitch=90°, 2: Roll=30°
  • Задача Gimbal Lock: вы можете потерять одну степень свободы, и устройство больше не может вращаться вокруг одной из осей. Решение состоит в использовании кватернионов или матриц вращения.

Но, как вы сказали в своем комментарии, истинный виновник, похоже, является эталоном. Начиная с iOS 5.0 Apple улучшил алгоритм слияния датчиков и рассмотрел данные магнитного поля, а также вычислил CMAttitude. Хотя существует старый метод startDeviceMotionUpdates, теперь он использует ссылку по умолчанию CMAttitudeReferenceFrameXArbitraryZVertical, так что все измерения связаны с "осью Z вертикальна, а ось X указывает в произвольном направлении в горизонтальной плоскости".

Чтобы получить ваши данные относительно ссылки при запуске (или любом другом ротации), вам нужно сохранить экземпляр CMAttitude, который вы хотите использовать, и затем использовать CMAttitude multiplyByInverseOfAttitude, чтобы преобразовать любое новое отношение, т.е. в начале вашего метода handleDeviceMotion.

(2) Дрейф вращения копыт

Я думаю, что это связано с ошибкой в ​​iOS 6, подобной той, что я описал в дрейфующим углом рыскания после быстрого перемещения, поскольку он работал отлично в предыдущей версии. Я подал ошибку - посмотрим, когда они это исправит.


ОБНОВЛЕНИЕ 2

Поскольку комментарии и чаты показали, что целью было управлять роботом, просто наклонив устройство. В этом случае знание полного состояния вращения устройства является бесполезным при изменении направления ходьбы. Таким образом, подход с использованием чистого акселерометра с использованием CMDeviceMotion.gravity гораздо удобнее.