Telecom Design SDK decode GPS frame

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 !

 

This entry was posted in sigfox and tagged , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *