Jump to content

Altitude above ground level?


Recommended Posts

This might be obvious to some of you, but I haven\'t been able to figure it out: Which structure/class contains the ship\'s altitude above ground level (or the ground elevation at the ship\'s location)?

I\'ve tried the following code in my \'onPartUpdate\' handler:

Vector3d dR3Position = vessel.findWorldCenterOfMass();

dASLAltitude = vessel.mainBody.GetAltitude(dR3Position);

dLatitude = vessel.mainBody.GetLatitude(dR3Position);

dLongitude = vessel.mainBody.GetLongitude(dR3Position);

I\'ve then used those values in \'GetRelSurfacePosition\' and \'GetWorldSurfacePosition\'. Both these functions take Lat/Lon/Alt as inputs.

I assume that the return value for \'GetRelSurfacePosition\' and \'GetWorldSurfacePosition\' is a vector describing the distance between the ground at some reference location and the specified lat/lon/alt. I hacked at it for about an hour last night (using a callback function to display various values to the screen) but I couldn\'t find an algorithm to output altitude above ground level. I only seemed to be able to get various incarnations of altitude above sea level...

I would have thought this should be easy. What am I missing?

Thanks in advance to anyone who can point me in the right direction.

Link to comment
Share on other sites

The GetRelSurfacePosition method doesn\'t take into account terrain elevation. It returns a position vector that is relative to the planet and it\'s own rotation.

Currently, there is no direct way to get the terrain height from the given position. What you can do though, is raycast down to the surface using a layerMask of 1 << 15. If that hits something, you\'ll know there is terrain below, and you can then use the raycast distance (hit.distance) to get the \'radar altitude\'.

For more information on raycasts, check out the Unity documentation on Physics.Raycast.

Hope this helps.

Cheers

Link to comment
Share on other sites

Thank you Harv! That seems to have worked.

Now my next question is: What bit should be set in the layerMask so that water is also detected? The raycast function doesn\'t seem to detect water when only the 15th bit is set?

I\'ll test it some more this evening.

Link to comment
Share on other sites

Height over water is exactly the altitude reported by the functions like getAltitudeAtPos, no need to consider it approximate.

You are right, but in order to use your suggestion, the module would need to detect whether it is over water or not.

The layerMask selectively filters out colliders when the raycast function is called. I suspect that water has its own filter bit in the layerMask. Maybe I\'ll just have to experiment to figure out what it is.

Link to comment
Share on other sites

You are right, but in order to use your suggestion, the module would need to detect whether it is over water or not.

The Raycast function returns a success flag. If you\'re casting a ray from your ship to the center of the planet and you don\'t hit anything, you\'re over water. (I\'m trying to think of edge cases where this isn\'t true, but nothing\'s coming to me.)

Link to comment
Share on other sites

The Raycast function returns a success flag. If you\'re casting a ray from your ship to the center of the planet and you don\'t hit anything, you\'re over water. (I\'m trying to think of edge cases where this isn\'t true, but nothing\'s coming to me.)

Hmmm. That\'s not what I\'m experiencing. The raycast function also returns a hit distance. Its value is consistent with altitude AGL.

In my case, I still get an altitude when I hover over (or land in) the water. I assume that the value I\'m seeing is the distance through the water to the 'bottom'? Maybe I need to fly further off shore to see the effect you\'re seeing? Have you tried hovering over the water close to KSC? What happens for you?

Link to comment
Share on other sites

If you want to return AGL or ASL, depending on which is closer, then you can use Mathf.Min( FlightGlobals.getAltitudeAtPos(...), {raycastthingy} ) to pick whichever value is least; ie, which you are closest to.

Link to comment
Share on other sites

Hmmm. That\'s not what I\'m experiencing. The raycast function also returns a hit distance. Its value is consistent with altitude AGL.

In my case, I still get an altitude when I hover over (or land in) the water. I assume that the value I\'m seeing is the distance through the water to the 'bottom'? Maybe I need to fly further off shore to see the effect you\'re seeing? Have you tried hovering over the water close to KSC? What happens for you?

If you hover over the water very near KSC, you indeed hit the ground below. When you go further, Physics.Raycast() will return false.

You\'re correct that identifying a bitmask which also detects water would be more useful. To be honest, I might just raycast everything, so I can also detect landed ships. :)

Link to comment
Share on other sites

You could make it return erroneous results (eg, add a random variance to it) when over water, since it\'s not exactly the stillest of surfaces.

For my purpose (landing computer) I actually simulate the water as being farther down than it really is. Coming to a near-stop at water level isn\'t so great, because then your engines shut off and the craft plunges in.

