Jump to content

KSP Math for distance is off?


Recommended Posts

So I created a mod that has some custom distance checking in it ... Seems that @SQUAD's math is off substantially

Here's my code from OrX Kontinuum ... simply put all it does is use the latitude, longitude and altitude of a vessel to check the distance from another vessel using it's latitude, longitude and altitude

Here's my code ... Tell me I'm wrong

Spoiler

        public bool VesselCheck(Vector3d _spawnLoc)
        {
            double _latDiff = 0;
            double _lonDiff = 0;
            double _altDiff = 0;
            bool _gateFound = false;

            List<Vessel>.Enumerator v = FlightGlobals.Vessels.GetEnumerator();
            while (v.MoveNext())
            {
                if (v.Current != null && v.Current.loaded && !v.Current.packed)
                {
                    if (v.Current.rootPart.Modules.Contains<ModuleOrXStage>() && v.Current.parts.Count >= 3)
                    {
                        if (_spawnLoc.z <= v.Current.altitude)
                        {
                            _altDiff = v.Current.altitude - _spawnLoc.z;
                        }
                        else
                        {
                            _altDiff = _spawnLoc.z - v.Current.altitude;
                        }

                        if (v.Current.latitude>= 0)
                        {
                            if (_spawnLoc.x >= v.Current.latitude)
                            {
                                _latDiff = _spawnLoc.x - v.Current.latitude;
                            }
                            else
                            {
                                _latDiff = v.Current.latitude - _spawnLoc.x;
                            }
                        }
                        else
                        {
                            if (_spawnLoc.x >= 0)
                            {
                                _latDiff = _spawnLoc.x - v.Current.latitude;
                            }
                            else
                            {
                                if (_spawnLoc.x <= v.Current.latitude)
                                {
                                    _latDiff = _spawnLoc.x - v.Current.latitude;
                                }
                                else
                                {

                                    _latDiff = v.Current.latitude - _spawnLoc.z;
                                }
                            }
                        }

                        if (v.Current.longitude >= 0)
                        {
                            if (_spawnLoc.y >= v.Current.longitude)
                            {
                                _lonDiff = _spawnLoc.y - v.Current.longitude;
                            }
                            else
                            {
                                _lonDiff = v.Current.longitude - _spawnLoc.y;
                            }
                        }
                        else
                        {
                            if (_spawnLoc.y >= 0)
                            {
                                _lonDiff = _spawnLoc.y - v.Current.longitude;
                            }
                            else
                            {
                                if (_spawnLoc.y <= v.Current.longitude)
                                {
                                    _lonDiff = _spawnLoc.y - v.Current.longitude;
                                }
                                else
                                {

                                    _lonDiff = v.Current.latitude - _spawnLoc.z;
                                }
                            }
                        }

                        double diffSqr = (_latDiff * _latDiff) + (_lonDiff * _lonDiff);
                        double _altDiffDeg = _altDiff * (((2 * (FlightGlobals.ActiveVessel.mainBody.Radius + FlightGlobals.ActiveVessel.altitude)) * Math.PI) / 360);
                        double altAdded = (_altDiffDeg * _altDiffDeg) + diffSqr;
                        double _targetDistance = Math.Sqrt(altAdded) * (1 / (((2 * (FlightGlobals.ActiveVessel.mainBody.Radius + FlightGlobals.ActiveVessel.altitude)) * Math.PI) / 360));

                        if (_targetDistance <= 10)
                        {
                            _gateFound = true;
                            break;
                        }
                    }
                }
            }
            v.Dispose();
            return _gateFound;
        }

 

Yes, you can see I am not wrong :wink:

If you do not understand the code in the spoiler, let me break it down for you .... I am using Pythagoras' theorem to calculate  the distance to the target

Using the double values for latitude, longitude and altitude of a given vessel I calculate it's distance from a second vessel ... My math is sound, no mistakes in the code as confirmed by a professor at Toronto University (I asked as a sanity check)

Turns out there is a fairly major discrepancy in the tune of 200 meters or so at 24 to 25 km ... Methinks @SQUAD might want to look into this

