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

M

Mr. Ken

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

BRG

Mr. Ken said:
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
 
R

Robert Mabee

BRG said:
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.
 
B

BRG

Robert said:
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
 
J

Jim Langston

BRG said:
Robert said:
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?
 
B

BRG

Jim said:
BRG said:
Robert said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top