Direction objects represent a rotation starting from an initial point in KSP‘s coordinate system where the initial state was looking down the \(+z\) axis, with the camera “up” being the \(+y\) axis. This exists primarily to enable automated steering.
In your thinking, you can largely think of Directions as being Rotations and Rotations as being Directions. The two concepts can be used interchangeably. Used on its own to steer by, a rotation from the default XYZ axes of the universe into a new rotation does in fact provide an absolute direction, thus the name Direction for these objects even though in reality they are just Rotations. It’s important to know that Directions are just rotations because you can use them to modify other directions or vectors.
When dealing with Directions (which are Rotations) in kOS, it is important to remember that KSP uses a left-handed coordinate system. This affects the convention of which rotation direction is positive when calculating angles.
||Looking along vector lookAt, rolled so that lookUp is upward.|
||A rotation that would rotate the universe around an axis|
||A rotation that would go from vectors fromVec to toVec|
|FACING||From SHIP or TARGET|
|PROGRADE, etc.||From SHIP, TARGET or BODY|
SET myDir TO R( a, b, c ).
Directioncan also be created out of a Quaternion tuple, indicated with the
Q()function, passing it the x, y, z, w values of the Quaternion. The concept of a Quaternion uses complex numbers and is beyond the scope of the kOS documentation, which is meant to be simple to understand. It is best to not use the Q() function unless Quaternions are something you already understand.
SET myDir TO Q( x, y, z, w ).
SET myDir TO HEADING(degreesFromNorth, pitchAboveHorizon).
The third parameter, roll, is optional. Roll indicates rotation about the longitudinal axis.
Directioncan be created with the LOOKDIRUP function by using two vectors. This is like converting a vector to a direction directly, except that it also provides roll information, which a single vector lacks. lookAt is a vector describing the Direction’s FORE orientation (its local Z axis), and lookUp is a vector describing the direction’s TOP orientation (its local Y axis). Note that lookAt and lookUp need not actually be perpendicualr to each other - they just need to be non-parallel in some way. When they are not perpendicular, then a vector resulting from projecting lookUp into the plane that is normal to lookAt will be used as the effective lookUp instead:
// Aim up the SOI's north axis (V(0,1,0)), rolling the roof to point to the sun. LOCK STEERING TO LOOKDIRUP( V(0,1,0), SUN:POSITION ). // // A direction that aims normal to orbit, with the roof pointed down toward the planet: LOCK normVec to VCRS(SHIP:BODY:POSITION,SHIP:VELOCITY:ORBIT). // Cross-product these for a normal vector LOCK STEERING TO LOOKDIRUP( normVec, SHIP:BODY:POSITION).
Directioncan be created with the ANGLEAXIS function. It represents a rotation of degrees around an axis of axisVector. To know which way a positive or negative number of degrees rotates, remember this is a left-handed coordinate system:
// Pick a new rotation that is pitched 30 degrees from the current one, taking into account // the ship's current orientation to decide which direction is the 'pitch' rotation: // SET pitchUp30 to ANGLEAXIS(-30,SHIP:STARFACING). SET newDir to pitchUp30*SHIP:FACING. LOCK STEERING TO newDir.
The fact that KSP is using a left-handed coordinate system is important to keep in mind when visualizing the meaning of an ANGLEAXIS function call. It affects which direction is positive when calculating angles.
Directioncan be created with the
ROTATEFROMTOfunction. It is one of the infinite number of rotations that could rotate vector fromVec to become vector toVec (or at least pointing in the same direction as toVec, since fromVec and toVec need not be the same magnitude). Note the use of the phrase “infinite number of”. Because there’s no guarantee about the roll information, there are an infinite number of rotations that could qualify as getting you from one vector to another, because there’s an infinite number of roll angles that could result and all still fit the requirement:
SET myDir to ROTATEFROMTO( v1, v2 ).
Suffix terms from other structures
Directioncan be made from many suffix terms of other structures, as shown below:
SET myDir TO SHIP:FACING. SET myDir TO TARGET:FACING. SET myDir TO SHIP:UP.
Direction is printed, it always comes out showing its Euler Rotation, regardless of how it was created:
// Initializes a direction to prograde // plus a relative pitch of 90 SET X TO SHIP:PROGRADE + R(90,0,0). // Steer the vessel in the direction // suggested by direction X. LOCK STEERING TO X. // Create a rotation facing northeast, // 10 degrees above horizon SET Y TO HEADING(45, 10). // Steer the vessel in the direction // suggested by direction X. LOCK STEERING TO Y. // Set by a rotation in degrees SET Direction TO R(0,90,0).
Suffix Type Description
Rotation around \(x\) axis
Rotation around \(y\) axis
Rotation around \(z\) axis
This Direction’s forward vector (z axis after rotation).
Alias synonym for
This Direction’s top vector (y axis after rotation).
Alias synonym for
This Direction’s starboard vector (z axis after rotation).
Alias synonym for
The inverse of this direction.
Using the negation operator
-on a Direction does the same thing as using the :INVERSE suffix on it.
Directionobject exists primarily to enable automated steering. You can initialize a
Directionobjects represent a rotation starting from an initial point in KSP‘s coordinate system where the initial state was looking down the \(+z\) axis, with the camera “up” being the \(+y\) axis. So for example, a
Directionpointing along the \(x\) axis might be represented as
R(0,90,0), meaning the initial \(z\)-axis direction was rotated 90 degrees around the \(y\) axis.
If you are going to manipulate directions a lot, it’s important to note that the order in which the rotations occur is:
- First rotate around \(z\) axis.
- Then rotate around \(x\) axis.
- Then rotate around \(y\) axis.
What this means is that if you try to
YAWin the same tuple, like so:
R(0,45,45), you’ll end up rolling first and then yawing, which might not be what you expected. There is little that can be done to change this as it’s the native way things are represented in the underlying Unity engine.
Also, if you are going to manipulate directions a lot, it’s important to note how KSP‘s native coordinate system works.
Access: Get only
Vectorof length 1 that is in the same direction as the “look-at” of this Direction. Note that it is the same meaning as “what the Z axis of the universe would be rotated to if this rotation was applied to the basis axes of the universe”. When you LOCK STEERING to a direction, that direction’s FOREVECTOR is the vector the nose of the ship will orient to. SHIP:FACING:FOREVECTOR is the way the ship’s nose is aimed right now.
Access: Get only
Vectorof length 1 that is in the same direction as the “look-up” of this Direction. Note that it is the same meaning as “what the Y axis of the universe would be rotated to if this rotation was applied to the basis axes of the universe”. When you LOCK STEERING to a direction, that direction’s TOPVECTOR is the vector the roof of the ship will orient to. SHIP:FACING:TOPVECTOR is the way the ship’s roof is aimed right now.
Access: Get only
Vectorof length 1 that is in the same direction as the “starboard side” of this Direction. Note that it is the same meaning as “what the X axis of the universe would be rotated to if this rotation was applied to the basis axes of the universe”. When you LOCK STEERING to a direction, that direction’s STARVECTOR is the vector the right wing of the ship will orient to. SHIP:FACING:STARVECTOR is the way the ship’s right wing is aimed right now.
You can use math operations on
Direction objects as well. The next example uses a rotation of “UP” which is a system variable describing a vector directly away from the celestial body you are under the influence of:
Supported Direction Operators:
|Direction Multiplied by Direction:|
// A direction pointing along compass heading 330, by rotating NORTH by 30 degrees around UP axis: SET newDir TO ANGLEAXIS(30,SHIP:UP) * NORTH.
|Direction Multiplied by Vector:|
// What would the velocity of your ship be if it was angled 20 degrees to your left? SET Vel to ANGLEAXIS(-20,SHIP:TOPVECTOR) * SHIP:VELOCITY:ORBIT. // At this point Vel:MAG and SHIP:VELOCITY:MAG should be the same, but they don't point the same way
|Direction Added to Direction:|
It’s supposed to perform a Euler rotation of one direction by another, but it’s preferred to use
For vector operations, you may use the
:VECTOR suffix in combination with the regular vector methods:
SET dir TO SHIP:UP. SET newdir TO VCRS(SHIP:PROGRADE:VECTOR, dir:VECTOR)
Directioncan be represented with the exact same amount of information: a tuple of 3 floating point numbers. So you might wonder why it is that a
Vectorcan hold information about the magnitude of the line segment, while a
Directioncannot, given that both have the same amount of information. The answer is that a
Directiondoes contain one thing a
Vectordoes not. A
Directionknows which way is “up”, while a
Vectordoes not. If you tell kOS to
LOCK STEERINGto a
Vector, it will be able to point the nose of the vessel in the correct direction, but won’t know which way you want the roof of the craft rotated to. This works fine for axial symmetrical rockets but can be a problem for airplanes.
Therefore if you do this:
SET MyVec to V(100,200,300). SET MyDir to MyVec:DIRECTION.