I am working on an 802.11a demod that works, for the most part, but has a bug that causes intermittent errors. I haven't finished characterizing it, but it appears that the problem is in my equalizer block.

802.11a is an OFDM signal, and each OFDM symbol has 64 sub-channels. Four of those sub-channels are pilots (known data), at sub-channels 7, 21, -7, and -21. I use the pilots to correct for any remaining carrier offset (shows up as a constant phase offset in the pilots) and timing offset (shows up as a liner offset- i.e. the phase offset is 0 at bin 0 and grows as it gets further from bin 0).

I do simple averaging to detect the carrier offset phase, and some simple manipulations before averaging to detect the time phase offset (e.g. multiply channel -21 by -1, multiply channel -7 by -3, and multiply channel 7 by 3). I'm intentionally leaving out some unneeded details, but hopefully this gives the gist of what I'm doing.

My problem is that the circular nature of angles can cause the averaging to misbehave in catastrophic ways for certain values. For instance, imagine imagine averaging $-\frac{4}{5}\pi$ and $\frac{4}{5}\pi$. It's easy to see graphically that the answer should be either $-\pi$ or $\pi$, but the standard averaging formula gives the answer of 0, literally the opposite of the correct answer.

enter image description here

What is the proper way to average angles?

EDIT: I'll try and make what I'm doing a little clearer. There are two "error conditions" that manifest themselves differently at the output of the FFT. First is carrier offset, which manifests itself as a constant phase offset.

enter image description here

For this case averaging the cartesian pilot values rather than the angle, as John suggested, is a good idea. Thank you.

The second error condition is timing offset, which manifests as a linear phase offset. The greater the time offset, the larger the slope of the phase offset. The slope can also be negative, depending on whether the receiver is ahead or behind where it should be.

enter image description here

