Task: Orbital elements




Go: package main

import (
    "fmt"
    "math"
)

type vector struct{ x, y, z float64 }

func (v vector) add(w vector) vector {
    return vector{v.x + w.x, v.y + w.y, v.z + w.z}
}

func (v vector) mul(m float64) vector {
    return vector{v.x * m, v.y * m, v.z * m}
}

func (v vector) div(d float64) vector {
    return v.mul(1.0 / d)
}

func (v vector) abs() float64 {
    return math.Sqrt(v.x*v.x + v.y*v.y + v.z*v.z)
}

func (v vector) String() string {
    return fmt.Sprintf("(%g, %g, %g)", v.x, v.y, v.z)
}

func orbitalStateVectors(
    semimajorAxis, eccentricity, inclination, longitudeOfAscendingNode,
    argumentOfPeriapsis, trueAnomaly float64) (position vector, speed vector) {

    i := vector{1, 0, 0}
    j := vector{0, 1, 0}
    k := vector{0, 0, 1}

    mulAdd := func(v1, v2 vector, x1, x2 float64) vector {
        return v1.mul(x1).add(v2.mul(x2))
    }

    rotate := func(i, j vector, alpha float64) (vector, vector) {
        return mulAdd(i, j, math.Cos(alpha), math.Sin(alpha)),
            mulAdd(i, j, -math.Sin(alpha), math.Cos(alpha))
    }

    i, j = rotate(i, j, longitudeOfAscendingNode)
    j, _ = rotate(j, k, inclination)
    i, j = rotate(i, j, argumentOfPeriapsis)

    l := 2.0
    if eccentricity != 1.0 {
        l = 1.0 - eccentricity*eccentricity
    }
    l *= semimajorAxis
    c := math.Cos(trueAnomaly)
    s := math.Sin(trueAnomaly)
    r := l / (1.0 + eccentricity*c)
    rprime := s * r * r / l
    position = mulAdd(i, j, c, s).mul(r)
    speed = mulAdd(i, j, rprime*c-r*s, rprime*s+r*c)
    speed = speed.div(speed.abs())
    speed = speed.mul(math.Sqrt(2.0/r - 1.0/semimajorAxis))
    return
}

func main() {
    long := 355.0 / (113.0 * 6.0)
    position, speed := orbitalStateVectors(1.0, 0.1, 0.0, long, 0.0, 0.0)
    fmt.Println("Position :", position)
    fmt.Println("Speed    :", speed)
}




Python: import math

class Vector:
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z

    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y, self.z + other.z)

    def __mul__(self, other):
        return Vector(self.x * other, self.y * other, self.z * other)

    def __div__(self, other):
        return Vector(self.x / other, self.y / other, self.z / other)

    def __str__(self):
        return '({x}, {y}, {z})'.format(x=self.x, y=self.y, z=self.z)

    def abs(self):
        return math.sqrt(self.x*self.x + self.y*self.y + self.z*self.z)

def mulAdd(v1, x1, v2, x2):
    return v1 * x1 + v2 * x2

def rotate(i, j, alpha):
    return [mulAdd(i,math.cos(alpha),j,math.sin(alpha)), mulAdd(i,-math.sin(alpha),j,math.cos(alpha))]

def orbitalStateVectors(semimajorAxis, eccentricity, inclination, longitudeOfAscendingNode, argumentOfPeriapsis, trueAnomaly):
    i = Vector(1, 0, 0)
    j = Vector(0, 1, 0)
    k = Vector(0, 0, 1)

    p = rotate(i, j, longitudeOfAscendingNode)
    i = p[0]
    j = p[1]
    p = rotate(j, k, inclination)
    j = p[0]
    p  =rotate(i, j, argumentOfPeriapsis)
    i = p[0]
    j = p[1]

    l = 2.0 if (eccentricity == 1.0) else 1.0 - eccentricity * eccentricity
    l *= semimajorAxis
    c = math.cos(trueAnomaly)
    s = math.sin(trueAnomaly)
    r = 1 / (1.0 + eccentricity * c)
    rprime = s * r * r / l
    position = mulAdd(i, c, j, s) * r
    speed = mulAdd(i, rprime * c - r * s, j, rprime * s + r * c)
    speed = speed / speed.abs()
    speed = speed * math.sqrt(2.0 / r - 1.0 / semimajorAxis)

    return [position, speed]

ps = orbitalStateVectors(1.0, 0.1, 0.0, 355.0 / (113.0 * 6.0), 0.0, 0.0)
print "Position :", ps[0]
print "Speed    :", ps[1]