I\'ve thought about making some kind of radar part which would give plugins easy access to this kind of information, but I imagine the requirements of each plugin are too different to neatly wrap them all up into one device.

Link to comment
Share on other sites

  • 2 weeks later...

Thanks to all who contributed so far, this thread has been immensely helpful.

I (think I) have finally managed to figure out how to get altitude above ground. What puzzles me is AGL appears conclusive up to about 10km (± ~3) ASL, but from then on Raycast() indicates no more hits.

I\'m using [tt]Physics.Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitInfo, float distance, int layerMask)[/tt] with

origin = (Vector3)vessel.rigidbody.position // vessel\'s position
direction = (Vector3)(-((origin - vessel.mainBody.position).normalized)) // vector to centre of reference body
distance = (float)vessel.mainBody.GetAltitude (origin) + 12345.6f // ASL plus some offset, just to be safe
layerMask = 1<<15 // from Harv\'s post above

I am wondering, is this some limitation of the physics engine, or am I missing something fundamental?

PS.:

Just FYI, as there appeared to be some uncertainty regarding the layer mask, the reported altitude appears correct over land as well as water, sea bottom seems to fall sharply in the waters east of KSC (and IIRC, even before the terrain update) – as long as anything is reported at all, but I don\'t see any relation to whether it\'s above land or water.

Link to comment
Share on other sites

  • 1 year later...
If you hover over the water very near KSC, you indeed hit the ground below. When you go further, Physics.Raycast() will return false.

You're correct that identifying a bitmask which also detects water would be more useful. To be honest, I might just raycast everything, so I can also detect landed ships. :)

Found this thread when looking for a way to make rays collide with the ocean, and decided to try out raycasting with all 32 possible individual masks. Unfortunately, none of them collide with the ocean. However, there are other ways around this, of course, if you remember your trig. Obviously, this only matters if you need distance at an angle other than straight down, as pqs gives you that.

Unfortunately, I had trig many years ago and have had extremely little use for it (until now!) and so I've forgotten much of it. I'm in the process of relearning it, but if someone else beats me to a solution, feel free to post it.

Link to comment
Share on other sites

Also, it looks like some properties have been added since the original thread. I use the following in my height control mod for height from terrain.

if(FlightGlobals.ActiveVessel.heightFromTerrain >= 0) 
{
AltitudeAboveGround = Mathf.Min(FlightGlobals.ActiveVessel.heightFromTerrain, FlightGlobals.ActiveVessel.altitude)
}

.altitude is your height above sea level as reported at the top of the screen.

.heightFromTerrain is your height above terrain, ignoring water. So over shallow water, out to a seabed depth of about 600meters, .heightFromTerrain will return altitude to the sea bed. Deeper then that it looks like the 'terrain' object does not exist and .heightFromTerrain returns -1

Therefore the IF statement is required to error trap the .heightFromTerrain value and give you your current height above ground or water.

Note that both these are relative to your active vessel's center of mass, not the side of the vessel closest to ground.

D.

Edited by Diazo
Link to comment
Share on other sites

Found this thread when looking for a way to make rays collide with the ocean, and decided to try out raycasting with all 32 possible individual masks. Unfortunately, none of them collide with the ocean. However, there are other ways around this, of course, if you remember your trig. Obviously, this only matters if you need distance at an angle other than straight down, as pqs gives you that.

Unfortunately, I had trig many years ago and have had extremely little use for it (until now!) and so I've forgotten much of it. I'm in the process of relearning it, but if someone else beats me to a solution, feel free to post it.

unfortunately, PQS doesn't really work that well. I attached a gui element, used celestialBody.pqsController.GetSurfaceHeight(pos), and created a rover that displayed my terrain height and drove it around. There were lots of times where it was flat out wrong, dipping up or down (sometimes as much as 20m).

Link to comment
Share on other sites

Also, it looks like some properties have been added since the original thread. I use the following in my height control mod for height from terrain.

if(FlightGlobals.ActiveVessel.heightFromTerrain >= 0) 
{
AltitudeAboveGround = Mathf.Min(FlightGlobals.ActiveVessel.heightFromTerrain, FlightGlobals.ActiveVessel.altitude)
}

.altitude is your height above sea level as reported at the top of the screen.

.heightFromTerrain is your height above terrain, ignoring water. So over shallow water, out to a seabed depth of about 600meters, .heightFromTerrain will return altitude to the sea bed. Deeper then that it looks like the 'terrain' object does not exist and .heightFromTerrain returns -1

Therefore the IF statement is required to error trap the .heightFromTerrain value and give you your current height above ground or water.