EDIT: So it turns out that my math was right ... I was just using the wrong math :blush:

 

Edited by DoctorDavinci
Link to comment
Share on other sites

Well.  I'm just going to take a guess.  Do you want line of sight or great circle distance?  And what are Squad reporting?  Both kinds are useful in different contexts.  (KER, for example, reports line of sight, to the best of my determination.  Atmospheric Autopilot reports great circle distance...)

Furthermore, I see you are using trig for long/lat meaning you are computing circumferences (great circle) but then you appear to be using Pythag (line of sight/Cartesian) mixed in.

And you're writing out long if statements to accomplish the calculation of abs() values.  I'll add that the only way you use _latdiff, for example, is to square it anyway, so whether you have the abs value or not is irrelevant as -5 * -5 = 5 * 5 = 25.

I'm betting on Squad.  But if you want help, let me know exactly what you are trying to achieve, and I'll help you, best I can.  HNY.

Edited by Hotel26
Link to comment
Share on other sites

On 1/1/2020 at 1:39 AM, Hotel26 said:

Well.  I'm just going to take a guess.  Do you want line of sight or great circle distance?  And what are Squad using?  Both kinds are useful in different contexts.

Furthermore, I see you are using trig for long/lat meaning you are computing circumferences (great circle) but then you appear to be using Pythag (line of sight/Cartesian) mixed in.

And you're writing out long if statements to accomplish the calculation of abs() values.

I'm betting on Squad.

Nope, you're wrong ... that is the math, can't argue with the math

Let me break it down further for you since you seem to not understand what is going on

The code below just initializes the values in the method

            double _latDiff = 0;
            double _lonDiff = 0;
            double _altDiff = 0;

The line below grabs the list of vessels in the flight scene (all vessels)

            List<Vessel>.Enumerator v = FlightGlobals.Vessels.GetEnumerator();

The next line is used to iterate through each vessel in the list

            while (v.MoveNext())

Within the while (v.MoveNext())  deal I calculate the altitude of the targeted vessel and determine which is higher (altDiff = which altitude is the highest ... Altitude calculated from the radius of the celestial body plus the double value of the altitude of the vessel in question)

                        if (_spawnLoc.z <= v.Current.altitude)
                        {
                            _altDiff = v.Current.altitude - _spawnLoc.z;
                        }
                        else
                        {
                            _altDiff = _spawnLoc.z - v.Current.altitude;
                        }

After calculating the altitude I then calculate the difference in degrees of latitude (latDiff = difference in lattitude ... the math below is perfectly clear and is irrefutable)

                        if (v.Current.latitude>= 0)
                        {
                            if (_spawnLoc.x >= v.Current.latitude)
                            {
                                _latDiff = _spawnLoc.x - v.Current.latitude;
                            }
                            else
                            {
                                _latDiff = v.Current.latitude - _spawnLoc.x;
                            }
                        }
                        else
                        {
                            if (_spawnLoc.x >= 0)
                            {
                                _latDiff = _spawnLoc.x - v.Current.latitude;
                            }
                            else
                            {
                                if (_spawnLoc.x <= v.Current.latitude)
                                {
                                    _latDiff = _spawnLoc.x - v.Current.latitude;
                                }
                                else
                                {

                                    _latDiff = v.Current.latitude - _spawnLoc.z;
                                }
                            }
                        }

