atan2 для двух синусоид произвольного фазового сдвига?

Я пытаюсь реализовать функцию, подобную atan2, для сопоставления двух входных синусоидальных сигналов произвольного относительного фазового сдвига с одним выходным сигналом, который линейно идет от 0 до . atan2 обычно предполагает наличие двух сигналов со сдвигом фазы на 90 градусов.

Учитывая y0(x) = sin(x) и y1 = sin(x + phase), где phase — фиксированное ненулевое значение, как я могу реализовать способ возврата x по модулю ?


person tarabyte    schedule 08.05.2019    source источник
comment
Является ли это правильной постановкой задачи: учитывая, что y0 и y1 равны sin(x) и sin(x+phase), где фаза — константа, вернуть x по модулю 2π?   -  person Eric Postpischil    schedule 08.05.2019
comment
Пожалуйста, переформулируйте проблему точно, так как она не ясна. atan2(y,x) работает с y и x и вычисляет угол линии, проходящей от (0,0) и (x,y) относительно положительной оси x, что дает результат от -π, исключенного до + π включено.   -  person George Kourtis    schedule 08.05.2019
comment
Примечание: -π <= atan2() <= +π, а не тот же диапазон, что и [0...2π), и fmod(a, 2*M_PI).   -  person chux - Reinstate Monica    schedule 09.05.2019
comment
Это больше похоже на математический вопрос, чем на вопрос программирования.   -  person user253751    schedule 09.05.2019


Ответы (2)


atan2 возвращает угол двумерного вектора. Ваш код не обрабатывает такое масштабирование должным образом. Но не беспокойтесь, на самом деле очень легко свести вашу проблему к atan2, которая прекрасно со всем справится.

Обратите внимание, что вычисление sin(x) и sin(x + phase) аналогично проецированию точки (cos(x), sin(x)) на оси (0, 1) и (sin(phase), cos(phase)). Это то же самое, что скалярное произведение по этим осям или преобразование системы координат из стандартной ортогональной в асимметричную. Это предлагает простое решение: инвертировать преобразование, чтобы получить координаты в ортогональном базисе, а затем использовать atan2.

Вот код, который делает это:

double super_atan2(double x0, double x1, double a0, double a1) {
    double det = sin(a0 - a1);
    double u = (x1*sin(a0) - x0*sin(a1))/det;
    double v = (x0*cos(a1) - x1*cos(a0))/det;
    return atan2(v, u);
}

double duper_atan2(double y0, double y1, double phase) {
    const double tau = 6.28318530717958647692; // https://tauday.com/
    return super_atan2(y0, y1, tau/4, tau/4 - phase);
}

super_atan2 получает углы двух осей проекции, duper_atan2 решает задачу именно так, как вы указали.

Также обратите внимание, что вычисление det не является строго обязательным. Его можно заменить на fmod и copysign (нам еще нужен правильный знак u и v).

person Yakov Galka    schedule 08.05.2019