Now, since it is strictly linear (the origin passes through zero), I could theoretically calculate the slope from just one pilot. I would first calculate the carrier offset phase offset (i.e. error condition #1), subtract that out, and then use any of the four to calculate the slope. That would avoid averaging altogether. The problem is that noise can make these values jump around, so my estimate is much better if I use all four- thus the averaging.

Hopefully the picture above makes it clear that I can't just take the pilot values and average them as is- I have to modify them to make them a constant + noise. I do this by multiplying the angle of the -21 pilot by -1, the -7 pilot by -3, the 7 pilot by 3, and the 21 pilot by 1. They thus become equivalent to the 21 pilot and can be averaged.

enter image description here

I don't know of a good way to multiply the angle of a vector by a constant like "3" in the cartesian system, so it looks to me like I would have to convert to polar coordinates, multiply the angles by -1, -3, 3, and 1 respectively, convert back to cartesian coordinates, average the pilots, then convert back to polar to get the phase offset. While this is do-able, I would like to find a less klunky solution if possible.

  • 5
    $\begingroup$ I always average the complex numbers then take the angle of that result. $\endgroup$
    – John
    Jan 27, 2014 at 15:19
  • 1
    $\begingroup$ I'd also prefer @John's method. Actually adding up the complex numbers corresponds to a vector addition in the complex plane which yields an angle of $\pi$ in your example. Taking the angle of the result is sufficient as averaging only affects the magnitude (unless limited range of numbers is an issue) $\endgroup$
    – Deve
    Jan 27, 2014 at 15:50
  • $\begingroup$ @John That's a very good point, but like the case of the time/phase offset where I want to multiply the angle of the "7" channels by 3 before averaging I don't see a good way of doing that. I guess I could convert to polar, multiply by 3, convert back to cartesian, average, then convert back to polar, but that is awfully klunky. $\endgroup$
    – Jim Clay
    Jan 27, 2014 at 16:47
  • $\begingroup$ @JimClay: Why are you averaging values together? That's not clear from your description. In general, you shouldn't be coherently averaging values together unless they are in fact coherent; otherwise, you get the destructive interference that you've noted. I think a little more detail would help. $\endgroup$
    – Jason R
    Jan 27, 2014 at 18:00

5 Answers 5


As you pointed out in your edit, averaging the values isn't a great fit for this sort of problem. A simple alternative would be to simply fit a line to the four phase measurements using a linear least squares fit. That should perform better than the single-point approach.

A possibly even-better solution would be to fit a sinusoid to the four complex samples instead. This prevents you from having to calculate their phase angles first, which could cause a degradation in performance at low SNR.

Also, to accomplish your original goal of multiplying a complex number's phase by 3, you can do so by simply taking each number to the third power:

$$ \arg(x^3) = 3 \arg(x) $$

This obviously will also affect the magnitude of each sample, but if you're only concerned about phase, you can typically work around that. By doing this, however, you're going to limit the range of timing offsets that your estimator will work over. Multiplying the phase of a complex number by 3 will introduce a $2\pi/3$ phase ambiguity in the output (i.e. you wouldn't be able to detect a shift in phase of $2\pi/3$). This is similar to the contant phase ambiguities that you often see in PSK synchronization systems (like a Costas loop).


The usual way to approach directional is to move to a (complex) vector approach.

For example, if your observations are periodic with period $P$ then the mean of $N$ observations, $\hat\alpha(n)$ can be found as per equation (1) of the above link: $$ \hat{\mu}_P = \frac{P}{2\pi} \left[ \arg \left ( \sum_{n=0}^{N-1} e^{j2\pi\hat\alpha(n)/P} \right) \right ]_{2\pi} $$ which scales the $\hat\alpha$ to be periodic over $2\pi$, performs a unit vector complex sum, takes the argument (angle) of the complex sum, and finally rescales to in $[0,P)$.

A similar approach can be used to obtain a "circular sample variance".


I would change the domain from $[-\pi:+\pi)$ to $[0:2\pi)$ and deal with everything modulo $2\pi$. Then you don't need to deal with negative angles.

Or as John mentioned, use complex numbers for everything up to where you need an actual angle.

  • 3
    $\begingroup$ The problem is that that just shifts where the problem occurs, it doesn't get rid of the problem. For instance, imagine an angle of $0.1$ and and angle of $2\pi - 0.1$. The "average" would be $\pi$, which is, of course, the wrong answer. $\endgroup$
    – Jim Clay
    Jan 27, 2014 at 16:44
  • $\begingroup$ Yeah, you're right. You'd need to do a quadrant based approach like how the atan2 function is calculated and for the same reason of the discontinuity at $\pm\pi$ (or $0/2\pi$). That wouldn't lend itself well to performing averages. $\endgroup$ Jan 27, 2014 at 18:04

Here is a quick hack I've used in the past to find an "average angle". It's a little clunky and uses more magic numbers than I would like, but at least it's quick and efficient and doesn't have the catastrophic failure that simple arithmetic averaging gives.

// median_average: find the "average angle" from some set of angles.
// pick A and B "well separated" from each other and from 0 --
// perhaps A =~= 2pi/3 and B =~= 4pi/3
average0 = (average{ (angles .- 0) mod 2pi } + 0) mod 2pi
averageA = (average{ (angles .- A) mod 2pi } + A) mod 2pi
averageB = (average{ (angles .- B) mod 2pi } + B) mod 2pi
average = median ( average0, averageA, averageB )

I typically store angles in something like "brad" representation, so that the "mod 2pi" operation is a quick "bitand MASK".

I have a proof that the median of 3 intermediate averages always gives the "correct" average for any 2 angles that are less than 2pi/3 apart; the median of 5 intermediate averages always gives the "correct" average for any 2 angles that are less than 4pi/5 apart, etc.

Whenever this "median_average" algorithm averages 2 angles together that are "not too far apart", at most 1 of the 3 intermediate simple averages gives a catastrophically wrong value (at most 2 of the 5 intermediate averages). (As you already mentioned, the "average0" value is completely wrong when trying to average 0.1 and 2pi-0.1). Then the final median() throws out the "wrong" value (if there is one) and returns one of the 2 correct averages.

(Have you considered the possibility that the timing offset is so bad that the phase offset crosses the +pi line and "wraps around" to -pi ? Maybe you're lucky enough that that never happens in your system).


For computing the average of angles, you may use circular statistics as defined in Mardia K. V., Jupp P. E. (2009, Directional Statistics, Vol. 494 Hoboken, NJ: Wiley) and as used in this paper, Eq. 10:

The idea behind Equation 10 is that in order to compute the mean of a circular quantity, the position and direction first need to be transformed into an angle, which is then projected to the 2D unit circle where the arithmetic mean is computed. After that, the angle that the mean position forms is transformed back from an angle to space. For positions, this takes the form:

$$ x_{pred}^{net}(t) = 1 + \frac{1}{2 \pi} \textrm{arctan2}(\sum_i^{N_{exc}} \mathit{p}_i(t) (\sin(2\pi x_i - \pi)), \sum_i^{N_{exc}} \mathit{p}_i(t) (\cos(2 \pi x_i - \pi))) $$

in your context, you have $N$ measures $\theta_i$ with probabilities $p_i$, the average $\theta$ is equal to:

$$ \theta = \textrm{arctan2}(\sum_i^{N} \mathit{p}_i (\sin(2\pi \theta_i - \pi)), \sum_i^{N} \mathit{p}_i (\cos(2 \pi \theta_i - \pi))) $$

  • $\begingroup$ Yup, that's basically the same as the approach I suggested... though the $\theta$ equation you have is wrong; I believe the $1 +$ is not necessary, nor is the $\frac{1}{2\pi}$. Edited to match what I think is correct. YMMV. $\endgroup$
    – Peter K.
    Jan 30, 2014 at 21:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.