Then I calculate the difference in longitude (same deal as the latitude calculation ... completely irrefutable unless you're using non reality mathematics in another universe)

                        if (v.Current.longitude >= 0)
                        {
                            if (_spawnLoc.y >= v.Current.longitude)
                            {
                                _lonDiff = _spawnLoc.y - v.Current.longitude;
                            }
                            else
                            {
                                _lonDiff = v.Current.longitude - _spawnLoc.y;
                            }
                        }
                        else
                        {
                            if (_spawnLoc.y >= 0)
                            {
                                _lonDiff = _spawnLoc.y - v.Current.longitude;
                            }
                            else
                            {
                                if (_spawnLoc.y <= v.Current.longitude)
                                {
                                    _lonDiff = _spawnLoc.y - v.Current.longitude;
                                }
                                else
                                {

                                    _lonDiff = v.Current.latitude - _spawnLoc.z;
                                }
                            }
                        }

I then calculate the hypotenuse using the following  (Pythagoras perhaps?)

                        double diffSqr = (_latDiff * _latDiff) + (_lonDiff * _lonDiff);

I then use the altDiff to calculate the exact amount of degree difference

                        double _altDiffDeg = _altDiff * (((2 * (FlightGlobals.ActiveVessel.mainBody.Radius + FlightGlobals.ActiveVessel.altitude)) * Math.PI) / 360);

The above gives me how many degrees (in doubles) there is in altitude between the two vessles ... I then calculate the altitude to add using the altDiff squared plus the diffSqr calculated two steps above

                        double altAdded = (_altDiffDeg * _altDiffDeg) + diffSqr;

I then calculate the actual distance, using Pythagoras' Theorem

                        double _targetDistance = Math.Sqrt(altAdded) * (1 / (((2 * (FlightGlobals.ActiveVessel.mainBody.Radius + FlightGlobals.ActiveVessel.altitude)) * Math.PI) / 360));

 

 

 

Edited by DoctorDavinci
Link to comment
Share on other sites

3 minutes ago, DoctorDavinci said:

In conclusion, Squads distance calculations are just wrong

Perhaps they are.  But the game has been out for ~8 years, and the stock game and mods have always seemed to handled these possible discrepancies with no issues.  Maybe they are wrong, but if it doesn't affect anything....

Link to comment
Share on other sites

6 minutes ago, Gargamel said:

Perhaps they are.  But the game has been out for ~8 years, and the stock game and mods have always seemed to handled these possible discrepancies with no issues.  Maybe they are wrong, but if it doesn't affect anything....

I'm pretty sure this is part of why the targeting for BD Armory is off ... KSP using doubles for the coord system ... Unity can only use float values for anything as doubles are not in its repetoire

When you convert a double based vector to a float based vector you lose accuracy ... my math is sound as confirmed by a math prof at Toronto University (not to menton a few other people) so the distance calculations are off ... no question about it

 

Edited by DoctorDavinci
Link to comment
Share on other sites

21 minutes ago, Hotel26 said:

argument from authority

Think so? .... I don't

It is not an argument from authority, just a confirmation of my math

Please, prove my math wrong... I beg you

Over 28000 lines of code in here .... show me where I went wrong

https://github.com/DoctorDavinci/OrX_Kontinuum

Evidence instead of assertions please :)

Honestly, do I need to break down the grade 3 mathematics I am using even further?

Edited by DoctorDavinci
Link to comment
Share on other sites

If altDiffDeg is in degrees, and you have the distance in latitude/longitude (which is a flat plane I think?) why don't you use trig to work out the hypotenuse of the triangle?

c8ch9oC.png

Sorry for the font, it was what I had on my computer. And sorry for the way that it smooths my lines.

Also I'm not sure why o = θ^2 + a?

1 hour ago, DoctorDavinci said:

double altAdded = (_altDiffDeg * _altDiffDeg) + diffSqr;

Surely it should be

yDhJhn7.png

Unless of course I've got the meaning of those values completely wrong.

Link to comment
Share on other sites

6 hours ago, DoctorDavinci said:

Turns out there is a fairly major discrepancy in the tune of 200 meters or so at 24 to 25 km ... Methinks

<1%* is not exactly "major" - especially when nothing in the game needs that kind of accuracy for distance calculations. The only thing that jumps out of me that even needs those calculations is rendezvous. If you are 25km out of rendezvous, an extra 200m isn't going to help.

*originally this said 10% because I hadn't had my coffee yet. I was wrong.

Edited by severedsolo
Link to comment
Share on other sites

It is quite a major difference if it does happen, because when doing interplanetary transfers, it could cause you to completely lose the intercept.

