Средняя функция сенсорных данных в Android

Я пытаюсь построить средневзвешенное значение из данных датчиков, которые я получаю с помощью SensorManager. Моя проблема в том, что азимут, тангаж и крен имеют максимальное значение, и когда я нахожусь именно в этой точке, значения меняются от 0 до 359 или наоборот. Мое среднее значение на данный момент представляет собой просто сложение всех значений и одно деление на количество значений.

Допустим, я получаю значения: 1, 359, 350, 10. В этом случае я хочу, чтобы среднее значение равнялось 0. Как мне изменить уравнение, чтобы получить эту функциональность?

Должен ли я проверять «ближайшее» расстояние до 0/360 и использовать это значение вместо реального значения?

Это также создаст некоторые проблемы, если у меня будут значения около 180:

160, 200 -> среднее значение должно быть 180, но с моей идеей ближайшего расстояния это будет 160, потому что 200 + 160 = 360.

Как я могу это решить?

Изменить: это значения, которые я получаю от SensorManager.

  • 0 ‹= азимут‹360
  • 180‹=шаг‹=180
  • 90‹=рулон‹=90

Edit2: Извините, я забыл упомянуть, что использую средневзвешенное значение:

double sum = 0;
for int i = 0; i < max; i++
   sum += value[i] * (i / (triangular_number(max))
return sum

person Frame91    schedule 31.05.2013    source источник
comment
В вашем алгоритме попробуйте добавить все azimuth и посмотреть, являются ли они целым числом, кратным 360. Если это так, то вы можете оставить значение равным 0, как вы хотели. Я вижу в этом один из паттернов, которым вы можете воспользоваться.   -  person Shobhit Puri    schedule 01.06.2013
comment
Эй, я думаю, вы неправильно поняли мой вопрос;) Я не ищу модульную функцию, моя проблема - это среднее значение таких значений, как 350, 10, 330, 30, которое должно быть равно нулю, но математически это около 180   -  person Frame91    schedule 01.06.2013


Ответы (2)


Для вычисления среднего значения угла используйте следующее

public static final float averageAngle(float[] terms, int totalTerm)
{
    float sumSin = 0;
    float sumCos = 0;
    for (int i = 0; i < totalTerm; i++)
    {
        sumSin += Math.sin(terms[i]);
        sumCos += Math.cos(terms[i]);
    }
    return (float) Math.atan2(sumSin / totalTerm, sumCos / totalTerm);
}
person Hoan Nguyen    schedule 01.06.2013
comment
Привет. Спасибо! Торбен уже упоминал эту формулу. Но как я могу реализовать средневзвешенное значение с этим? где я должен умножить значение на свой вес? - person Frame91; 01.06.2013
comment
Зачем вам взвешенное среднее? - person Hoan Nguyen; 01.06.2013
comment
Я просто тестирую несколько разных методов;) и, поскольку обычно чем новее, тем лучше, я хочу добавить вес в свою формулу. - person Frame91; 01.06.2013
comment
Вы должны положить свой вес на угол, прежде чем вычислять среднее значение. - person Hoan Nguyen; 01.06.2013
comment
так что вы имеете в виду как: sumSin += Math.sin(terms[i] * weight) ? Я сделал это, но я не получаю от этого никакой пользы. atan2((sin(x*0.4) + sin(x*0,6)), (cos(x*0.4) + cos(x*0.6))) должен возвращать x, потому что значение не изменилось, но это не так. 'т. - person Frame91; 01.06.2013
comment
sin (x * 0,4) + sin (x * 0,6) не является sin (x), поэтому atan2 выше не является x. - person Hoan Nguyen; 01.06.2013
comment
Хм, я не знаю, как с этим справиться. Можете ли вы дать мне подсказку? - person Frame91; 01.06.2013
comment
atan2(sin(300) + sin(300), cos(300)+ cos(300)) = -60 = 300 , хм... вы имели в виду перед вычислением среднего, где в вашей формуле вы упоминаете, я должен используй это? Я думал, что моя догадка была верна :/ - person Frame91; 01.06.2013
comment
Мне нужно знать причину, по которой вы хотите сделать средневзвешенное значение, прежде чем я смогу предложить, что делать. Вместо угла вы можете усреднить матрицы вращения, а затем вычислить углы, используя getOrientation. В данном случае это обычное среднее значение. - person Hoan Nguyen; 01.06.2013
comment
Причина в том, что более новые значения обычно более точны, чем старые значения, поэтому я просто хочу иметь немного от старых значений, но в целом я хочу иметь самое новое значение. Это просто для проверки того, какие методы сглаживания сенсорных данных наиболее полезны для моего приложения, где я проецирую что-то на свой дисплей, что зависит от моего направления;) - person Frame91; 01.06.2013
comment
В этом случае сделайте так, чтобы новый считался несколько раз. Например, если более новый угол равен 1,5, сделайте его несколько раз 1,5, 1,5, 1,5 (например, 3 раза) - person Hoan Nguyen; 01.06.2013
comment
Боже... просто, но круто! Большое Вам спасибо :)) - person Frame91; 01.06.2013

Я нашел сообщение в блоге об этом.

Подводя итог: вам нужно рассчитать среднее значение синусов всех ваших значений айзмута и среднее значение косинусов значений айзмута, а затем поместить эти средние значения в функцию atan2, а затем, при необходимости, сделать результат положительным, добавив 2 * ЧИСЛО ПИ. Не забудьте преобразовать значения градусов в радианы и наоборот.

person Torben Kohlmeier    schedule 31.05.2013
comment
Спасибо! Можно ли использовать на нем функцию средневзвешенного значения? Я забыл упомянуть, что он должен быть взвешен (значение * (индекс/размер)). Спасибо! - person Frame91; 01.06.2013
comment
Я не уверен, но я думаю, что это должно работать и со средневзвешенным значением. Среднее значение, которое я упомянул, является средним арифметическим, поэтому вместо этого вы можете просто попробовать использовать взвешенное среднее арифметическое. - person Torben Kohlmeier; 01.06.2013
comment
ХМ, я не получаю хороших результатов, когда пытаюсь комбинировать его с весом... Здесь я добавил функцию веса: sumSin += Math.sin(bearing)* (weight); то же самое с cos, а затем в конце atan2(sin,cos). Или мне нужно поместить расчет веса в другое место? - person Frame91; 01.06.2013
comment
Это должно быть правильно. Вы делили на сумму весов? - person Torben Kohlmeier; 02.06.2013