Pitch, Heading and RollΒΆ

This example calculates the pitch, heading and rolls angles of the active vessel once per second.

using System;
using KRPC.Client;
using KRPC.Client.Services.SpaceCenter;
using Vector3 = System.Tuple<double, double, double>;

class AngleOfAttack
{
    static Vector3 CrossProduct (Vector3 u, Vector3 v)
    {
        return new Vector3 (
            u.Item2 * v.Item3 - u.Item3 * v.Item2,
            u.Item3 * v.Item1 - u.Item1 * v.Item3,
            u.Item1 * v.Item2 - u.Item2 * v.Item1
        );
    }

    static double DotProduct (Vector3 u, Vector3 v)
    {
        return u.Item1 * v.Item1 + u.Item2 * v.Item2 + u.Item3 * v.Item3;
    }

    static double Magnitude (Vector3 v)
    {
        return Math.Sqrt (DotProduct (v, v));
    }

    // Compute the angle between vector x and y
    static double AngleBetweenVectors (Vector3 u, Vector3 v)
    {
        double dp = DotProduct (u, v);
        if (dp == 0)
            return 0;
        double um = Magnitude (u);
        double vm = Magnitude (v);
        return Math.Acos (dp / (um * vm)) * (180f / Math.PI);
    }

    public static void Main ()
    {
        var conn = new Connection ("Angle of attack");
        var vessel = conn.SpaceCenter ().ActiveVessel;

        while (true) {
            var vesselDirection = vessel.Direction (vessel.SurfaceReferenceFrame);

            // Get the direction of the vessel in the horizon plane
            var horizonDirection = new Vector3 (
                0, vesselDirection.Item2, vesselDirection.Item3);

            // Compute the pitch - the angle between the vessels direction and
            // the direction in the horizon plane
            double pitch = AngleBetweenVectors (vesselDirection, horizonDirection);
            if (vesselDirection.Item1 < 0)
                pitch = -pitch;

            // Compute the heading - the angle between north and
            // the direction in the horizon plane
            var north = new Vector3 (0, 1, 0);
            double heading = AngleBetweenVectors (north, horizonDirection);
            if (horizonDirection.Item3 < 0)
                heading = 360 - heading;

            // Compute the roll
            // Compute the plane running through the vessels direction
            // and the upwards direction
            var up = new Vector3 (1, 0, 0);
            var planeNormal = CrossProduct (vesselDirection, up);
            // Compute the upwards direction of the vessel
            var vesselUp = conn.SpaceCenter ().TransformDirection (
                new Vector3 (0, 0, -1),
                vessel.ReferenceFrame, vessel.SurfaceReferenceFrame);
            // Compute the angle between the upwards direction of
            // the vessel and the plane normal
            double roll = AngleBetweenVectors (vesselUp, planeNormal);
            // Adjust so that the angle is between -180 and 180 and
            // rolling right is +ve and left is -ve
            if (vesselUp.Item1 > 0)
                roll *= -1;
            else if (roll < 0)
                roll += 180;
            else
                roll -= 180;

            Console.WriteLine ("pitch = {0:F1}, heading = {1:F1}, roll = {2:F1}",
                               pitch, heading, roll);

            System.Threading.Thread.Sleep (1000);
        }
    }
}
#include <iostream>
#include <iomanip>
#include <tuple>
#include <thread>
#include <chrono>
#include <cmath>
#include <krpc.hpp>
#include <krpc/services/space_center.hpp>

static const double pi = 3.1415926535897;
typedef std::tuple<double, double, double> vector3;

vector3 cross_product(const vector3& u, const vector3& v) {
  return std::make_tuple(
    std::get<1>(u)*std::get<2>(v) - std::get<2>(u)*std::get<1>(v),
    std::get<2>(u)*std::get<0>(v) - std::get<0>(u)*std::get<2>(v),
    std::get<0>(u)*std::get<1>(v) - std::get<1>(u)*std::get<0>(v));
}

double dot_product(const vector3& u, const vector3& v) {
  return
    std::get<0>(u)*std::get<0>(v) +
    std::get<1>(u)*std::get<1>(v) +
    std::get<2>(u)*std::get<2>(v);
}

double magnitude(const vector3& v) {
  return std::sqrt(dot_product(v, v));
}

// Compute the angle between vector u and v
double angle_between_vectors(const vector3& u, const vector3& v) {
  double dp = dot_product(u, v);
  if (dp == 0)
    return 0;
  double um = magnitude(u);
  double vm = magnitude(v);
  return std::acos(dp / (um*vm)) * (180.0 / pi);
}

int main() {
  krpc::Client conn = krpc::connect("Pitch/Heading/Roll");
  krpc::services::SpaceCenter space_center(&conn);
  auto vessel = space_center.active_vessel();

  while (true) {
    vector3 vessel_direction = vessel.direction(vessel.surface_reference_frame());

    // Get the direction of the vessel in the horizon plane
    vector3 horizon_direction {
      0, std::get<1>(vessel_direction), std::get<2>(vessel_direction)
    };

    // Compute the pitch - the angle between the vessels direction
    // and the direction in the horizon plane
    double pitch = angle_between_vectors(vessel_direction, horizon_direction);
    if (std::get<0>(vessel_direction) < 0)
      pitch = -pitch;

    // Compute the heading - the angle between north
    // and the direction in the horizon plane
    vector3 north {0, 1, 0};
    double heading = angle_between_vectors(north, horizon_direction);
    if (std::get<2>(horizon_direction) < 0)
      heading = 360 - heading;

    // Compute the roll
    // Compute the plane running through the vessels direction
    // and the upwards direction
    vector3 up {1, 0, 0};
    vector3 plane_normal = cross_product(vessel_direction, up);
    // Compute the upwards direction of the vessel
    vector3 vessel_up = space_center.transform_direction(
      std::make_tuple(0, 0, -1),
      vessel.reference_frame(),
      vessel.surface_reference_frame());
    // Compute the angle between the upwards direction of
    // the vessel and the plane normal
    double roll = angle_between_vectors(vessel_up, plane_normal);
    // Adjust so that the angle is between -180 and 180 and
    // rolling right is +ve and left is -ve
    if (std::get<0>(vessel_up) > 0)
        roll *= -1;
    else if (roll < 0)
        roll += 180;
    else
        roll -= 180;

    std::cout << std::fixed << std::setprecision(1);
    std::cout << "pitch = " << pitch << ", "
              << "heading = " << heading << ", "
              << "roll = " << roll << std::endl;

    std::this_thread::sleep_for(std::chrono::seconds(1));
  }
}
#include <math.h>
#include <unistd.h>
#include <krpc_cnano.h>
#include <krpc_cnano/services/space_center.h>

static double pi = 3.1415926535897;
typedef krpc_tuple_double_double_double_t vector3;

vector3 cross_product(vector3 u, vector3 v) {
  vector3 result = {
    u.e1*v.e2 - u.e2*v.e1,
    u.e2*v.e0 - u.e0*v.e2,
    u.e0*v.e1 - u.e1*v.e0
  };
  return result;
}

double dot_product(vector3 u, vector3 v) {
  return u.e0*v.e0 + u.e1*v.e1 + u.e2*v.e2;
}

double magnitude(vector3 v) {
  return sqrt(dot_product(v, v));
}

// Compute the angle between vector u and v
double angle_between_vectors(vector3 u, vector3 v) {
  double dp = dot_product(u, v);
  if (dp == 0)
    return 0;
  double um = magnitude(u);
  double vm = magnitude(v);
  return acos(dp / (um*vm)) * (180.0 / pi);
}

int main() {
  krpc_connection_t conn;
  krpc_open(&conn, "COM0");
  krpc_connect(conn, "");

  krpc_SpaceCenter_Vessel_t vessel;
  krpc_SpaceCenter_ActiveVessel(conn, &vessel);
  krpc_SpaceCenter_ReferenceFrame_t srf_ref;
  krpc_SpaceCenter_Vessel_SurfaceReferenceFrame(conn, &srf_ref, vessel);
  krpc_SpaceCenter_ReferenceFrame_t vessel_ref;
  krpc_SpaceCenter_Vessel_ReferenceFrame(conn, &vessel_ref, vessel);

  while (true) {
    vector3 vessel_direction;
    krpc_SpaceCenter_Vessel_Direction(conn, &vessel_direction, vessel, srf_ref);

    // Get the direction of the vessel in the horizon plane
    vector3 horizon_direction = {
      0, vessel_direction.e1, vessel_direction.e2
    };

    // Compute the pitch - the angle between the vessels direction
    // and the direction in the horizon plane
    double pitch = angle_between_vectors(vessel_direction, horizon_direction);
    if (vessel_direction.e0 < 0)
      pitch = -pitch;

    // Compute the heading - the angle between north
    // and the direction in the horizon plane
    vector3 north = {0, 1, 0};
    double heading = angle_between_vectors(north, horizon_direction);
    if (horizon_direction.e2 < 0)
      heading = 360 - heading;

    // Compute the roll
    // Compute the plane running through the vessels direction
    // and the upwards direction
    vector3 up = {1, 0, 0};
    vector3 plane_normal = cross_product(vessel_direction, up);
    // Compute the upwards direction of the vessel
    vector3 vessel_up;
    vector3 tmp = { 0, 0, -1 };
    krpc_SpaceCenter_TransformDirection(conn, &vessel_up, &tmp, vessel_ref, srf_ref);
    // Compute the angle between the upwards direction of
    // the vessel and the plane normal
    double roll = angle_between_vectors(vessel_up, plane_normal);
    // Adjust so that the angle is between -180 and 180 and
    // rolling right is +ve and left is -ve
    if (vessel_up.e0 > 0)
        roll *= -1;
    else if (roll < 0)
        roll += 180;
    else
        roll -= 180;

    printf("pitch = %.1f, heading = %.1f, roll = %.1f\n", pitch, heading, roll);
    sleep(1);
  }
}
import krpc.client.Connection;
import krpc.client.RPCException;
import krpc.client.services.SpaceCenter;

import org.javatuples.Triplet;

import java.io.IOException;
import java.lang.Math;

public class PitchHeadingRoll {

    static Triplet<Double,Double,Double> crossProduct(
        Triplet<Double,Double,Double> u, Triplet<Double,Double,Double> v) {
        return new Triplet<Double,Double,Double>(
            u.getValue1() * v.getValue2() - u.getValue2() * v.getValue1(),
            u.getValue2() * v.getValue0() - u.getValue0() * v.getValue2(),
            u.getValue0() * v.getValue1() - u.getValue1() * v.getValue0()
        );
    }

    static double dotProduct(Triplet<Double,Double,Double> u,
                             Triplet<Double,Double,Double> v) {
        return u.getValue0() * v.getValue0() +
               u.getValue1() * v.getValue1() +
               u.getValue2() * v.getValue2();
    }

    static double magnitude(Triplet<Double,Double,Double> v) {
        return Math.sqrt(dotProduct(v, v));
    }

    // Compute the angle between vector x and y
    static double angleBetweenVectors(Triplet<Double,Double,Double> u,
                                      Triplet<Double,Double,Double> v) {
        double dp = dotProduct(u, v);
        if (dp == 0) {
            return 0;
        }
        double um = magnitude(u);
        double vm = magnitude(v);
        return Math.acos(dp / (um * vm)) * (180f / Math.PI);
    }

    public static void main(String[] args)
        throws IOException, RPCException, InterruptedException {
        Connection connection = Connection.newInstance();
        SpaceCenter spaceCenter = SpaceCenter.newInstance(connection);
        SpaceCenter.Vessel vessel = spaceCenter.getActiveVessel();

        while (true) {
            Triplet<Double,Double,Double> vesselDirection =
                vessel.direction(vessel.getSurfaceReferenceFrame());

            // Get the direction of the vessel in the horizon plane
            Triplet<Double,Double,Double> horizonDirection =
                new Triplet<Double,Double,Double>(
                    0.0, vesselDirection.getValue1(), vesselDirection.getValue2());

            // Compute the pitch - the angle between the vessels direction
            // and the direction in the horizon plane
            double pitch = angleBetweenVectors(vesselDirection, horizonDirection);
            if (vesselDirection.getValue0() < 0) {
                pitch = -pitch;
            }

            // Compute the heading - the angle between north
            // and the direction in the horizon plane
            Triplet<Double,Double,Double> north =
                new Triplet<Double,Double,Double>(0.0,1.0,0.0);
            double heading = angleBetweenVectors(north, horizonDirection);
            if (horizonDirection.getValue2() < 0) {
                heading = 360 - heading;
            }

            // Compute the roll
            // Compute the plane running through the vessels direction
            // and the upwards direction
            Triplet<Double,Double,Double> up =
                new Triplet<Double,Double,Double>(1.0,0.0,0.0);
            Triplet<Double,Double,Double> planeNormal =
                crossProduct(vesselDirection, up);
            // Compute the upwards direction of the vessel
            Triplet<Double,Double,Double> vesselUp = spaceCenter.transformDirection(
                new Triplet<Double,Double,Double>(0.0,0.0,-1.0),
                vessel.getReferenceFrame(), vessel.getSurfaceReferenceFrame());
            // Compute the angle between the upwards direction
            // of the vessel and the plane normal
            double roll = angleBetweenVectors(vesselUp, planeNormal);
            // Adjust so that the angle is between -180 and 180 and
            // rolling right is +ve and left is -ve
            if (vesselUp.getValue0() > 0) {
                roll *= -1;
            } else if (roll < 0) {
                roll += 180;
            } else {
                roll -= 180;
            }

            System.out.printf("pitch = %.1f, heading = %.1f, roll = %.1f\n",
                              pitch, heading, roll);
            Thread.sleep(1000);
        }
    }
}
local krpc = require 'krpc'
local platform = require 'krpc.platform'
local math = require 'math'
local List = require 'pl.List'
local conn = krpc.connect('Pitch/Heading/Roll')
local vessel = conn.space_center.active_vessel

function cross_product(u, v)
    return List{u[3]*v[3] - u[3]*v[2],
                u[1]*v[1] - u[1]*v[3],
                u[2]*v[2] - u[2]*v[1]}
end

function dot_product(u, v)
    return u[1]*v[1] + u[2]*v[2] + u[3]*v[3]
end

function magnitude(v)
    return math.sqrt(dot_product(v, v))
end

function angle_between_vectors(u, v)
    -- Compute the angle between vector u and v
    dp = dot_product(u, v)
    if dp == 0 then
        return 0
    end
    um = magnitude(u)
    vm = magnitude(v)
    return math.acos(dp / (um*vm)) * (180. / math.pi)
end

while true do

    local vessel_direction = vessel:direction(vessel.surface_reference_frame)

    -- Get the direction of the vessel in the horizon plane
    local horizon_direction = List{0, vessel_direction[2], vessel_direction[3]}

    -- Compute the pitch - the angle between the vessels direction and
    -- the direction in the horizon plane
    local pitch = angle_between_vectors(vessel_direction, horizon_direction)
    if vessel_direction[1] < 0 then
        pitch = -pitch
    end

    -- Compute the heading - the angle between north and
    -- the direction in the horizon plane
    local north = List{0, 1, 0}
    local heading = angle_between_vectors(north, horizon_direction)
    if horizon_direction[3] < 0 then
        heading = 360 - heading
    end

    -- Compute the roll
    -- Compute the plane running through the vessels direction
    -- and the upwards direction
    local up = List{1, 0, 0}
    local plane_normal = cross_product(vessel_direction, up)
    -- Compute the upwards direction of the vessel
    local vessel_up = conn.space_center.transform_direction(
        List{0, 0, -1}, vessel.reference_frame, vessel.surface_reference_frame)
    -- Compute the angle between the upwards direction of
    -- the vessel and the plane normal
    local roll = angle_between_vectors(vessel_up, plane_normal)
    -- Adjust so that the angle is between -180 and 180 and
    -- rolling right is +ve and left is -ve
    if vessel_up[1] > 0 then
        roll = -roll
    elseif roll < 0 then
        roll = roll + 180
    else
        roll = roll - 180
    end

    print(string.format('pitch = %1.f, heading = %.1f, roll = %.1f',
                        pitch, heading, roll))

    platform.sleep(1)

end
import math
import time
import krpc
conn = krpc.connect(name='Pitch/Heading/Roll')
vessel = conn.space_center.active_vessel


def cross_product(u, v):
    return (u[1]*v[2] - u[2]*v[1],
            u[2]*v[0] - u[0]*v[2],
            u[0]*v[1] - u[1]*v[0])


def dot_product(u, v):
    return u[0]*v[0] + u[1]*v[1] + u[2]*v[2]


def magnitude(v):
    return math.sqrt(dot_product(v, v))


def angle_between_vectors(u, v):
    """ Compute the angle between vector u and v """
    dp = dot_product(u, v)
    if dp == 0:
        return 0
    um = magnitude(u)
    vm = magnitude(v)
    return math.acos(dp / (um*vm)) * (180. / math.pi)


while True:

    vessel_direction = vessel.direction(vessel.surface_reference_frame)

    # Get the direction of the vessel in the horizon plane
    horizon_direction = (0, vessel_direction[1], vessel_direction[2])

    # Compute the pitch - the angle between the vessels direction and
    # the direction in the horizon plane
    pitch = angle_between_vectors(vessel_direction, horizon_direction)
    if vessel_direction[0] < 0:
        pitch = -pitch

    # Compute the heading - the angle between north and
    # the direction in the horizon plane
    north = (0, 1, 0)
    heading = angle_between_vectors(north, horizon_direction)
    if horizon_direction[2] < 0:
        heading = 360 - heading

    # Compute the roll
    # Compute the plane running through the vessels direction
    # and the upwards direction
    up = (1, 0, 0)
    plane_normal = cross_product(vessel_direction, up)
    # Compute the upwards direction of the vessel
    vessel_up = conn.space_center.transform_direction(
        (0, 0, -1), vessel.reference_frame, vessel.surface_reference_frame)
    # Compute the angle between the upwards direction of
    # the vessel and the plane normal
    roll = angle_between_vectors(vessel_up, plane_normal)
    # Adjust so that the angle is between -180 and 180 and
    # rolling right is +ve and left is -ve
    if vessel_up[0] > 0:
        roll *= -1
    elif roll < 0:
        roll += 180
    else:
        roll -= 180

    print('pitch = % 5.1f, heading = % 5.1f, roll = % 5.1f' %
          (pitch, heading, roll))

    time.sleep(1)