Errors in mathematical functions with multiple variable types

Hello

Ultimate goal:

compute the distance between two points for differential GPS measurements (using Adafruit GPS module).

How I'm going about it:

I am receiving a long variable type (the other GPS) via a radio transmitter. The primary unit receives it's position directly from the attached GPS in the form of a double (I believe). I am multiplying that float by 10000 and attempting to cast it as a long. From there, I am calculating the difference and dividing the result by a decimal. For future math operations, I am using the abs() function to get the absolute value. From there, I am casting the value as a float because I am raising the value to the power of two using the function pow(). Finally, I am taking the square root of that (and another value with the same operations done to it) to get the distance.

However, I am getting occasional overflow issues and very odd numbers (generally very high). Thus, I am hoping someone can point out where the source(s) of error is(are). For help in the overflow area, I'm dealing with numbers around 37000000 and 121000000.

EDIT #1: I have just realized upon writing this that I do not need to take the absolute value before raising the number to the power of two, but I have decided to leave it in to ensure that I do not create a coding hole that doesn't make sense.

EDIT #2: Thank you everyone for your responses and help. We ended up using the Haversine distance formula (incorporates the Earth's radius). Coding for that proved to be much easier, and we realized that 1) doing math functions inside abs() isn't recommended, and 2) if the data type is a float, use fabs(). In the end, the project was successful, and we were able to achieve an error of about 10 feet using differential GPS calculation.

Thank you very much for your time and patience!

-Bob

Here is the code:

#define sec_feet_lat_conversion 986//.72753
#define sec_feet_lon_conversion 1537//.06506
struct roverRemoteData receivedData;//this is the data structure for the radio receiver
  uint8_t rcvdSize = sizeof(receivedData);//this is for the size of the data structure
  
  double parent_latitude;//GPS lat. position from GPS module for primary(parent) device
  double parent_longitude;//GPS lon. position from GPS module for primary device
  long child_latitude;//whole number received from secondary device via radio receiver
  long child_longitude;//whole number received from....
  long GPS_P_Latitude;
  long GPS_P_Longitude;
  double latitude_feet;
  double longitude_feet;
  double Latitude_Distance;
  double Longitude_Distance;
  double straight_line_distance;
 
  parent_latitude = GPS.latitude;
  parent_longitude = GPS.longitude;
  child_latitude = receivedData.GPS_CLatitude;//data from radio receiver via structure
  child_longitude = receivedData.GPS_CLongitude;//data from radio receiver via structure
  
  GPS_P_Latitude = (long)(parent_latitude * 10000);//multiplying to get a whole number
  
  GPS_P_Longitude = (long)(parent_longitude * 10000);
  
  long c_p_lat_diff = (GPS_P_Latitude - child_latitude)/sec_feet_lat_conversion;//calc. difference and converting seconds to feet)
  latitude_feet = abs(c_p_lat_diff);//ensuring positive value
  float float_lat_feet = (float)latitude_feet;//casting as float for pow()
  
  long c_p_lon_diff = (GPS_P_Longitude - child_longitude)/sec_feet_lon_conversion;
  longitude_feet = abs(c_p_lon_diff);
  float float_lon_feet = (float)longitude_feet;
  
  
  
  Latitude_Distance = pow(float_lat_feet, 2.0);

  Longitude_Distance = pow(float_lon_feet, 2.0);
  
  
  straight_line_distance = sqrt(Latitude_Distance + Longitude_Distance);

What is this doing?

  double longitude_feet;
...
  float float_lon_feet = (float)longitude_feet;

double and float on the Arduino (Uno at least) are the same data type.

Your maths appears to be over simplified. Longitude is not directly related to distance from any point. It is, instead an angular displacement about the axis of the earth.

consider two points on the equator, If one is at 0 degrees (just off the west coast of Africa) and the other at 180 degrees (somewhere in the middle of the Pacific Ocean) The distance between them will be over 12,000 miles.

Whereas if we take a latitude of just one foot from the North Pole, If someone is standing at 0 degrees, Another person at 180 degrees would be just 2 feet away.

From this you can see that a difference in longitude of 180 degrees, could be just 2 foot, or 12000 miles. There's a useful site here Online distance calculator

If you are only going to use your results within a fairly small area and you're not too close to either of the poles, Your method could work, with the addition of a couple of constants, (one for longitude, another for latitude).

Due to this flaw in the basis of your calculations I haven't tried to debug your code.

KenF is quite right, although from your snippet it is hard to tell exactly what you are doing. I did some calculations a while ago (in PHP) about the difference between two points given in latitude and longitude a while ago, and knowing the radius of the Earth was one of the constants you needed to use.

It wasn't a simple calculation. :slight_smile:

this is the thread to read - Calculating distance between two points accurately - Syntax & Programs - Arduino Forum -

snippet
The great circle distance d between two points with coordinates {lat1,lon1} and {lat2,lon2} is given by:
d=acos(sin(lat1)*sin(lat2)+cos(lat1)*cos(lat2)*cos(lon1-lon2))

What makes you think what you can't and,subtract, multiply, etc floats?

Mark

holmes4:
What makes you think what you can't and,subtract, multiply, etc floats?

Mark

You certainly can't and them.

AWOL:
You certainly can't and them.

Not completely true, you can logically && them but not bitwise & them (compiler error).

useful to test for 0.0 or not of multiple floats.

void setup() 
{
  Serial.begin(115200);
  Serial.println(1.0 && 2.0);
  Serial.println(0.0 && 2.0);
  Serial.println(1.0 || 2.0);
  Serial.println(0.0 || 2.0);
}

void loop() {}

1
0
1
1

Accurate distance calculation from lat/long is more involved, the earth isn't spherical,
it bulges at the equator, so the exact formulae are much more complicated. If you
can live with the 0.5% error of the spherical assumption things are simpler. For
very short distances you can simplify greatly of course and pretend the earth's
surface is flat.

Alas for GPS calculations float isn't really precise enough, and true doubles would be
better (the ATmega Arduino's don't provide double arithmetic in the distribution).

An excellent reference for a variety of latitude/longitude calculations, and efficient formulas (with code) is Calculate distance and bearing between two Latitude/Longitude points using haversine formula in JavaScript