atan2 для двух синусоид произвольного фазового сдвига? - PullRequest
3 голосов
/ 08 мая 2019

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

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

Ответы [ 2 ]

8 голосов
/ 09 мая 2019

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).

1 голос
/ 09 мая 2019

Происхождение:

[y0; y1] = [sin(x); sin(x+phase)]  
         = [sin(x); sin(x) * cos(phase) + cos(x) * sin(phase)]
         = [0, 1; sin(phase), cos(phase)] * [cos(x); sin(x)]

Let M := [0, 1; sin(phase), cos(phase)]. Then det(M) = -sin(phase).
Suppose phase != k * pi, for any integer k. Then M is invertible and
inv(M) = [-cos(phase)/sin(phase), 1/sin(phase); 1, 0].

Let [u; v] := inv(M) * [y0; y1]
            = [(-y0 * cos(phase) + y1)/sin(phase); y0].  

Then [u; v] = [cos(x); sin(x)] and x = atan2 (v, u).

В коде:

// assume phase != k * pi, for any integer k
double f (double y0, double y1, double phase)
{
    double u = (- y0 * cos(phase) + y1) / sin(phase);
    double v = y0;

    double x = atan2 (v, u);
    return (x < 0) ? (x + 2 * M_PI) : x;
}
...