Which would actually be a good way of proving this: set up an interplanetary transfer and work out the difference in periapsis altitude this would predict, and see if that does happen.

Also Rule 2.2D (EDIT: as invoked by Gargamel below).

Edited by fulgur
Link to comment
Share on other sites

1 minute ago, fulgur said:

Could you possibly tell me why my maths is wrong? I'm assuming it is but as I don't know why, perhaps you could enlighten me?
Not being sarcastic.

In the case of KSP the issue arises from Unity using float values instead of doubles (which are more precise)

Basically if you have a number that has 15 to 16 decimal places (a double) and then need to convert it to a number that Unity can use (which is a float ... meaning 7 decimal places) you lose a ton of precision

KSP code uses Unity to calculate its vectors and distances which is unable to use doubles (see above)

This causes a discrepancy in the math since, from what I understand, Unity requires any doubles to be converted to floats (7 decimal places instead of 15 to 16)

What is happening, from my perspective, is a truncating effect on vector and distance calculations in the core of KSP due to its code using Unity to do its math instead of doing the math itself

Link to comment
Share on other sites

On 1/1/2020 at 4:07 AM, fulgur said:

Ah. So if that is happening, how can it be fixed? KSP runs on Unity.

 

It's already all there in OrX K ... if they can figure it out that is :wink:

Although my code is licensed GPLv3 so they can't touch it

Edited by DoctorDavinci
Link to comment
Share on other sites

Come up with a couple of ways of proving this:

1) If you change all values to floats, does the difference disappear?
2) If there is a difference which goes up with the distance, couldn't you test whether it has an impact on the game by asking the game for a projected Eeloo periapsis for example, and comparing it with the real value (what it says at periapsis)? Unless that's not the error.

Spoiler

You said that there is a difference of 0.2m at 25km.

Eeloo's SoI is 1.2*10^8km. Its Pe is 6.7 * 10^10km while Kerbin's Ap is 1.3 * 10^10km. Therefore the shortest distance is 5.4 * 10^10, which is 520 000 000x bigger than 25km.

So the error of 0.2km will be multiplied to 104 000 000 km, or 1.04 * 10^8. This means that if you have a projected closest approach (periapsis) of more than about 16 000 000km, or 1.6 * 10^7, or 16Mm, this error would mean that you miss Eeloo entirely.

This does make the assumption that you have a K-Drive & go straight from Kerbin to Eeloo on the shortest possible path, while Kerbin is at Ap and Eeloo is at Pe. The error would therefore be even bigger at larger distances.

This is easily testable by mounting an Eeloo mission and seeing if there is any difference between projected Pe and actual Pe (or indeed missing the SoI altogether).

 

Link to comment
Share on other sites

2 hours ago, DoctorDavinci said:

Nope, you're wrong ... that is the math, can't argue with the math

Let me break it down further for you since you seem to not understand what is going on

The code below just initializes the values in the method

            double _latDiff = 0;
            double _lonDiff = 0;
            double _altDiff = 0;

The line below grabs the list of vessels in the flight scene (all vessels)

            List<Vessel>.Enumerator v = FlightGlobals.Vessels.GetEnumerator();

The next line is used to iterate through each vessel in the list

            while (v.MoveNext())

Within the while (v.MoveNext())  deal I calculate the altitude of the targeted vessel and determine which is higher (altDiff = which altitude is the highest ... Altitude calculated from the radius of the celestial body plus the double value of the altitude of the vessel in question)

                        if (_spawnLoc.z <= v.Current.altitude)
                        {
                            _altDiff = v.Current.altitude - _spawnLoc.z;
                        }
                        else
                        {
                            _altDiff = _spawnLoc.z - v.Current.altitude;
                        }

