The Telecom Design SDK contains a function to encode GPS coordinates : TD_SENSOR_EncodePositionXY this function from the SDK allow to choose the size of the GPS encoded data and to reduce it. This post explains how this function works and gives a php implementation to decode it.
The encoding function can be call from the GPS loop with the following parameters :
- the fix structure
- the destination buffer
- the size of the encoded data
- a default value to return
A full precision encoding will need 48 bits : 2 will be used for sign of latitude and longitude when the 46 others, split in 23 bits for each are containing longitude and latitude. According to the documentation, this allow a precision of 60 cm in latitude and 119 cm in longitude.
If you want to save 1 byte, the precision will change for 9,52/19,6 meters ; 32 bits encoding will reduce the precision to 152/305 meters.
After asking a question to TD forum, I got the precise answer from the team on the way to decode the positions encoded that way : you can find it here.
So basically to decode a 48bits encoded frame that way :
444444443333333333222222222211111111110000000000 765432109876543210987654321098765432109876543210 X - lng Sign 1=- X - lat Sign 1=- XXXXXXXXXXXXXXXXXXXXXXX - 23b Latitude XXXXXXXXXXXXXXXXXXXXXXX - 23b Longitude
Then we have the following algorithm for 48 bits
if ( encodedLat != 8333333 ) latitude = ( encodedLat * 108 + 53 ) / 10_000_000; else latitude = 90.0 latitude = (latSign > 0)?-latitude:latitude; if ( encodedLng != 8372093 ) longitude = ( encodedLng * 215 + 107 ) / 10_000_000; else longitude = 180.0 longitude = (lngSign > 0)?-longitude:longitude;
The way to do this in PHP is assuming $_gps contains the 48 bits of the encoded location :
$_lngS = ( ($_gps & 0x800000000000 ) > 0 ) ? -1 : 1; $_latS = ( ($_gps & 0x400000000000 ) > 0 ) ? -1 : 1; $_encLat = ($_gps & 0x3FFFFF800000 ) >> 23; $_encLng = ($_gps & 0x7FFFFF ); if ( $_encLat != 8333333 ) { $_decLat = $_latS * ( $_encLat * 108 + 53) / 10000000; } else { $_decLat = $_latS * 90.0; } if ( $_encLng != 8372093 ) { $_decLng = $_lngS * ( $_encLng * 215 + 107) / 10000000; } else { $_decLng = $_lngS * 180.0; }
For 40 bits encoding, the algorithm would be :
if ( encodedLat != 524170 ) latitude = ( encodedLat * 1717 + 858 ) / 10_000_000; else latitude = 90.0 latitude = (latSign > 0)?-latitude:latitude; if ( encodedLng != 524170 ) longitude = ( encodedLng * 3434 + 1716 ) / 10_000_000; else longitude = 180.0 longitude = (lngSign > 0)?-longitude:longitude;
and the php implementation :
$_lngS = ( ($_gps & 0x8000000000 ) > 0 ) ? -1 : 1; $_latS = ( ($_gps & 0x4000000000 ) > 0 ) ? -1 : 1; $_encLat = ($_gps & 0x3FFFF80000 ) >> 23; $_encLng = ($_gps & 0x7FFFF ); if ( $_encLat != 524170 ) { $_decLat = $_latS * ( $_encLat * 1717 + 858) / 10000000; } else { $_decLat = $_latS * 90.0; } if ( $_encLng != 524170 ) { $_decLng = $_lngS * ( $_encLng * 3434 + 1716) / 10000000; } else { $_decLng = $_lngS * 180.0; }
Hope it helps !
It was an informative post about Telecom Design SDK decode GPS frame, thanks for sharing