# Unusual algorithm needed for digital compass

Status
This thread has been Locked and is not open to further replies. The original thread starter may use the Report button to request it be reopened but anyone else with a similar issue should start a New Thread. Watch our Welcome Guide to learn how to use this site.

#### AlbertB

Hi Guys,

I'm doing some work on analysing the data fed in from a digital compass over time. This includes working out statistical info like standard deviations of the last N points. Simple enough, just keep an array of the points and work out the total, then mean and consequently SD. The data is added to the array up to a set number of points, then the oldest is discharged when the new one arrives. Nothing strange so far.

Another important point here is that the results of all calculations are only used internally, so the actual values do not matter as long as they maintain continuity. It is actually used to make a Yes/No decision each time which is reported back to the rest of the application.

There is a BIG problem with this procedure in that, when the boat steers through due North, the data gets screwed by the jump from 0 to 359 and vice versa. Think of the simple case of holding 2 records. As we steer from 2deg through North 1 degree at a time, the total and mean would become 3/1.5, 1/0.5, 359/179.5. And the SD would jump about too. In the real case of maybe 40+ points being involved, this jump would have destroyed the continuity of the whole data block for another 40 readings until it was flushed out. And if the boat crossed North again in that time it would get worse. And if it was trying to steer a line due North the jitter would play havoc with all of the data. That jump cannot be accomodated in what I am having to do.

So I could detect it crossing the North line and add or subtract 360 degrees as necessary. This would work once but what if the boat steered back across, or worse, right round and crossed again? I would have to adjust by 720 degrees this time or suffer another potential jump. And so on.

So, does anyone have an algorithm which would help to solve this situation, or some ideas as to an approach which I may have missed?

Thanks!

#### IMM

I'm not clear enough on the situation to suggest some ideas about using the heading value and deciding based on recent history what should be done. Questions of that type would require that I know something like - the boat can't turn fast enough to move more than 90deg between samplings. What kind of sampling rate does your data represent.? If the nyquist is adequate ...

On a more general note - you could work with a smooth function such as sine or cosine. Store the cosine, calculate based on that function and convert back as required?

#### OBP

Would it be possible to just plot the difference in heading from the previous heading rather than the heading itself?

#### Jimmy the Hand

I guess you should convert 359 to -1, 358 to -2, etc.
If this helps, try the following formula:
Corrected Degree = ((Measured Degree + 180) mod 360) - 180

#### AlbertB

Hi Guys,

Thanks for the responses, I do appreciate the help.

IMM's points about max turn rates etc are very valid here and are one of my own nightmares. The definitive data on criteria like that is just not available, so I am having to make some initial assumptions, (educated guesses). From the nature of the activity, which involves towing very long lines of kit behind a boat, the craft is going to be very restricted in its turning ability. I have assumed something like 1deg/sec max. This does free us up to use a very simple approach. More of that later.

After more digging around after posting I found a very obscure site with a discussion on a similar topic, and IMM's other suggestion was talked about there. Using the sine of the bearing angle would allow us a continuous function but can be ambiguous. For example, increasing our heading to 90deg would give a situation where it was impossible to tell whether the craft had continued on up to 91deg, or started back down to 89deg when we converted the sine back to an angle. However - if we store both the sine and cosine we have a situation where the 2 pieces of information would allow us to decipher accurately in every case. This would work I think in my situation. But wait for the final solution before deciding on this one.

Dealing with the difference as OBP suggests was something which I tried and rejected early on. It would work. To a point! But then the constant conversions for the statistical data which I am having to calculate and keep became ponderous.

Jimmy's point was one which I had assumed I would have to take into account when I first looked at the problem. The issue here is that, imagine you cross from 1deg to 359deg. You subtract 360 from then on down. (It is worth noting here that I am having to hold a user defined number of historical data readings which may be up to a couple of hundred!) If the system continues turning anticlockwise until it eventually returns to 1deg, (now -359deg), and again crosses the North line, to assure continuity we are now subtracting 720deg. It would work but not in this case.

The solution I came up with and have working is very basic but effective, (simple was in the remit!) I detect zero crossing by testing every new bearing, (B[n]), as it comes in against the last one, (B[n-1]), with:

abs(B[n] - B[n-1]) > 300

If this falls true I have crossed the North line. This covers movement in both directions. (And 300 is only an arbitrary big number, anything larger than the largest single difference between consecutive points would do.)

When zero crossing has been detected, I go into a mode where any new bearing below 45deg has 360deg added to it. This effectively gives me continuity within a band from 45deg around to 405deg which I am now well within. The first time only, I then go into the historic data array and update every reading of under 45deg in the same way. Finally I recalculate the statistical data with the updated values and the system works in "High Mode" from then on. The stats do not care if they are in one mode or another as long as there is continuity within their base data set.

I then continue as normal but monitoring the readings coming in to detect the first one which falls either <330deg or >390deg, (have to be careful with how I do that as they are not exclusive), this means that the system has moved far enough away from North to be reset. I simply reconvert the history and stats to their original form and stop adding 360deg.

The actual values within the programme are not seen by the user at any time, only the result of a test performed internally with it. So as long as this gives the correct outcome, which it does, the crudeness of the system is not a problem.

I like simple solutions. They are easy to code, easy to maintain, and easily accessible to other who may come after. Many thanks for your support, and I hope it stirred the grey matter in a positive way.

#### Jimmy the Hand

AlbertB said:
Jimmy's point was one which I had assumed I would have to take into account when I first looked at the problem. The issue here is that, imagine you cross from 1deg to 359deg. You subtract 360 from then on down. (It is worth noting here that I am having to hold a user defined number of historical data readings which may be up to a couple of hundred!) If the system continues turning anticlockwise until it eventually returns to 1deg, (now -359deg), and again crosses the North line, to assure continuity we are now subtracting 720deg. It would work but not in this case.
I'm not sure what you mean by this... The formula I've given never returns a value outside of the range [-180...+179] deg. Have you tried it at all? Even if you cross the North line 5 times clockwise, and stop on 1801°, the formula will return 1°, so what's the problem? Am I missing something?

#### AlbertB

Yes Jimmy. To keep the statistics accurate throughout this I cannot have any discontinuity in the list of historic readings. At some point in your formula, if I am reading it right, there will be a point where it jumps from -180 to 179 or vice versa. This will screw up my calculations until that discontinuity is flushed out of the historical data.

Let's imagine starting at 5deg and stepping anticlockwise in 2deg steps calculating just the mean of 2 results each time. (The real system is much more complicated than this of course).

1) 5, 3 - mean=4
2) 3, 1 - mean=2
3) 1, 359 - mean=180 - PROBLEM!
4) 359, 357 - mean=356

If we are working in the range of -179 - +180

1) 5, 3 - mean=4
2) 3, 1 - mean=2
3) 1, -1 - mean=0 - PROBLEM SOLVED!
4) -1. -3 - mean=-2

Your formula on its own works perfectly at removing the problem from North crossing and assuring continuity, but shifts it to South crossing. If we continue round we will eventually get to

5) -177, -179 - mean=-178
6) -179, 179 - mean=0 - SAME PROBLEM!

#### IMM

f we store both the sine and cosine we have a situation where the 2 pieces of information would allow us to decipher accurately in every case.
Well -- sine or cosine plus quadrant
In any case, you would porbably choose the one which is 'steepest' around the avg. course.
You would need the deriv. to get back towards a degree type result.

Status
This thread has been Locked and is not open to further replies. The original thread starter may use the Report button to request it be reopened but anyone else with a similar issue should start a New Thread. Watch our Welcome Guide to learn how to use this site.

As Seen On