After calculating the altitude I then calculate the difference in degrees of latitude (latDiff = difference in lattitude ... the math below is perfectly clear and is irrefutable)

                        if (v.Current.latitude>= 0)
                        {
                            if (_spawnLoc.x >= v.Current.latitude)
                            {
                                _latDiff = _spawnLoc.x - v.Current.latitude;
                            }
                            else
                            {
                                _latDiff = v.Current.latitude - _spawnLoc.x;
                            }
                        }
                        else
                        {
                            if (_spawnLoc.x >= 0)
                            {
                                _latDiff = _spawnLoc.x - v.Current.latitude;
                            }
                            else
                            {
                                if (_spawnLoc.x <= v.Current.latitude)
                                {
                                    _latDiff = _spawnLoc.x - v.Current.latitude;
                                }
                                else
                                {

                                    _latDiff = v.Current.latitude - _spawnLoc.z;
                                }
                            }
                        }

Then I calculate the difference in longitude (same deal as the latitude calculation ... completely irrefutable unless you're using non reality mathematics in another universe)

                        if (v.Current.longitude >= 0)
                        {
                            if (_spawnLoc.y >= v.Current.longitude)
                            {
                                _lonDiff = _spawnLoc.y - v.Current.longitude;
                            }
                            else
                            {
                                _lonDiff = v.Current.longitude - _spawnLoc.y;
                            }
                        }
                        else
                        {
                            if (_spawnLoc.y >= 0)
                            {
                                _lonDiff = _spawnLoc.y - v.Current.longitude;
                            }
                            else
                            {
                                if (_spawnLoc.y <= v.Current.longitude)
                                {
                                    _lonDiff = _spawnLoc.y - v.Current.longitude;
                                }
                                else
                                {

                                    _lonDiff = v.Current.latitude - _spawnLoc.z;
                                }
                            }
                        }

I then calculate the hypotenuse using the following  (Pythagoras perhaps?)

                        double diffSqr = (_latDiff * _latDiff) + (_lonDiff * _lonDiff);

I then use the altDiff to calculate the exact amount of degree difference

                        double _altDiffDeg = _altDiff * (((2 * (FlightGlobals.ActiveVessel.mainBody.Radius + FlightGlobals.ActiveVessel.altitude)) * Math.PI) / 360);

The above gives me how many degrees (in doubles) there is in altitude between the two vessles ... I then calculate the altitude to add using the altDiff squared plus the diffSqr calculated two steps above

                        double altAdded = (_altDiffDeg * _altDiffDeg) + diffSqr;

I then calculate the actual distance, using Pythagoras' Theorem

                        double _targetDistance = Math.Sqrt(altAdded) * (1 / (((2 * (FlightGlobals.ActiveVessel.mainBody.Radius + FlightGlobals.ActiveVessel.altitude)) * Math.PI) / 360));

In conclusion, Squads distance calculations are just wrong

 

 

Honestly not sure where to begin with how wrong this math is

Link to comment
Share on other sites

15 minutes ago, cineboxandrew said:

Honestly not sure where to begin with how wrong this math is

Please, show me where I am wrong ... I beg you

If you know my math is wrong then it should be fairly simple to demonstrate ... meaning you should know where to begin :)

Edited by DoctorDavinci
Link to comment
Share on other sites

22 minutes ago, cineboxandrew said:

I then calculate the hypotenuse using the following  (Pythagoras perhaps?)

                        double diffSqr = (_latDiff * _latDiff) + (_lonDiff * _lonDiff);

It doesn’t work like that, the Pythagorean theorem works on linear directions in cartesian space, not angles in spherical space. If you start at the equator and go 90° east and 90° north, you’re 90° from your starting point, not 127°

 

24 minutes ago, cineboxandrew said:

I then use the altDiff to calculate the exact amount of degree difference

                        double _altDiffDeg = _altDiff * (((2 * (FlightGlobals.ActiveVessel.mainBody.Radius + FlightGlobals.ActiveVessel.altitude)) * Math.PI) / 360);

The above gives me how many degrees (in doubles) there is in altitude between the two vessles ... I then calculate the altitude to add using the altDiff squared plus the diffSqr calculated two steps above

Degrees of altitude? What does that even mean? Why are you multiplying the altitude by pi?

This whole set of code will work fine for small angles (see the small angle approximation) but completely fall apart with larger distance in any axis but r, but of course you only tested it in the r axis...

