Pull to refresh

Comments 36

Когда то давно видел приложение с «умной калибровкой» гироскопа. Алгоритм такой — кладу телефон на стол, жму кнопку, поворачиваю вокруг вертикальной оси на 180 градусов, опять нажимаю. По двум измерениям программа вычисляла вертикаль даже в том случае если у меня кривой стол.

Увы, теперь не могу это приложение найти. Везде предлагается положить на горизонтальную поверхность и просто сбросить датчик. Но ведь действительно далеко не всегда есть уверенность в горизонтальности стола или пола…
Инетерсный способ, спасибо — попробую на досуге разобраться в этом с точки зрения 3D математики.
уже начинаю думать, что та программа мне приснилась)) Буду рад если метод сработает)
По идее должне работать нормально. Нужно только разобраться. При вращении 5S вектор гравитации значительно не изменился относительно телефона.
Вполне рабочий метод, у меня так как то сантехники правильность показаний строительного уровня проверяли.
Разобрался в математике — это отличный способ вычислить реальный вектор гравитации.
UFO just landed and posted this here
Поделюсь чуть позже.

Еще нужно поспать часа 3 и облечь все это в понятную векторную форму.

На вскидку, например, если нормально плоскости это гравитация, то в обе стороны будет отклонение -2°, что и есть погрешность.

Но плоскость в этом методе не обязательно должна быть перпендикулярной гравитации.

На наклонной плоскости при первом замере отклонение нормали плоскости от гравитации будет, скажем, -11°, а во втором уже -7° (в случае, когда я измерял это на наклоненной книжке). Здесь, соответственно, понятно, что реальное отклонение от гравитации -9°. Остается вычислить правильный вектор и превратить его в референсную матрицу 3х3, для учета ошибки акселерометра.
В векторном виде без оптимизации на вскидку это будет:

VE=(VG0-VG1*MR180)/2

Не забываем нормализовать все векторы.
UFO just landed and posted this here
Наверное, мне так проще воспринимать для понимания — да и много где в описании вычислений пишут «rotation about gravity».
Этим способом широко пользуются строители, при измерении наклона уровнем. Смотрят на пузырек уровня 2 раза повернув его на 180 град. Таким образом калибруется инструмент или отправляется на свалку, если оба варианта не сходятся как ни калибруй.
Хорошие методы вырастают из традиционных — только цифровой «уровень» еще можно вылечить калибровкой :)
Нормальные металлические плотницкие уровни вполне себе калибруются.
Несмотря на то, что устройство неподвижно с течением времени происходит смещение. На 00:09 смещается с 0° на 359°. На 01:21 уменьшается до 358°. На 03:03 мы уже видим азимут 357°.

Включаю компас на Nokia Lumia 920 в лесу, произвожу калибровку по инструкции приложения, получаю направление на север, кладу телефон на пенёк и наблюдаю чудное превращение стрелки компаса в стрелку часов. Стрелка крутится по кругу со скоростью примерно 1 градус в 1-4 секунды, описывая полный круг. Та же проблема повторяется в другом приложении, и на другом телефоне той же модели. Собственно вопрос в том, есть ли под Windows Phone приложение, которое компенсирует подобные погрешности?
Калибровка решает вопрос с изначальной ошибкой акселерометра. Когда он установлен не идеально относительно устройства. Для компенсации вибраций и мелких движений нужен массив датчиков, а в устройствах обычно только один датчик одного типа. В общем, да, это недостаток. Только в моем случае это около 1° в минуту.
Принцип везде одинаковый — сработает.

Есть еще метод вращения вокрук каждой оси по несколько раз, скажем, по три.

