Усреднение углов … Снова

Я думаю, что очевидное использование как ярлык. Если Вы, например, инициализация объекта, Вы просто сохраняете ввод большого "Имени объекта". Отчасти как шепелявость,"со слотами", который позволяет Вам записать

(with-slots (foo bar) objectname
   "some code that accesses foo and bar"

, который совпадает с записью

"some code that accesses (slot-value objectname 'foo) and (slot-value objectname 'bar)""

, более очевидно, почему это - ярлык тогда, когда Ваш язык позволяет "Objectname.foo", но все еще.

18
задан Lior Kogan 6 August 2014 в 18:20
поделиться

10 ответов

Спасибо всем за то, что помогли мне разобраться в моей проблеме. более ясно.

Я нашел то, что искал. Он называется методом Мицута .

Входные и выходные данные находятся в диапазоне [0..360).

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

Метод предполагает, что разница между последовательными выборками составляет менее 180 градусов (что означает, что если мы не будем производить выборку достаточно быстро, изменение выборочного сигнала на 330 градусов будет неправильно обнаружено как изменение на 30 градусов в другом направлении и вставит ошибку в расчет). Кто-нибудь из теоремы выборки Найквиста – Шеннона?

Вот код на C ++:

double AngAvrg(const vector<double>& Ang)
{
    vector<double>::const_iterator iter= Ang.begin();

    double fD   = *iter;
    double fSigD= *iter;

    while (++iter != Ang.end())
    {
        double fDelta= *iter - fD;

             if (fDelta < -180.) fD+= fDelta + 360.;
        else if (fDelta >  180.) fD+= fDelta - 360.;
        else                     fD+= fDelta       ;

        fSigD+= fD;
    }

    double fAvrg= fSigD / Ang.size();

    if (fAvrg >= 360.) return fAvrg -360.;
    if (fAvrg <  0.  ) return fAvrg +360.;
                       return fAvrg      ;
}

Он объяснен на странице 51 по адресу http://www.epa.gov/scram001/guidance/met/mmgrma. pdf

Спасибо, MaR, за отправку ссылки в качестве комментария.

Если выборочные данные постоянны,

9
ответ дан 30 November 2019 в 07:13
поделиться

Что это вообще значит для усреднения пеленгов источника? Начните с ответа на этот вопрос, и вы приблизитесь к тому, чтобы определить, что вы подразумеваете под средним значением углов.

На мой взгляд, угол с тангенсом, равным 1/2, является правильным ответом. Если у меня есть единичная сила, толкающая меня в направлении вектора (1, 0), другая сила толкает меня в направлении вектора (1, 0), а третья сила толкает меня в направлении вектора (0, 1 ), то результирующая сила (сумма этих сил) будет силой, толкающей меня в направлении (1, 2). Это векторы, представляющие пеленг 0 градусов, 0 градусов и 90 градусов. Угол, представленный вектором (1, 2), имеет тангенс, равный 1/2.

В ответ на ваше второе изменение:

Допустим, мы измеряем направление ветра. Наши 3 измерения были 0, 0 и 90 градусов. Поскольку все измерения одинаково надежны, почему наша лучшая оценка направления ветра не должна составлять 30 градусов? установка на 25,56 градуса - это смещение в сторону 0 ...

Хорошо, вот в чем проблема. Единичный вектор с углом 0 не имеет тех же математических свойств, что и действительное число 0. Используя обозначение 0v для представления вектора с углом 0, обратите внимание, что

0v + 0v = 0v

неверно, но

0 + 0 = 0

верно для действительных чисел. Таким образом, если 0v представляет ветер с единичной скоростью и углом 0, то 0v + 0v - ветер с удвоенной единичной скоростью и углом 0.

3
ответ дан 30 November 2019 в 07:13
поделиться

На мой взгляд, это касается углов, а не векторов. По этой причине среднее значение 360 и 0 действительно равно 180. Среднее значение одного поворота и отсутствия поворотов должно составлять пол-оборота.

2
ответ дан 30 November 2019 в 07:13
поделиться

[ Примечание вопрос ОП (но не заголовок), похоже, изменился на довольно специализированный вопрос ("... среднее значение ПОСЛЕДОВАТЕЛЬНОСТИ углов, где каждый следующий сложение не отличается от текущего среднего более чем на указанную величину. ") - см. комментарий @MaR и мой. Мой следующий ответ касается заголовка ОП и основной части обсуждения и ответов, связанных с ним. ]

Это не вопрос логики или интуиции, а вопрос определения. Это обсуждалось на SO раньше без какого-либо реального консенсуса. Углы должны быть определены в пределах диапазона (который может быть от -PI до + PI, от 0 до 2 * PI или может быть от -Inf до + Inf. В каждом случае ответы будут разными.

Мировой "угол" вызывает путаница, поскольку это означает разные вещи. Мы не можем переопределить квадратный корень из -4 в -2, потому что он более информативен - он должен быть + -2 * i. Точно так же среднее значение пеленгов -90 градусов и +90 градусов является вектором нулевой длины, а не 0,0 градуса.

Википедия ( http://en.wikipedia.org/wiki/Mean_of_circular_quantities ) имеет специальный раздел и состояния (уравнения представляют собой LaTeX, их можно увидеть в Википедии):

Большинство обычных средств не работают круговые величины, такие как углы, дневное время, дробные части реального числа. Для тех количеств, которые вам нужны среднее круговых величин.

Так как среднее арифметическое не эффективны для углов следующие может использоваться для получения как среднее значение и мера для отклонение углов:

Преобразуйте все углы в соответствующие точки на единичной окружности, например, от α до (cosα, sinα). Это преобразовать полярный координаты в декартовой системе координат. Затем вычислите среднее арифметическое эти точки. Полученная точка будет лежат на единичном диске. Преобразуйте это укажите обратно в полярные координаты. В угол - разумное среднее значение входные углы. Результирующий радиус будет 1, если все углы равны. Если углы распределены равномерно по кругу, то получившийся радиус будет 0, и нет круговое среднее. Другими словами, радиус измеряет концентрацию углы.

Учитывая углы \ alpha_1, \ dots, \ alpha_n среднее значение вычислено

 M \ alpha = \ operatorname {atan2} \ left (\ frac {1} {n} \ cdot \ sum_ {j = 1} ^ n

\ sin \ alpha_j, \ гидроразрыва {1} {n} \ cdot \ sum_ {j = 1} ^ n \ cos \ alpha_j \ right)

с использованием варианта atan2 функция арктангенса или

 M \ alpha = \ arg \ left (\ frac {1} {n} \ cdot \ sum_ {j = 1} ^ n

\ exp (i \ cdot \ alpha_j) \ right)

с использованием комплексных чисел.

Обратите внимание, что в вопросе OP угол 0 является чисто произвольным - нет ничего особенного в ветре, исходящем из 0, в отличие от до 180 (кроме этого полушария на велосипеде холоднее). Попробуйте изменить 0,0,90 на 289, 289, 379 и посмотрите, как простая арифметика больше не работает.

(Там есть некоторые распределения, в которых углы 0 и PI имеют особое значение, но не в объеме здесь).

Вот некоторые интенсивные предыдущие дискуссии, которые отражают текущий разброс взглядов: -)

http://mathforum.org/library/drmath/view/53924.html

Как рассчитать среднее значение набор круговых данных?

http://forums.xkcd.com/viewtopic.php?f=17&t=22435

http: //www.allegro. cc / forum / thread / 595008

18
ответ дан 30 November 2019 в 07:13
поделиться

Редактировать: Эквивалентный, но более надежный алгоритм (и более простой):

  1. разделить углы на 2 группы, [0-180) и [180-360)
  2. численно усреднить обе группы
  3. усреднить 2 средние группы с надлежащим взвешиванием
  4. , если произошло повторение, исправить на 180 °

Это работает, потому что усреднение чисел работает «логически», если все углы находятся в одном полукруге. Затем мы откладываем получение ошибки обхода до самого последнего шага, где ее легко обнаружить и исправить. Я также добавил код для обработки случаев с противоположным углом. Если средние значения противоположны, мы отдаем предпочтение полушарию, в котором больше углов, а в случае равных углов в обоих полушариях мы возвращаем Нет , потому что среднее значение не имеет смысла.

Новый код:

def averageAngles2(angles):
    newAngles = [a % 360 for a in angles];
    smallAngles = []
    largeAngles = []
    # split the angles into 2 groups: [0-180) and [180-360)
    for angle in newAngles:
        if angle < 180:
            smallAngles.append(angle)
        else:
            largeAngles.append(angle)
    smallCount = len(smallAngles)
    largeCount = len(largeAngles)
    #averaging each of the groups will work with standard averages
    smallAverage = sum(smallAngles) / float(smallCount) if smallCount else 0
    largeAverage = sum(largeAngles) / float(largeCount) if largeCount else 0
    if smallCount == 0:
        return largeAverage
    if largeCount == 0:
        return smallAverage
    average = (smallAverage * smallCount + largeAverage * largeCount) / \
        float(smallCount + largeCount)
    if largeAverage < smallAverage + 180:
        # average will not hit wraparound
        return average
    elif largeAverage > smallAverage + 180:
        # average will hit wraparound, so will be off by 180 degrees
        return (average + 180) % 360
    else:
        # opposite angles: return whichever has more weight
        if smallCount > largeCount:
            return smallAverage
        elif smallCount < largeCount:
            return largeAverage
        else:
            return None

>>> averageAngles2([0, 0, 90])
30.0
>>> averageAngles2([30, 350])
10.0
>>> averageAngles2([0, 200])
280.0

Вот несколько наивный алгоритм:

  1. удалить все противоположные углы из списка
  2. взять пару углов
  3. повернуть их в первый и второй квадрант и усреднить их
  4. повернуть средний угол обратно на ту же величину
  5. для каждого оставшегося угла, среднее значение таким же образом, но с последовательным увеличением веса до составного угла

некоторый код Python (шаг 1 не реализован)

def averageAngles(angles):
    newAngles = [a % 360 for a in angles];
    average = 0
    weight = 0
    for ang in newAngles:
        theta = 0
        if 0 < ang - average <= 180:
            theta = 180 - ang
        else:
            theta = 180 - average
        r_ang = (ang + theta) % 360
        r_avg = (average + theta) % 360
        average = ((r_avg * weight + r_ang) / float(weight + 1) - theta) % 360
        weight += 1
    return average

2
ответ дан 30 November 2019 в 07:13
поделиться

Вы можете сделать это: скажем, у вас есть набор углов в массиве angle , затем для вычисления массива сначала выполните: angle [i] = angle [i] mod 360 , теперь выполняется простое усреднение по массиву. Итак, когда у вас есть 360, 10, 20, вы усредняете 0, 10 и 20 - результаты интуитивно понятны.

0
ответ дан 30 November 2019 в 07:13
поделиться

Что плохого в том, чтобы принимать набор углов как действительные значения и просто вычислять среднее арифметическое этих чисел? Тогда вы получите интуитивно понятное (0 + 0 + 90) / 3 = 30 градусов.

Правка : Спасибо за полезные комментарии и указание на то, что углы могут превышать 360. Я считаю, что ответом может быть обычное среднее арифметическое. уменьшенный "по модулю" 360: мы суммируем все значения, делим на количество углов, а затем вычитаем / добавляем кратное 360 так, чтобы результат лежал в интервале [0..360).

0
ответ дан 30 November 2019 в 07:13
поделиться

Я думаю, проблема связана с тем, как вы относитесь к углам больше 180 (а также к углам больше 360). Если вы уменьшите углы до диапазона от +180 до -180 перед добавлением их к общей сумме, вы получите нечто более разумное:

int AverageOfAngles(int angles[], int count)
{
    int total = 0;
    for (int index = 0; index < count; index++)
    {
        int angle = angles[index] % 360;
        if (angle > 180) { angle -= 360; }
        total += angle;
    }

    return (int)((float)total/count);
}
0
ответ дан 30 November 2019 в 07:13
поделиться

Это неверно на каждом уровне.

Векторы складываются согласно правилам сложения векторов. «Интуитивный, ожидаемый» ответ может быть не таким интуитивным.

Возьмем следующий пример. Если у меня есть один единичный вектор (1, 0) с началом в (0,0), который указывает в + x-направлении, и другой (-1, 0), который также имеет начало в (0,0), которое указывает в Направление -x, каким должен быть «средний» угол?

Если я просто сложу углы и разделю на два, я могу утверждать, что «средний» равен +90 или -90. Как вы думаете, какой из них должен быть?

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

(1, 0) + (-1, 0) = (0, 0)

В полярных координатах это вектор с нулевой величиной и нулевым углом.

Итак, что должно быть "

3
ответ дан 30 November 2019 в 07:13
поделиться

Возможно, вы могли бы представить углы в виде кватернионов и возьмите среднее значение этих кватернионов и преобразуйте его обратно в угол.

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

Кватернионы в 2D упрощаются до комплексных чисел, поэтому я предполагаю, что это просто векторы, но, возможно, какой-нибудь интересный алгоритм усреднения кватернионов, например http: // ntrs. nasa.gov/archive/nasa/casi.ntrs.nasa.gov/20070017872_2007014421.pdf при упрощении до 2D будет вести себя лучше, чем просто векторное среднее.

0
ответ дан 30 November 2019 в 07:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: