Search code examples
c++type-conversionudplatitude-longitude

Converting a UDP Payload -> Struct -> Long, Lat in decimal degree (12.41N, 2.40E) (im a junior < 1 year) c++


First ever time asking a question on here so go easy on me if its not up to par.

Visual Studio. C++. UDP.

I receive a UDP payload which I store in a char buffer. I have a struct which is byte-aligned to split the buffer into the elements of the struct.

I need to get the lon, lat from the struct and cout to console but it doesnt look correct.

When i wireshark the UDP payload i can see the lon, lat and i know the values it represents: 3FA24690119236AC -> 12.41890000 (N) 3FCBBE7C9C146695-> 2.04515000 (E)

The data type for the lon, lat im using is unsigned long long.

I cannot work out how to go from 3FCBBE7C9C146695 -> 12.41890000 bearing in mind its probably little-endian.

Could someone be so kind as to explain what I should be doing, in a <1 year juniors mindset and demonstrate with some code.

I understand you wont have the UPD payload.

This is my understanding of what I would like to see (if I even understand the process correctly).

char buffer[] = { '3F', 'A2', '46', '90', '11', '92', '36', 'AC'};
struct payload { unsigned long long lat; };

payload p;
std::memcpy(&p, buffer, sizeof(p));

.... convert to its dec degree

printf("Lat: %llu\n", p.lat);

Again I am a newbie and wish to learn!

Many thanks in advance, also let me know if I need to format my question better!

p.lat = ntohll(p.lat); p.lat = ntohd(p.lat);

Tried these and changing the data type to double, long, int64, uint64 but I'm chasing my tail now.

More Info....

12.41250000°N 2.43520000°E is the output i want to see.

UDP payload only (lat, lon are the only parts of interest)

39000000000000000000000000030000006500000059ffffffffffffffff41d9205f3f80000000000001c0a801b73fcbbad397da94bd3fa5c2db1fc191f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017ae

Documentation states these (lat, lon) should be 8 byte double (accepted values: -π/2 - &pi/2; (Radians)) for lat 8 byte double (accepted values: -π - π (Radians) for lon

Now using unsigned char arrays (UPD -> Struct)

then

double result;
std::memcpy(&result, p.lat, sizeof(double));
std::cout << "Lat: " << result << std::endl;

gives: Lat: -4.74162e-12

Printing out the array: 3fa5c2db1fc191f8 so it seems the array hold the correct hex i see in wireshark.

Please do try and 'dumb it down' as I really would like to understand the issue i have and not just to solve it.

Thanks Again


Solution

  • Clue1: RADIANS

    Clue2: There's nothing stopping you trying the degrees and radians double to char[] conversion and seeing what it gives you.

    It turns out that it converts the radians, rather than degrees version of the angle. On my PC at least you also have to reverse the order of bytes. (But I don't know how universal that is.)

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    
    const double PI = 4.0 * atan( 1.0 );
    
    double decode( unsigned char *buffer, int n )
    {
       reverse( buffer, buffer + n);
       double result;
       memcpy( &result, buffer, n );
       return result * 180.0 / PI;
    }
    
    int main()
    {
       const int N = sizeof( double );
       unsigned char buffer1[N] = { 0x3f, 0xcb, 0xba, 0xd3, 0x97, 0xda, 0x94, 0xbd };
       unsigned char buffer2[N] = { 0x3f, 0xa5, 0xc2, 0xdb, 0x1f, 0xc1, 0x91, 0xf8 };
       cout << "Latitude:  " << decode( buffer1, N ) << '\n';
       cout << "Longitude: " << decode( buffer2, N ) << '\n';
    }
    

    Output:

    Latitude:  12.4125
    Longitude: 2.4352