На iOS второй метот тоже вполне актуален.
Понятно. Благодарю.
А то, знаете-ли, вращать аппарат, одна из сторон которого чувствительна к малейшим прикосновениям, три раза по трём осям — непростая задачка. :-)
Так как делать калибровку датчиков?
Ну например возьмем Android. Как вариант мы подписываемся на обработку событий от акселерометра, магнитометр и дитчика положения:
sm.registerListener(sensorEventListener, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), sm.SENSOR_DELAY_NORMAL);
sm.registerListener(sensorEventListener, sm.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), sm.SENSOR_DELAY_NORMAL);
sm.registerListener(sensorEventListener, sm.getDefaultSensor(Sensor.TYPE_ORIENTATION), sm.SENSOR_DELAY_NORMAL);

и получаем сырые данные, из которых после обработки получаем нужные нам данные:
public void onSensorChanged(SensorEvent event)
{
	switch (event.sensor.getType())
	{
		case Sensor.TYPE_ACCELEROMETER:
			System.arraycopy(event.values, 0, mGravs, 0, 3);
			break;
		case Sensor.TYPE_MAGNETIC_FIELD:
			System.arraycopy(event.values, 0, mGeoMags, 0, 3);
			break;
		case Sensor.TYPE_ORIENTATION:
			System.arraycopy(event.values, 0, mOldOreintation, 0, 3);
			break;
		default:
			return;
	}

	if (mGravs != null && mGeoMags != null)
	{
		if (SensorManager.getRotationMatrix(mRotationM, mInclinationM, mGravs, mGeoMags))
		{
			SensorManager.getOrientation(mRotationM, mOrientation);
			// TODO
		}
	}
}


В каком месте здесь можно вносить какие-либо корректировки и какого плана эти корректировки должны быть?
Однозначный ответ здесь дать нельзя. Зависит от того в какой ориентации работает приложение, каким методом калибруется и т.п… Но смысл везде примерно одинаковый — на выходе нам нужно получить коррекционную матрицу 3х3, умножив на которую вектор мы получим вектор с учетом поправки сенсора.

У меня как-то так работает:

mat3 calibration_rotation_matrix_from_gravity(vec3 gravity)
{
	/*
	 
	 The calibration is per orientation.
	 The rotation origin is a gravity should be axis.
	 
	 *** rules ***
	 
	 A == G * M0
	 G == A * Mt
	 
	 (1) M0 - the rotation matrix
	 (2) Mt - the transpose matrix of the rotation matrix
	 
	 */
	vec3 a=vec3_normalize(gravity);
	vec3 b=vec3_normalize(vec3_most_significant_basis_vector(gravity));
	mat3 m=mat3_make_rotation_ab(a,b);
	return(m);
}
Здесь соответвенно считается, то настоящая гравити это вектор «b», за который берется наибольший базисный вектор от гравитации, если при этом устройство лежит какой-либо гранью на идеально выравненной плоской поверхности.
Ну вот это как раз и интересовало — как физически делать какую-либо калибровку. Ожидал увидеть какие-то формулы…
Еще интересный аспект — дитчики ведь на самом деле не калибруются. Калибруется только приложение, которое эти датчики использует.
Я разрабатывал что-то подобное на просмотр google street view и столкнулся с неточностью определения положения в пространстве. После некоторых попыток задействовать фильтрацию, я решил «подсмотреть» как сделано в том-же google street view — там была некоторая простая математика с матрицами.
Ну вот она и есть математика, выше =)
1. Фильтр Калмана для коррекции ошибок используете?
2. Слышал о такой штуке, как Sensor Fusion, правда в контексте андроида. Что она из себя представляет?
3. Есть какие-то данные о том, сколько замеров в секунду выдают эти сенсоры?
1)

В чистом виде ФК не решит проблему дрифта, если пользоваться данными только от одного сенсора, поэтому техники совмещения данных от всех доступных сенсоров подобные SF это выход.

Здесь неплохое видео, которое объясняет технические детали, включая и про ФК:
www.youtube.com/watch?v=C7JQ7Rpwn2k

Если кратко, то, например, дрифт гироскопа это как раз и есть результат фильтрации шума.

В iOS аналогичная технология фильтрации данных зашита в CoreMotion. Она работает и развивается уже достаточно давно. Фильтрация на уровне драйвров CM появилась с 2010 года.

