Jump to content

Finding the height of the lowest point on my vessel


Recommended Posts

I'm working on a landing plugin. So far I've been using vessel.heightFromTerrain and vessel.altitude to determine how high up I am. However I just noticed that those values are measured from the center of mass for my vessel. What I really care about is the distance the vessel can travel before some part of it touches the ground. So I'm more concerned with the very bottom of my vessel than the CoM. Any suggestions on how I might go about getting more accurate readings? Is there some way to query the coordinates of each part?

Thanks!

Link to comment
Share on other sites

vessel.heightFromTerrain is not something I would use. It's either deprecated or unused, because it does not return what you are looking for. vessel.altitude is also not very reliable.

You'll want to do three things: determine altitude from sea level, determine true altitude from ground as well as ground altitude, and determine what is the lowest part on your vessel and what is the altitude from there.

For the first part: ASL altitude. Probably the easiest. FlightGlobals.getAltitudeAtPos(CoM) will do that. You just need to define your CoM, which can also be made obtained by this.vessel.findWorldCenterOfMass().

For true altitude, there is no easy way to do it. There's no value that currently returns is as is. One of the easiest way to do it in my opinion is with a RayCast. Then you just need to return the smallest distance between ASL altitude and the raycast distance, because it won't consider water as surface, or return ASL if the raycast hits nothing. Then you ca

Then for the lowest part of your vessel, this gets tricky. Looking at the MechJeb source code in that case is quite useful. You'll need to loop through all the parts in the vessel. From there, you just want to find the lowest point on each part, get it's altitude from ground, and then compare it to the other part.

It should look something like this:

        public Vector3 CoM, up;
public RaycastHit craft;
public float ASL, trueAlt, surfaceAlt, bottomAlt;

public void Update()
{
CoM = this.vessel.findWorldCenterOfMass(); //Gets CoM
up = FlightGlobals.getUpAxis(CoM); //Gets up axis (needed for the raycast)
ASL = FlightGlobals.getAltitudeAtPos(CoM);
if (Physics.Raycast(CoM, -up, out craft, ASL + 10000f, 1 << 15))
{
trueAlt = Mathf.Min(ASL, craft.distance); //Smallest value between ASL and distance from ground
}

else { trueAlt = ASL; }

surfaceAlt = ASL - trueAlt;
bottomAlt = trueAlt; //Initiation to be sure the loop doesn't return a false value
foreach (Part p in vessel.parts)
{
if (p.collider != null) //Makes sure the part actually has a collider to touch ground
{
Vector3 bottom = p.collider.ClosestPointOnBounds(vessel.mainBody.position); //Gets the bottom point
float partAlt = FlightGlobals.getAltitudeAtPos(bottom) - surfaceAlt; //Gets the looped part alt
bottomAlt = Mathf.Max(0, Mathf.Min(bottomAlt, partAlt)); //Stores the smallest value in all the parts
}
}
}

Hope this helped!

Link to comment
Share on other sites

Thanks Chris, that's exceptionally helpful! And your example even includes a number of nice tricks that I can use to tidy up my code.

I'm curious though, what are vessel.heightFromTerrain and vessel.altitude failing to do correctly? I've tested my part using those calls quite a bit, and at least close to the ground/water the results are reliable to within a meter or two. If FlightGlobals is the proper way to handle this I have no problem switching over, I'd just like to better understand the reasoning.

Link to comment
Share on other sites

I've had no issues with vessel.heightFromTerrain or vessel.altitude being inaccurate.

I believe they report from vessel CoM though so they can't be used to land.

The other limitation is that they report directly below the vessel. If you are moving horizontally over crater edges, the numbers can change very rapidly.

I also had problems with landing which led to the Velocity Control mod in my sig, but as I approached it differently then it sounds like you are I did not need to know the distance to ground you are looking for.

D.

Edited by Diazo
Link to comment
Share on other sites

Thanks Diazo, I'll take a closer look at your code if I get stuck again.

This is only somewhat related, but since you guys have already been so helpful: Is there a way to share a variable between multiple instances of a partmodule? A vessel will typically have several Landertrons attached, but I really shouldn't be redoing these height calculations multiple times per physics step. I'd like to have the first one to load designate itself the master and then share its calculation results with the other units. To do this I think I would need something like a global variable, but I haven't been able to find any relevant examples for KSP.

Link to comment
Share on other sites

Off the top of my head, two variables: VesselHeight(float) and HeightCalced(bool)

First line in the main module would have a HeightCalced=false

Then the Landertron would only calculate VesselHeight if HeightCalced was false, and when it sets VesselHeight it would set HeightCalced to true.

That way only the first Landertron checked would calculate height and height would calculate once per update.

As long as those two variables are static and within the same class, that's the easiest way I know to go about it.

D.

Link to comment
Share on other sites

vessel.heightFromTerrain was returning false values when working with my parachutes. I believe those are all old values from before FlightGlobals was created. They sometimes work, but most often don't. I spoke with Mu and there is no easy way to get true altitude. Sometimes it's better to gow with slightly complicated methods to get a more ac curate result than try to go the easy way that might break in some rare cases.

Link to comment
Share on other sites

I did some experimentation with vessel.heightFromTerrain a while back. There is some weirdness with it and the other altitude fields.

  • heightFromTerrain is the height from the ground, buildings. It becomes -1 when sea depth is greater than 600m (terrainAltitude <= -600).
  • heightFromSurface was always -1 in my testing.
  • pqsAltitude: the altitude above the planet quadtree sphere (the basic low resolution sphere) compared to sea level. It doesn't take buildings into account. It is generally within +/- 1m of terrainAltitude, except when over buildings or sea with a depth of greater than 600m (terrainAltitude <= -600, heightFromTerrain == -1).
  • terrainAltitude is the altitude from solid ground, including buildings and the seabed. Negative values indicate areas which are underwater.

Some of these switch to -1 at orbital altitudes, but that wasn't part of the testing I was doing.

Link to comment
Share on other sites

I did some experimentation with vessel.heightFromTerrain a while back. There is some weirdness with it and the other altitude fields.

  • heightFromTerrain is the height from the ground, buildings. It becomes -1 when sea depth is greater than 600m (terrainAltitude <= -600).
  • heightFromSurface was always -1 in my testing.
  • pqsAltitude: the altitude above the planet quadtree sphere (the basic low resolution sphere) compared to sea level. It doesn't take buildings into account. It is generally within +/- 1m of terrainAltitude, except when over buildings or sea with a depth of greater than 600m (terrainAltitude <= -600, heightFromTerrain == -1).
  • terrainAltitude is the altitude from solid ground, including buildings and the seabed. Negative values indicate areas which are underwater.

Some of these switch to -1 at orbital altitudes, but that wasn't part of the testing I was doing.

I had a chat with Mu the other day, heightFromTerrain and heightFromSurface are supposed to be private variables, and are only used in very specific situations, such as landings and takeoffs, so I don't think we should use them cause they might be very unreliable.

pqsAltitude however is the altitude of the surface relatively from sea level, but does not take in consideration buildings indeed.

I didn't ask for terrainAltitude, but considering pqs is the value we look for, I believe that one falls in the same category as heightFromSurface and heightFromTerrain

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