457,864 Members | 1,293 Online 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
5 Replies

 P: n/a 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 AWGNgaussian 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 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" 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( PI ); else { Theta = std::atan( (Point2.y - Point1.y) / (Point2.x - Point1.x) ); if ( Point2.x > Point1.x ) Theta = static_cast( PI ) / 2.0f - Theta; else Theta = static_cast( 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( PI ) / 2.0f - Theta; else Theta = static_cast( PI ) * 1.5f - Theta; }; return Theta; } Is that all that can be simplified? May 6 '06 #5

 P: n/a Jim Langston wrote: "BRG" 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( PI ); else { Theta = std::atan( (Point2.y - Point1.y) / (Point2.x - Point1.x) ); if ( Point2.x > Point1.x ) Theta = static_cast( PI ) / 2.0f - Theta; else Theta = static_cast( 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( PI ) / 2.0f - Theta; else Theta = static_cast( 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. 