2
votes

I have some gps sensor data which uses signed 24 bits to represent latitude and longitude each. I want to convert this data in more readable degrees, minutes and seconds format.

I have searched a lot but no algorithm is working for me. I would like to do this in python.

The spec sheet tells the following

Byte [8] > Value: MSB of the UP501 received Latitude

Byte [9] > Value: CSB of the UP501 received Latitude

Byte [10] > Value: LSB of the UP501 received Latitude

Byte 8, 9 and 10 represent the latitude. The north-south latitude is encoded using a signed 24 bit word where -2^23 corresponds to 90° south (the South Pole) and 2^23- 1 corresponds to 90° north (the North Pole). The equator corresponds to 0.

Byte [11] > Value: MSB of the UP501 received Longitude

Byte [12] > Value: CSB of the UP501 received Longitude

Byte [13] > Value: LSB of the UP501 received Longitude

Byte 11, 12 and 13 represent the longitude. The east-west longitude is encoded using a signed 24 bit word where -2^23 corresponds to 180° west and 2^23 -1 corresponds to 180° east. The Greenwich meridian corresponds to 0.

Example data (from 8-13 bytes)

1E 55 9C 1C 69 5A

should give 21°19′44″N, 39°57′13″E

EDIT: After the first comment, here is the problem Every where I have seen is the 32 bit representation of the coordinates. Those methods are not working for me as I do not get what I expect. Not even close.

Is there a better way for this conversion?

1
So, what is the issue? What did you try and where are you stuck?spectras
That's a bit ugly; the scaling factor is different depending on what side of the 0 you're on. (For instance, there are 2**12 values representing southern latitudes, but only 2**12 - 1 values representing northern latitudes.)chepner
I tried stackoverflow.com/questions/7151896/… stackoverflow.com/questions/17355604/… And I have read other solutions on SO but everywhere its 32 bit unsigned representation and not 24 bit signedHassan
@gbs I don't need the code, I am not asking for the code. I can write the code myself. Problem is that I cant find the conversion algo. Do you know how can I mathematically convert this HEX to lat/long? may be divide by x, multiply by y etc?Hassan
lat would be int("1E559C", 16), I imagine each degree would be something like 93206.7, diving would give 21.328883171081543 but I know very little about calculating lat and longPadraic Cunningham

1 Answers

3
votes

It's a little tricky, since there are several scales involved. First, divide your signed value by 2**23 - 1 to see what "fraction" of the hemisphere it represents.

>>> 0x1e559c / (2.**23 - 1)
0.2369876190409206

So, what is 23.69...% of 90 degrees?

>>> 0x1e559c / (2.**23 - 1) * 90
21.328885713682855

21.something degrees; we're on the right track. Instead, note that there are 90*3600 seconds of latitude between the equator and a pole. Let's see what fraction of that we have:

>>> 0x1e559c / (2.**23 - 1) * 90 * 3600
76783.98856925828

So the given value is ~76784 seconds north of the equator; converting that to degrees/minutes/seconds:

# seconds to minutes and seconds
>>> divmod(76784, 60)
(1279, 44)

# minutes to degrees and minutes
>>> divmod(1279, 60)
(21, 19)

And there's your 21 degrees, 19 minutes, 44 seconds. Now, we know to divide by 2**23 - 1 because we knew the value was less than 0x7fffff and so in the northern hemisphere. (If the value were in the southern hemisphere, we would need to divide by 2**23, because the scaling is asymmetrical.)

For longitude, you would multiply by 180*3600 seconds per hemisphere instead of 90*3600, then proceed in the same fashion.


One caveat; I didn't include an example for the southern/western hemisphere, because I wasn't sure if 90S was 0x800000 (two's complement) or 0xffffff (signed magnitude).