2)

Sensor Fusion штука более интересная и отвечает на большее число вопросов, но она также подвержена аналогичным недостаткам — просто так недостатки железа не обойдешь софтом, ошибка все равно будет накапливаться и точность, актуальность ориентации будет теряться со временем.

Панацеи решения вопросов потери данных в дискретных датчиках софтом я пока не вижу.

Знать недостатки сенсоров и пользоваться приложениями их использующими зная эти недостатки все равно будет нужно.

3)

Эти данные тщательно обычно скрываются.

Часть удается установить опытным путем, как, например, FOV камеры — часть искать на сайтах производителей, когда какой Chip Works разберет устройство на части и идентифицирует конкретные компоненты.

Единственное, что я видел, на одном из WWDC рассказали, что акселерометр и гироскоп в новом дивайсе имеют разрешение (частоту) в N раз больше, чем в предыдущих поколениях устройств, не вдаваясь в конкретные числа.
Реализовать самим нечто подобное и реально работающее врядли получится. Почему — ясно из презентации SF от Google по ссылке выше, а также рассказывалось на WWDC про Core Motion от Apple. Для вычислений используются данные недоступные разработчикам (как, например, температура), что Apple сказал прямым текстом, а у Google это мельком заметно на слайде.
Спасибо за подробные ответы. Интересно, почему производители не пробуют ставить по 2-3 MEMS-датчика каждого типа. Они ведь весьма дешевы и компактны.
Полагаю расход питания, патенты, стоимость играют роль — полагаю, что эта будет развиваться со временем.
Где посмотреть детали по сенсорам? Например латентность
А еще хочу посмотреть более детально, как учитывается вращение для корректировки данных акселерометра.
Оветил выше в пункте 3 — обычно эти данные трательно скрываются.
Смотря, что понимать под вращением.

Если это калибрация поворотом на 180 градусов, то я писал формулу вычисления коррекционного вектора выше в комментах:

VE=(VG0-VG1*MR180)/2 — если не ошибся. Здесь замеры гравитации в двух положениях и матрица поворота на 180 градусов по нужной оси. Векторы нужно нормализовать.

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

Автоматическая и идеальная же коррекция здесь нереальна — Sensor Fusion (что точно известно) и Core Motion (предположительно) скорее, наоборот, гироскоп компенсируют данными акселерометра.
Не. Я имел в виду — как учитывать влияние вращательного движения на отклонения в показаниях акселерометра. Вы же не будете отрицать, что акселерометр, движущийся с вами по петле американских горок будет показывать все время вертикально вниз к поверхности?! (Ну это простейший пример, — у меня планируется чуть сложнее). Он потому и акселерометр, а не гравитометр, что показывает ускорение, а не чисто гравитацию.
Фильтры для акселерометра предназначены как раз для разделения ускорения и гравитации.

Как их объядиняют с гироскопом описано здесь — схемы, математика, код:
www.thousand-thoughts.com/2012/03/android-sensor-fusion-tutorial/

Схема:


Идеалом это тоже не является, но помогает.

Похожие технологии уже зашиты в Android и iOS на уровне драйверов, но дрифт небольшой все равно остается.
На видео снят компас в режиме «гирокомпаса» настроенный точно на север запущен на устройстве, которое неподвижно лежит на столе. Несмотря на то, что устройство неподвижно с течением времени происходит смещение. На 00:09 смещается с 0° на 359°. На 01:21 уменьшается до 358°. На 03:03 мы уже видим азимут 357°.


А разве это погрешность датчика, а не следствие вращения Земли вокруг оси?
В частности это результат шумоподавления.

Сами шумы вызваны множеством факторов — вибрации от вентиляторов в мониторе и компе, сердцебиение и пульс пользователя, метро проходящее рядом и так далее.

Вращение земли, как фактор можно не рассматривать — его влияние настолько мало, что не будет заметно датчиками.
Sign up to leave a comment.

Articles