This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

64 bit double precision floating point format in MSP430

Other Parts Discussed in Thread: MSP430F2619

Hi,

Currently, I need to use Universal Transverse Mercator (UTM) projection to map the longitude and latitude as a position on the map. 

 

However, the calculation of UTM is complicated, and the single precision floating point number is not good enough for us to get a very accurate result because of the calculation errors.

 

We want the accuracy after UTM projection less than 1 meter both in northing and easting. But, the result with single precision floating point number brings us more than 1 meter errors.

 

Therefore, we would like to use  64 bit double precision floating point format to reduce the calculation error. However, CCEv3.1 doesn't support 64 bit double precision format. So, does anyone know how to do a double precision calculation with CCEv3.1?

 

Any suggestion would be great!

 

Thanks!

 

Regards

 

Liu

  • Liu,

    an alternative option for you could be the use of IAR Embedded Workbench for MSP430 instead of the current CCS (or CCE). According to the compiler docs they support 64-bit floating point 'double'. Make sure to configure the 'double' size to 64-bit under Project Options --> General Options --> Floating-point. They have a 30-day trial version, so you could give it a shot to see how your algorithm performs.

    Also I'm not exactly sure about your calculation, but I would probably try to re-arrange it somehow so that it can be done using the existing 32-bit float data types in CCS/CCE.

    Regards,
    Andreas

  • Hi andre,

    The code that we use in our UTM calculation is shown below. We found the code from a C++ program, and it is pretty complicated involving some polynomial calculations, trigonometric math, natural log, and so on.

    void LLtoUTM(float lat, float lon, float equatorialRadius, float eccSquared, float *UTMNorthing, float *UTMEasting)
    {
        float eccPrimeSquared, k0;
        float lonOrigin;
        float latRad, lonRad, lonOriginRad;
        float n, t, c, a, m;
        UBYTE zoneNumber;
       
        k0 = 0.9996;
       
        latRad = deg2rad(lat);
        lonRad = deg2rad(lon);
       
        zoneNumber = ((lon + 180) / 6) + 1;
        if( lat >= 56.0 && lat < 64.0 && lon >= 3.0 && lon < 12.0 )
        {
            zoneNumber = 32;
        }           

          // Special zones for Svalbard
        if( lat >= 72.0 && lat < 84.0 )
        {
            if(        lon >= 0.0  && lon <  9.0) zoneNumber = 31;
              else if(lon >= 9.0  && lon < 21.0) zoneNumber = 33;
              else if(lon >= 21.0 && lon < 33.0) zoneNumber = 35;
              else if(lon >= 33.0 && lon < 42.0) zoneNumber = 37;
        }
        lonOrigin = (zoneNumber - 1) * 6 - 180 + 3;  // +3 puts origin in middle of zone
        lonOriginRad = deg2rad(lonOrigin);

        eccPrimeSquared = (eccSquared) / (1 - eccSquared);

        n = equatorialRadius / sqrt(1 - eccSquared * sin(latRad) * sin(latRad));
        t = tan(latRad) * tan(latRad);
        c = eccPrimeSquared*cos(latRad) * cos(latRad);
        a = cos(latRad) * (lonRad - lonOriginRad);

        m = equatorialRadius*((1 - eccSquared/4        - 3*eccSquared*eccSquared/64    - 5*eccSquared*eccSquared*eccSquared/256)*latRad
                                 - (3*eccSquared/8    + 3*eccSquared*eccSquared/32    + 45*eccSquared*eccSquared*eccSquared/1024)*sin(2*latRad)
                                                    + (15*eccSquared*eccSquared/256 + 45*eccSquared*eccSquared*eccSquared/1024)*sin(4*latRad)
                                                    - (35*eccSquared*eccSquared*eccSquared/3072)*sin(6*latRad));
       
        *UTMEasting = (float)(k0*n*(a+(1-t+c)*a*a*a/6
                        + (5-18*t+t*t+72*c-58*eccPrimeSquared)*a*a*a*a*a/120)
                        + 500000.0);

        *UTMNorthing = (float)(k0*(m+n*tan(latRad)*(a*a/2+(5-t+9*c+4*c*c)*a*a*a*a/24
                         + (61-58*t+t*t+600*c-330*eccPrimeSquared)*a*a*a*a*a*a/720)));
                     
        if(lat < 0)
        {
            *UTMNorthing += 10000000.0;    //10000000 meter offset for southern hemisphere
        }
    }

    Liu

  • Hi Liu,

    the code looks pretty...complicated. It probably needs a deeper understanding of the problem to come up with an alternative and more MCU-friendly solution. So just FYI, I've just tried the latest EW430 V4.21.2, compiled the algorithm after changing all 'float' to 'double', and ran it so that you can see some performance numbers. The test was done using the highest optimizer setting (max. speed) and the code was compiled for an MSP430F2619 using the small memory model.

    First, here is the function call used:

        double equatorialRadius = 6378137;
        double eccSquared = 0.00669438;
        LLtoUTM(50, 50, equatorialRadius, eccSquared, &northing, &easting);

    And here are the results:

        Setting "double" to 32-Bit: Approximately 55,000 CPU Cycles, Code size: ~6KB
        Setting "double" to 64-Bit: Approximately 220,000 CPU Cycles, Code size: ~12KB

    Looks pretty involving to me for one little routine

    Regards,
    Andreas

  • Hi andre,

    Thanks for helping me test the code. I tried to test the code with IAR C/C++ 30 days trial  this afternoon. But, I haven't got the registration accepted by IAR before I can download it.

    As you mentioned, we need to do more investiagtions about the code, and we have analyzed it with matlab. However, the simplified equation of UTM is still complicated. Specially, thoes two used to calculate northing and easting. So, if you have any ideal about simplification. Could you please let me know? Really appreciate.

    Currently,  we decide to create a library which allows us to do double format calculation. But, it is not a small job. If we can have a simple and quick way to get the problem fixed, that would be great!

    Regards

    Liu

**Attention** This is a public forum