if you want the real formula for distance between points in a spherical coordinate system, look at this stack exchange post

Link to comment
Share on other sites

17 minutes ago, cineboxandrew said:

It doesn’t work like that, the Pythagorean theorem works on linear directions in cartesian space, not angles in spherical space. If you start at the equator and go 90° east and 90° north, you’re 90° from your starting point, not 127°

 

Degrees of altitude? What does that even mean? Why are you multiplying the altitude by pi?

This whole set of code will work fine for small angles (see the small angle approximation) but completely fall apart with larger distance in any axis but r, but of course you only tested it in the r axis...

if you want the real formula for distance between points in a spherical coordinate system, look at this stack exchange post

lol 

So I am calculating which of the vessels have a higher altitude and using that altitude and adding it to the radius of the celestial body 

I then take the latitude of each vessel and through math figure out which has a higher value and also check if the value is negative (I do this for longitude as well)

After calculating those values I have the lengths of the three sides of a right angle triangle ... math much?

Simple math gives me a distance ... where is this wrong?

You do realize that there is more than one way to skin a cat, no? ... meaning there is more than one way to calculate distance between two points in 3D space?

EDIT: Actually there is really only one way to get the hypotenuse of a right angle triangle that I know of ... do you know of other ways, I'd like to know what they are

EDIT 2: Still haven't shown where the math is wrong .... still waiting :)

Edited by DoctorDavinci
Link to comment
Share on other sites

1 hour ago, fulgur said:

Come up with a couple of ways of proving this:

1) If you change all values to floats, does the difference disappear?
2) If there is a difference which goes up with the distance, couldn't you test whether it has an impact on the game by asking the game for a projected Eeloo periapsis for example, and comparing it with the real value (what it says at periapsis)? Unless that's not the error.

  Reveal hidden contents

You said that there is a difference of 0.2m at 25km.

Eeloo's SoI is 1.2*10^8km. Its Pe is 6.7 * 10^10km while Kerbin's Ap is 1.3 * 10^10km. Therefore the shortest distance is 5.4 * 10^10, which is 520 000 000x bigger than 25km.

So the error of 0.2km will be multiplied to 104 000 000 km, or 1.04 * 10^8. This means that if you have a projected closest approach (periapsis) of more than about 16 000 000km, or 1.6 * 10^7, or 16Mm, this error would mean that you miss Eeloo entirely.

This does make the assumption that you have a K-Drive & go straight from Kerbin to Eeloo on the shortest possible path, while Kerbin is at Ap and Eeloo is at Pe. The error would therefore be even bigger at larger distances.

This is easily testable by mounting an Eeloo mission and seeing if there is any difference between projected Pe and actual Pe (or indeed missing the SoI altogether).

 

You have forgotten that there is a maximum discrepancy of 0.0000001 in the calculations ... meaning there is a maximum distance discrepancy that will limit the error factor

Link to comment
Share on other sites

When did you say that?
Also the error from your own example was 0.008! (0.2km divided by 25km).


As well as this there is a difference in lat/long depending on altitude, because lat/long are based on degrees and that changes depending on altitude:

tb4SlEl.png

Here you can see the extra distance.

Edited by fulgur
Link to comment
Share on other sites

3 hours ago, fulgur said:

When did you say that?
Also the error from your own example was 0.008! (0.2km divided by 25km).

I didn't say it, I assumed it was a given that those reading this thread would realize that is the case ... my bad

3 hours ago, fulgur said:

As well as this there is a difference in lat/long depending on altitude, because lat/long are based on degrees and that changes depending on altitude:

tb4SlEl.png

Here you can see the extra distance.

There is not a difference in lat/long, it's actually a difference in how many meters are in a degree ... more specifically a difference In degrees per meter of distance at a given altitude

That is what most of the math is for, calculating how many meters are in a degree at a given altitude (I use the higher of the two) 

The math isn't wrong, that I am sure of

Still waiting for proof that it is wrong ... any takers @cineboxandrew, @Hotel26?

Edited by DoctorDavinci
Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...