Jump to content

Prograde, and several other grades. :)


Recommended Posts

I'm trying to do something pretty basic, but it's confounding me... partly because there are about a dozen variables in the KSP API that sound like almost what I'm looking for.

I'm trying to build indicators into my plugin that will help you point towards prograde, retrograde, normal, antinormal, and the next maneuver node.

Ideally, what the user will see at the end of all my math are pitch and yaw numbers that relate where the nose of the ship is pointed to where they want to burn... so as you approach an ascending node during an intercept, the program would start showing you how many degrees you need to pitch and yaw to point anti-normal to match planes with your target, for example. Similarly, as you approach a maneuver node I'd like pitch and yaw numbers that show the relationship of the control transform to the node... and as you plan a circularization I'd like pitch and yaw numbers relative to prograde or retrograde, whether you've got a maneuver node set or not.

I've grabbed the next maneuver node via :

Math.Sqrt(Math.Pow((vessel.patchedConicSolver.maneuverNodes[0].DeltaV.x),2)+Math.Pow((vessel.patchedConicSolver.maneuverNodes[0].DeltaV.y),2)+Math.Pow((vessel.patchedConicSolver.maneuverNodes[0].DeltaV.z),2)).ToString()  ; 

And it seems to come out relative to prograde - as in a prograde burn of 1000m/s will return 0,0,1000.

But I can't figure out how to figure out where the nose of my ship is pointing relative to prograde or the maneuver node. It seems like it should be pretty basic... but all of the variables I've tried so far seem to return world coordinates... or just numbers that don't make sense in context at all.

Art

Link to comment
Share on other sites