Note that both these are relative to your active vessel's center of mass, not the side of the vessel closest to ground.

D.

Unfortunately that does not work at all. I had a talk with Mu a while ago while I was figuring this out myself for RealChute. Turns out that vessel.heightFromTerrain should actually be a private field. It's rarely ever used for the game, and definitely isn't what you are looking for there. RealChute confirmed it the hard way for me (meeting a mountain at high velocity).

unfortunately, PQS doesn't really work that well. I attached a gui element, used celestialBody.pqsController.GetSurfaceHeight(pos), and created a rover that displayed my terrain height and drove it around. There were lots of times where it was flat out wrong, dipping up or down (sometimes as much as 20m).

That one is going a little complex. Actually, the way to get terrain altitude is vessel.pqsAltitude. Mu directed me to that one actually, and I can confirm that it returns the height of the terrain, and that it does not clamp to ocean. However it's quite easy to get it with something like this:

double terrainAlt = this.vessel.ocean ? Math.Max(this.vessel.pqsAltitude, 0d) : this.vessel.pqsAltitude;

However this returns the altitude directly below the ship's COM. You could indeed get it with some trig, and I could help you with it in #kspmodders if you wait for me to get home later :P

Link to comment
Share on other sites

Unfortunately that does not work at all. I had a talk with Mu a while ago while I was figuring this out myself for RealChute. Turns out that vessel.heightFromTerrain should actually be a private field. It's rarely ever used for the game, and definitely isn't what you are looking for there. RealChute confirmed it the hard way for me (meeting a mountain at high velocity).

Odd, I guess I got lucky then.

I've been using it for several versions of my height control mod now and I display that value as height from terrain on my mod and when I look at it the number seems reasonable.

I've never checked when doing something that changes the CoM location though such as deploying a parachute does. (I assume deploying a parachute change the CoM location anyway.)

Since that is straight from Mu though I'll look at switching to the the .pqsAltitude property.

D.

Link to comment
Share on other sites

Odd, I guess I got lucky then.

I've been using it for several versions of my height control mod now and I display that value as height from terrain on my mod and when I look at it the number seems reasonable.

I've never checked when doing something that changes the CoM location though such as deploying a parachute does. (I assume deploying a parachute change the CoM location anyway.)

Since that is straight from Mu though I'll look at switching to the the .pqsAltitude property.

D.

If I remember correctly, this is only when the vessel is landed. Or something like that.

Link to comment
Share on other sites

I've been looking at KER recently and it uses:

vessel.mainBody.GetAltitude(vessel.CoM) - vessel.terrainAltitude

(well, it has some spurious "this." in there too).

Is this wrong? I don't recall the readout being obviously wrong when driving a rover around...

Link to comment
Share on other sites

I've been looking at KER recently and it uses:

vessel.mainBody.GetAltitude(vessel.CoM) - vessel.terrainAltitude

(well, it has some spurious "this." in there too).

Is this wrong? I don't recall the readout being obviously wrong when driving a rover around...

According to Mu it could have unpredictable effects. On my side it had the effect of smashing my first test pods in the mountains when I first drafted RealChute. It doesn't seem to be as much on target as it always should.

Link to comment
Share on other sites

Anyway, this is what I came up with for distance & surface normal at an angle (with respect to the ocean--the intent being to take to compare with a raycast, take the min() of the distances, and then decide the correct normal based on that):

dAGb9jd.png

I originally thought I could solve this relatively easily with the law of cosines, until I realized that that's intended for finding the angle between two known sides, and not when you have an angle next to only one known side. I still think it's applicable, just I have to derive exactly what I need correctly.

p.s. - In case it wasn't apparent, ignore the tangential line for the side of the triangle labeled "r+a", as that is the length of the full side, not just to where it intersects the tangent.

Edited by Orum
Link to comment
Share on other sites

Okay, quick 5 second test.

FlightGlobals.ActiveVessel.pqsAltitude (field) looks to be what to use. It returns the height of the terrain below the vessel's CoM as altitude above sea level (to the terrain, not the vessel).

There is also a FlightGlobals.ActiveVessel.PqsAltitude() method that also returns a double, but in a quick run in a rover around KSC, the .psqAltitude field was more accurate.

Note that .pqsAltitude returns a negative number over water, so I will confirm that your vessel's current altitude above terrain is:

VesselAboveTerrain = FlightGlobals.ActiveVessel.altitude - Math.Max(FlightGlobals.ActiveVessel.pqsAltitude,0);

The Math.Max ensures that if you are over water, the negative number for the seabed is not used.

D.

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...