By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,864 Members | 1,293 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,864 IT Pros & Developers. It's quick & easy.

How do I handle atan() when calculating absolute phase? (Communication engineering)

P: n/a
I am calculating the phase of an IQ signal, which are polluted by AWGN
gaussian
noise. Thus, near pi/2, direct division of atan(Q/I) may yield outputs
either +pi/2 or
-pi/2. How do I handle this situation?

Thanks.
May 4 '06 #1
Share this Question
Share on Google+
5 Replies


P: n/a
BRG
Mr. Ken wrote:
I am calculating the phase of an IQ signal, which are polluted by AWGN
gaussian
noise. Thus, near pi/2, direct division of atan(Q/I) may yield outputs
either +pi/2 or
-pi/2. How do I handle this situation?


As well as having the function atan(x), your system is likely to have
atan2(y, x) which eliminates the ambiguity except when x and y are both
zero.

Brian Gladman
May 4 '06 #2

P: n/a
BRG wrote:
Mr. Ken wrote:
I am calculating the phase of an IQ signal, which are polluted by AWGN
gaussian noise.


As well as having the function atan(x), your system is likely to have
atan2(y, x) which eliminates the ambiguity except when x and y are both
zero.


atan2 avoids infinity, and I think gives a full +/-pi range, but there's
still a massive jump in the number that represents phase, so you can't
just average that number to remove noise. You can smooth x and y first,
or smooth a modified phase w/ 2pi added or subtracted to keep it near
the recent average, and jump the average when it goes out of range.
May 4 '06 #3

P: n/a
BRG
Robert Mabee wrote:
BRG wrote:
Mr. Ken wrote:
I am calculating the phase of an IQ signal, which are polluted by AWGN
gaussian noise.


As well as having the function atan(x), your system is likely to have
atan2(y, x) which eliminates the ambiguity except when x and y are both
zero.


atan2 avoids infinity, and I think gives a full +/-pi range, but there's
still a massive jump in the number that represents phase, so you can't
just average that number to remove noise.


[snip]
You can at +pi/2 and -pi/2, the points to which the original poster
specifically referred.

When two quadrature signals I and Q are available, atan2(Q, I) is better
than atan(Q/I) since it not only eliminates the division by zero problem
but also eliminates the artificial phase ambiguity _introduced_ by
atan(Q/I) at +pi/2 and -pi/2.

Noise will still be an issue at +pi and -pi but at least atan2(Q, I)
won't produce the incorrect results given by atan(Q/I) near +pi/2 and
-pi/2 caused by essentially ignoring a good sign on Q when I is small.

Brian Gladman
May 5 '06 #4

P: n/a

"BRG" <br*@nowhere.org> wrote in message
news:44**********************@ptn-nntp-reader01.plus.net...
Robert Mabee wrote:
BRG wrote:
Mr. Ken wrote:
I am calculating the phase of an IQ signal, which are polluted by AWGN
gaussian noise.

As well as having the function atan(x), your system is likely to have
atan2(y, x) which eliminates the ambiguity except when x and y are both
zero.


atan2 avoids infinity, and I think gives a full +/-pi range, but there's
still a massive jump in the number that represents phase, so you can't
just average that number to remove noise.


[snip]
You can at +pi/2 and -pi/2, the points to which the original poster
specifically referred.

When two quadrature signals I and Q are available, atan2(Q, I) is better
than atan(Q/I) since it not only eliminates the division by zero problem
but also eliminates the artificial phase ambiguity _introduced_ by
atan(Q/I) at +pi/2 and -pi/2.

Noise will still be an issue at +pi and -pi but at least atan2(Q, I)
won't produce the incorrect results given by atan(Q/I) near +pi/2 and
-pi/2 caused by essentially ignoring a good sign on Q when I is small.


Hmm... Let's see how much of this mess it cleans up:

float CalcTheta( const JVEC2 Point1, const JVEC2 Point2 )
{
float Theta;
if ( Point2.x - Point1.x == 0 )
if ( Point2.y > Point1.y )
Theta = 0;
else
Theta = static_cast<float>( PI );
else
{
Theta = std::atan( (Point2.y - Point1.y) / (Point2.x - Point1.x) );
if ( Point2.x > Point1.x )
Theta = static_cast<float>( PI ) / 2.0f - Theta;
else
Theta = static_cast<float>( PI ) * 1.5f - Theta;
};

return Theta;
}

would become...

float CalcTheta( const JVEC2 Point1, const JVEC2 Point2 )
{
float Theta;
Theta = std::atan2( (Point2.y - Point1.y) / (Point2.x - Point1.x) );
if ( Point2.x > Point1.x )
Theta = static_cast<float>( PI ) / 2.0f - Theta;
else
Theta = static_cast<float>( PI ) * 1.5f - Theta;
};

return Theta;
}

Is that all that can be simplified?


May 6 '06 #5

P: n/a
BRG
Jim Langston wrote:
"BRG" <br*@nowhere.org> wrote in message
news:44**********************@ptn-nntp-reader01.plus.net...
Robert Mabee wrote:
BRG wrote:
Mr. Ken wrote:
> I am calculating the phase of an IQ signal, which are polluted by AWGN
> gaussian noise.
As well as having the function atan(x), your system is likely to have
atan2(y, x) which eliminates the ambiguity except when x and y are both
zero.
atan2 avoids infinity, and I think gives a full +/-pi range, but there's
still a massive jump in the number that represents phase, so you can't
just average that number to remove noise.

[snip]
You can at +pi/2 and -pi/2, the points to which the original poster
specifically referred.

When two quadrature signals I and Q are available, atan2(Q, I) is better
than atan(Q/I) since it not only eliminates the division by zero problem
but also eliminates the artificial phase ambiguity _introduced_ by
atan(Q/I) at +pi/2 and -pi/2.

Noise will still be an issue at +pi and -pi but at least atan2(Q, I)
won't produce the incorrect results given by atan(Q/I) near +pi/2 and
-pi/2 caused by essentially ignoring a good sign on Q when I is small.


Hmm... Let's see how much of this mess it cleans up:

float CalcTheta( const JVEC2 Point1, const JVEC2 Point2 )
{
float Theta;
if ( Point2.x - Point1.x == 0 )
if ( Point2.y > Point1.y )
Theta = 0;
else
Theta = static_cast<float>( PI );
else
{
Theta = std::atan( (Point2.y - Point1.y) / (Point2.x - Point1.x) );
if ( Point2.x > Point1.x )
Theta = static_cast<float>( PI ) / 2.0f - Theta;
else
Theta = static_cast<float>( PI ) * 1.5f - Theta;
};

return Theta;
}

would become...

float CalcTheta( const JVEC2 Point1, const JVEC2 Point2 )
{
float Theta;
Theta = std::atan2( (Point2.y - Point1.y) / (Point2.x - Point1.x) );
if ( Point2.x > Point1.x )
Theta = static_cast<float>( PI ) / 2.0f - Theta;
else
Theta = static_cast<float>( PI ) * 1.5f - Theta;
};

return Theta;
}

Is that all that can be simplified?


float CalcTheta( const JVEC2 Point1, const JVEC2 Point2 )
{
return std::atan2( Point2.x - Point1.x, Point2.y - Point1.y );
}

is an even simpler solution.

Brian Gladman
May 6 '06 #6

This discussion thread is closed

Replies have been disabled for this discussion.