have a look at this page (if you didn't allready)

http://wiki.unity3d.com/index.php?title=3d_Math_functions

if might give you an answer..

in general you must do two things

1. find out the nose vector and the prograde vector

2. calculate the angel between them

the tricky part is to split that up in two relative to two planes so you get seperate values..

iirc the page above has a function to do that somewhere..

not sure if it still works - the page is a bit older..

Link to comment
Share on other sites

what you need is

burnV = vessel.patchedConicSolver.maneuverNodes[0].GetBurnVector(vessel.orbit) => the burn direction in world coord

vessel.GetTransform().up / vessel.GetTransform().right / vessel.GetTransform().forward get you your ship orienation in world coord ( KSP mix things up a bit to make things more fun. the up transform vector is the one that point to the front of the ship).

Then you use Vector3d.Exclude to get the burn dir without the right / forward component.

yawnComponent = Vector3d.Exclude(vessel.GetTransform().right, burnV )

pitchComponent = Vector3d.Exclude(vessel.GetTransform().right, burnV )

yawn = Vector3d.Angle( yawnComponent , vessel.GetTransform().up)

pitch= Vector3d.Angle( pitchComponent , vessel.GetTransform().up)

or you transform burnV in coord local to the ship and do you trig math

localBurnV = vessel.GetTransform().InverseTransformDirection(burnV)

Link to comment
Share on other sites

Thank you so much for the help so far! You've definitely got me mostly there!

After a bit of trial and error with the various directions for this.vessel.GetTransform(), I've got pointing at the maneuver node working with the following code:

 Vector3 burnV = this.vessel.patchedConicSolver.maneuverNodes[0].GetBurnVector(this.vessel.orbit);
Vector3 yawnComponent = Vector3d.Exclude(vessel.GetTransform().forward, burnV);
Vector3 pitchComponent = Vector3d.Exclude(vessel.GetTransform().right, burnV);
double yawn = Vector3d.Angle(yawnComponent, vessel.GetTransform().up);
double pitch = Vector3d.Angle(pitchComponent, vessel.GetTransform().up);

And then I figured out how to relate it to Orbital Velocity to get prograde and retrograde.

  Vector3 progradev = this.vessel.GetObtVelocity();
Vector3 yawnComponent = Vector3d.Exclude(vessel.GetTransform().forward, progradev);
Vector3 pitchComponent = Vector3d.Exclude(vessel.GetTransform().right, progradev);
double yawn = Vector3d.Angle(yawnComponent, vessel.GetTransform().up);
double pitch = Vector3d.Angle(pitchComponent, vessel.GetTransform().up);

The only problem I'm left with is that all of this is returning degrees between 0 and 180 without any signs... so the program can't tell if pitch is off by +10 or -10 degrees. I'd really like a way to relate the vessel transform to normal and antinormal... and to tell the difference between the two, but both of those are returning 90,90 in the second set of code there. Is there a way to get a value WITH sign?

Link to comment
Share on other sites

Well, that's what I ment, those functions are on that list..

I didn't test them, but at least they claim to do that

//Get the shortest distance between a point and a plane. The output is signed so it holds information

//as to which side of the plane normal the point is.

public static float SignedDistancePlanePoint(Vector3 planeNormal, Vector3 planePoint, Vector3 point){

return Vector3.Dot(planeNormal, (point - planePoint));

}

//This function calculates a signed (+ or - sign instead of being ambiguous) dot product. It is basically used

//to figure out whether a vector is positioned to the left or right of another vector. The way this is done is

//by calculating a vector perpendicular to one of the vectors and using that as a reference. This is because

//the result of a dot product only has signed information when an angle is transitioning between more or less

//then 90 degrees.

public static float SignedDotProduct(Vector3 vectorA, Vector3 vectorB, Vector3 normal){

Vector3 perpVector;

float dot;

//Use the geometry object normal and one of the input vectors to calculate the perpendicular vector

perpVector = Vector3.Cross(normal, vectorA);

//Now calculate the dot product between the perpendicular vector (perpVector) and the other input vector

dot = Vector3.Dot(perpVector, vectorB);

return dot;

}

public static float SignedVectorAngle(Vector3 referenceVector, Vector3 otherVector, Vector3 normal)

{

Vector3 perpVector;

float angle;

//Use the geometry object normal and one of the input vectors to calculate the perpendicular vector

perpVector = Vector3.Cross(normal, referenceVector);

//Now calculate the dot product between the perpendicular vector (perpVector) and the other input vector

angle = Vector3.Angle(referenceVector, otherVector);

angle *= Mathf.Sign(Vector3.Dot(perpVector, otherVector));

return angle;

}

Link to comment
Share on other sites

I couldn't figure out how to get there from philotical's suggestions, though I'm confident that a few years closer to my math classes I might have figured it out.

What I did find was the signed angle routine in Mechjeb's math library. It gives the signed angle between two vectors, in reference to a third vector perpendicular to them. So I used Vector3.cross to generate a perpendicular vector. Initially the signs flipped at the 90 degree mark (so it would run from 0 to 90, then start going from -91 to -180) so I reversed the signs if the number is above 90 or below -90, and now it works just the way I want it to. For future reference -

 Vector3 burnV = this.vessel.patchedConicSolver.maneuverNodes[0].GetBurnVector(this.vessel.orbit);
Vector3 yawnComponent = Vector3d.Exclude(vessel.GetTransform().forward, burnV);
Vector3 crossp = Vector3.Cross(yawnComponent, vessel.GetTransform().right).normalized;
double yawn = AngleSigned(yawnComponent, vessel.GetTransform().up, crossp);
if (yawn > 90){
yawn = yawn * -1f;
} else if (yawn < -90){
yawn = yawn * -1f;
}

Vector3 pitchComponent = Vector3d.Exclude(vessel.GetTransform().right, burnV); \
crossp = Vector3.Cross(pitchComponent, vessel.GetTransform().forward).normalized;
double pitch = AngleSigned(pitchComponent, vessel.GetTransform().up, crossp);
if (pitch > 90){
pitch = pitch * -1f;
} else if (pitch < -90){
pitch = pitch * -1f;
}

Everything works just the way I want it to - 0,0 is prograde, 180,180 is retrograde, 90,-90 is antinormal and -90,90 is normal.

Thank you both for your help!

Art

Link to comment
Share on other sites

  • 3 months later...

Everything works just the way I want it to - 0,0 is prograde, 180,180 is retrograde, 90,-90 is antinormal and -90,90 is normal.

Art

this was exactly what I needed yesterday - thanks for sharing..

you don't have by any chance the "roll" version handy?

I'm still experimenting with what vectors to substitute - but my vector math is as low as it can be..

Link to comment
Share on other sites

...vessel.GetTransform().up / vessel.GetTransform().right / vessel.GetTransform().forward get you your ship orienation in world coord ( KSP mix things up a bit to make things more fun. the up transform vector is the one that point to the front of the ship)....

Wouldn't he need vessel.ReferenceTransform? or does GetTransform() now return the correct transform in regard to which part you are controlling from (ie.: ReferenceTransform)?

Link to comment
Share on other sites

  • 10 months later...

This thread was super helpful for me trying to figure out how to find pitch and yaw of various orbital vectors relative to my vessel heading. Thanks. :D

One problem though, is that calculating pitch and yaw independently means they are inaccurate when either of them have a magnitude greater than 90. For the prograde heading, the relative pitch and yaw come out as (0, 0) when the vessel is pointed prograde, but (180,180) when it's pointed retrograde. I'd expect either (180,0) or (0, 180).

This is what I ended up writing. It seems to work well so far. It returns a yaw between -180 and 180, and a pitch between -90 and 90.

 

 
        private float[] getOffsetFromHeading(Vessel ActiveVessel, Vector3d targetVector)
        {
            Vector3d yawComponent = Vector3d.Exclude(ActiveVessel.GetTransform().forward, targetVector);
            Vector3d yawCross = Vector3d.Cross(yawComponent, ActiveVessel.GetTransform().right);
            float yaw = SignedVectorAngle(yawComponent, ActiveVessel.GetTransform().up, yawCross);

            Vector3d pitchComponent = Vector3d.Exclude(ActiveVessel.GetTransform().right, targetVector);
            Vector3d pitchCross = Vector3d.Cross(pitchComponent, ActiveVessel.GetTransform().forward);
            float pitch = SignedVectorAngle(pitchComponent, ActiveVessel.GetTransform().up, pitchCross);

            if (Math.Abs(yaw) > 90) {
                yaw = -yaw;
                // This condition makes sure progradePitch doesn't wrap from -x to 360-x
                if (pitch > 0) {
                    pitch = pitch - 180;
                } else {
                    pitch = pitch + 180;
                }
            }
            return new float[] {pitch, yaw};
        }

        private float SignedVectorAngle(Vector3d referenceVector, Vector3d otherVector, Vector3d normal)
        {
            Vector3d perpVector;
            float angle;
            //Use the geometry object normal and one of the input vectors to calculate the perpendicular vector
            perpVector = Vector3d.Cross(normal, referenceVector);
            //Now calculate the dot product between the perpendicular vector (perpVector) and the other input vector
            angle = Vector3d.Angle(referenceVector, otherVector);
            angle *= Mathf.Sign(Vector3d.Dot(perpVector, otherVector));

            return angle;
        }

 

Edited by stibbons
yay syntax highlighted code block
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...