예제 #1
0
def add_earth_sphere(center=None):
    """Add a sphere the radius of the Earth to the current figure.

    :param [float] center: Coordinates to locate the center of the Earth in the plot
    :return:
    """
    phi = np.linspace(0, 2 * np.pi, 100)
    theta = np.linspace(0, np.pi, 100)

    if center is None:
        center = vt.Vector([0, 0, 0])

    x = constant.RADIUS_OF_EARTH * np.outer(np.cos(phi),
                                            np.sin(theta)) + center[0]
    y = constant.RADIUS_OF_EARTH * np.outer(np.sin(phi),
                                            np.sin(theta)) + center[1]
    z = constant.RADIUS_OF_EARTH * np.outer(np.ones(np.size(phi)),
                                            np.cos(theta)) + center[2]

    # earth_image_file_path = os.path.join(os.environ.get('SATSIMDIR'), 'basics', 'earth_map.png')
    # fn = mpl_cbook.get_sample_data(earth_image_file_path, asfileobj=False)
    # img = mpl_png.read_png(fn).transpose(1, 0, 2)

    # ax.plot_surface(x, y, z, color='r', shade=True)# rstride=1, cstride=1, facecolors=img)
    mlab.mesh(x, y, z, color=(0, 1, 0))
예제 #2
0
    def __init__(self, time):
        """

        :param datetime.datetime time: Initial time to start the Sun model
        :return: None
        """
        self.time = time
        self.direction = vt.Vector([0, 0, 0])
        self.distance = 0.0
        self.update(time)  # Update direction, distance to their correct values
예제 #3
0
def oe2rv(a, e, i, om, w, v, mu=constant.MU):
    """

    :param float a: Semi-major axis
    :param float e: Eccentricity
    :param float i: Inclination
    :param float om: Longitude of ascending node
    :param float w: Argument of periapsis
    :param float v: True anomaly
    :param float mu: Earth gravitation parameter. Defaults to Earth in km^3/s^2
    :rtype: (vt.Vector, vt.Vector)
    :return: position , velocity vectors in ECI
    """

    e2 = e**2
    p = a * (1.0 - e2)
    com = math.cos(om)
    som = math.sin(om)
    cin = math.cos(i)
    sin = math.sin(i)
    cwv = math.cos(w + v)
    swv = math.sin(w + v)
    snu = math.sin(v)

    # Comput the radius
    r = p / (1 + e * math.cos(v))

    # Compute angular momentum
    h = math.sqrt(mu * p)

    # Compute position vector
    r_eci = r * vt.Vector(
        [com * cwv - som * swv * cin, som * cwv + com * swv * cin, sin * swv])

    # Compute the velocity vector
    temp1 = r_eci * (h * e / (r * p)) * snu
    temp2 = (h / r) * vt.Vector([
        -com * swv - som * cwv * cin, -som * swv + com * cwv * cin, +sin * cwv
    ])
    v_eci = temp1 + temp2

    return r_eci, v_eci
예제 #4
0
def sph_to_xyz(r, theta, phi):
    """ Converts from spherical to cartesian coordinates.

    :param float r: the radial component
    :param float theta: the polar angle component, measured from the +Z axis
    :param float phi: the azimuthal angle component, measured form the +X axis
    :rtype: vt.Vector
    :return: xyz vector
    """

    return vt.Vector(r * math.cos(phi) * math.sin(theta),
                     r * math.sin(phi) * math.sin(theta), r * math.cos(theta))
예제 #5
0
    def update(self, time):
        """Calculates the direction and distance to the moon from the Earth

        :param datetime.datetime time: Update the moon model to the time given.
        :rtype: vt.Vector, float
        :return: Unit moon vector, distance from Earth to Moon
        """

        delta_J2000 = self.time - constant.J2000_DATE
        n_days_J2000 = delta_J2000.days + delta_J2000.seconds / 86400

        mean_lon_moon = 218.316 + 13.176396 * n_days_J2000
        mean_lon_moon %= 360.0
        mean_lon_moon *= constant.DEG_TO_RAD

        mean_anomaly_moon = 134.963 + 13.064993 * n_days_J2000
        mean_anomaly_moon %= 360.0
        mean_anomaly_moon *= constant.DEG_TO_RAD

        mean_dist_moon = 93.272 + 13.229350 * n_days_J2000
        mean_dist_moon %= 360.0
        mean_dist_moon *= constant.DEG_TO_RAD

        ecliptic_lon_moon = (mean_lon_moon / constant.DEG_TO_RAD +
                             6.289 * math.sin(mean_anomaly_moon))
        ecliptic_lon_moon *= constant.DEG_TO_RAD

        ecliptic_lat_moon = 5.128 * math.sin(mean_dist_moon)
        ecliptic_lat_moon *= constant.DEG_TO_RAD

        self.distance = (385001.0 - 20905.0 * math.cos(mean_anomaly_moon))

        obliquity_ecliptic = 23.439 - 0.0000004 * n_days_J2000
        obliquity_ecliptic *= constant.DEG_TO_RAD

        x_ec = math.cos(ecliptic_lat_moon) * math.cos(ecliptic_lon_moon)
        y_ec = math.cos(ecliptic_lat_moon) * math.sin(ecliptic_lon_moon)
        z_ec = math.sin(ecliptic_lat_moon)
        rect_ec = vt.Vector([[x_ec], [y_ec], [z_ec]])

        Q_eq_ec = vt.Matrix(
            [[1, 0, 0],
             [0,
              math.cos(obliquity_ecliptic), -math.sin(obliquity_ecliptic)],
             [0, math.sin(obliquity_ecliptic),
              math.cos(obliquity_ecliptic)]])

        self.direction = Q_eq_ec * rect_ec
        self.time = time
예제 #6
0
    def calculate_force(cls, r_ecef):
        """

        :param dt.datetime t: Time at which the force takes place
        :param vt.Vector r_eci: Position in ECI
        :rtype: vt.Vector
        :return: Force vector in ECI
        """

        r, theta, phi = conv.xyz_to_sph(r_ecef)

        f_r = cls._calculate_radial_force(r, phi, theta)
        f_t = cls._calculate_theta_force(r, phi, theta)
        f_p = cls._calculate_phi_force(r, phi, theta)

        f_ecef = conv.sph_to_xyz_dcm(theta, phi) * vt.Vector([f_r, f_t, f_p])
        return f_ecef
예제 #7
0
    def import_sat(cls, filename):
        single_items = ["name", "shape", "dry_mass", "fuel_mass", "drag_coeff", "rad_coeff"]
        vector_items = ["length", "cog", "cop", "drag_area", "solar_area", "rad_area"]
        matrix_items = ["moi"]
        params = {}

        try:
            tree = et.parse(filename)
        except IOError:
            print("Unable to open satellite file.")
            return
        except et.ParseError:
            print("Invalid XML file.")
            return
        root = tree.getroot()

        # Single items are defined in text
        for item in single_items:
            value = root.find(item).text
            try:
                params[item] = float(value)
            except ValueError:
                params[item] = value

        # Vector items are defined in attributes x, y, and z
        attributes = ['x', 'y', 'z']
        for item in vector_items:
            node = root.find(item)
            value = [float(node.attrib.get(a, 0)) for a in attributes]
            params[item] = vector_types.Vector(value)

        # Matrix items are defined in attributes xx, xy, xz, yx, yy, yz, zx, zy, zz
        attributes = ['xx', 'xy', 'xz',
                      'yx', 'yy', 'yz',
                      'zx', 'zy', 'zz']
        for item in matrix_items:
            node = root.find(item)
            value = [float(node.attrib.get(a, 0)) for a in attributes]
            params[item] = vector_types.Matrix(value)

        return SatModel(params)
예제 #8
0
    def make_quat(ax, ang):
        """

        :param vt.Vector axis: Axis of the rotation.
        :param float angle: Angle of rotation in radians.
        :rtype: Quaternion
        :return: quaternion representing the rotation
        """

        # Get copy of axis
        axis = vt.Vector(ax.x, ax.y, ax.z)

        # Make unit vector
        axis /= axis.norm()

        sangle = math.sin(ang / 2.0)
        cangle = math.cos(ang / 2.0)

        axis *= sangle

        return Quaternion([cangle, axis.x, axis.y, axis.z])
예제 #9
0
    def update(self, time):
        """Calculates the direction and distance to the sun from the Earth

        :param dt.datetime time: Update the sun model to the time given.
        :rtype: vt.Vector, float
        :return: Unit sun vector, distance from the Earth to the Sun
        """

        delta_J2000 = self.time - constant.J2000_DATE
        n_days_J2000 = delta_J2000.days + delta_J2000.seconds / 86400

        mean_lon_sun = 280.460 + 0.9856474 * n_days_J2000
        mean_lon_sun %= 360.0
        mean_lon_sun *= constant.DEG_TO_RAD

        mean_anomaly_sun = 357.528 + 0.9856003 * n_days_J2000
        mean_anomaly_sun %= 360.0
        mean_anomaly_sun *= constant.DEG_TO_RAD

        ecliptic_lon_sun = (mean_lon_sun / constant.DEG_TO_RAD +
                            1.915 * math.sin(mean_anomaly_sun) +
                            0.020 * math.sin(2.0 * mean_anomaly_sun))
        ecliptic_lon_sun *= constant.DEG_TO_RAD

        dist_earth_to_sun = (1.00014 - 0.01671 * math.cos(mean_anomaly_sun) -
                             0.00014 * math.cos(2.0 * mean_anomaly_sun))
        dist_earth_to_sun *= constant.AU_TO_KM

        obliquity_ecliptic = 23.439 - 0.0000004 * n_days_J2000
        obliquity_ecliptic *= constant.DEG_TO_RAD

        x_J2000_sun = math.cos(ecliptic_lon_sun)
        y_J2000_sun = math.cos(obliquity_ecliptic) * math.sin(ecliptic_lon_sun)
        z_J2000_sun = math.sin(obliquity_ecliptic) * math.sin(ecliptic_lon_sun)

        self.direction = vt.Vector([x_J2000_sun, y_J2000_sun, z_J2000_sun])
        self.distance = dist_earth_to_sun
        self.time = time
예제 #10
0
    def __orbit_force_model(t, y, time_init):
        x, y, z, v_x, v_y, v_z = y
        x_dot, y_dot, z_dot = v_x, v_y, v_z
        v_dot = SatModel.force_model.force(vector_types.Vector(x, y, z), time_init + dt.timedelta(seconds=t))

        return [x_dot, y_dot, z_dot, v_dot.x, v_dot.y, v_dot.z]
예제 #11
0
        quat[1] = x/angle * sin(angle/2.0)
        quat[2] = y/angle * sin(angle/2.0)
        quat[3] = z/angle * sin(angle/2.0)
        
        self.q *= space_types.Quaternion(quat)
        
    def get_att_vec(self):
        return self.q.dcm() * self.att_init
    
    def __str__(self):
        return str(self.get_att_vec())


if __name__ == '__main__':
    time_init       = dt.datetime.now()
    mass_prop       = {'mass': 1500.0, 'cog': vector_types.Vector([0.5, 0.5, 1.5]), 'moi': vector_types.Matrix(1375, 0, 0, 0, 1375, 0, 0, 0, 275)}
    pos_init        = vector_types.Vector([7141.9897400, 0.000, 0.000])
    vel_init        = vector_types.Vector([0.0, 270.96981048, 4306.941804035])
    att_init        = vector_types.Vector([0.0, 0.0, 1.0])
    ang_vel_init    = vector_types.Vector([0.0, 0.06, 0.0])
    
    satmodel = SatModel(time_init, mass_prop, pos_init, vel_init, att_init, ang_vel_init)
    x_plt, y_plt, z_plt = satmodel.att.get_att_vec()
    x_plt = [x_plt]
    y_plt = [y_plt]
    z_plt = [z_plt]

    x_pos, y_pos, z_pos = pos_init.x, pos_init.y, pos_init.z
    x_pos = list(x_pos)
    y_pos = list(y_pos)
    z_pos = list(z_pos)
예제 #12
0
import datetime as dt
import basics.conversions as conv
import math
import basics.plotting as plotting
from mpl_toolkits.mplot3d import Axes3D
import mayavi.mlab as mlab
import basics.rkf6 as rkf6
import basics.vector_types as vt
import scipy.integrate as spyi
import numpy as np
import time

# Setup the satellite model
time_init = dt.datetime.now()
mass_prop = {'mass': 1500.0,
             'cog': vt.Vector([0.5, 0.5, 1.5]),
             'moi': vt.Matrix(1375, 0, 0, 0, 1375, 0, 0, 0, 275)}
p_init = vt.Vector([7155.27304548, 0.0, 0.0])
v_init = vt.Vector([0.0, 0.46957258, 7.45043721])
att_init = vt.Vector([0.0, 0.0, 1.0])
ang_vel_init = vt.Vector([0.0, 0.06, 0.0])
satellite = SatModel.SatModel(time_init, mass_prop, p_init, v_init, att_init, ang_vel_init)

# Make universe
universe = Universe.Universe(satellite, time_init)

# Make plotting variables
x_sat = np.array([p_init.x])
y_sat = np.array([p_init.y])
z_sat = np.array([p_init.z])
예제 #13
0
def rv_to_oe(r_eci, v_eci, mu=constant.MU):
    """Convert ECI position/velocity state vectors to orbital elements

    :param vt.Vector r_eci:
    :param vt.Vector v_eci:
    :param float mu:
    :rtype: (float, float, float, float, float, float)
    :return: a, e, i, om, w, v
    """

    # Calculate some initial constants
    r2 = r_eci.norm2()
    r = math.sqrt(r2)
    v2 = v_eci.norm2()
    v = math.sqrt(v2)
    rdotv = r_eci * v_eci

    # Calculate angular momentum
    h_eci = r_eci.cross(v_eci)
    h2 = h_eci.norm2()
    h = math.sqrt(h2)

    # Calculate node vector
    n_eci = vt.Vector([0, 0, 1]).cross(h_eci)
    n = n_eci.norm()
    n_unit = n_eci / n

    # Calculate eccentricity vector
    e_eci = ((v2 - mu / r) * r_eci - rdotv * v_eci) / mu
    e2 = e_eci.norm2()
    e = math.sqrt(e2)
    e_unit = e_eci / e

    # Calculate mechanical energy
    E = v2 / 2 - mu / r

    # Calculate semi-major axis and latus rectum
    if e != 1.0:
        a = -mu / (2 * E)
        p = a * (1 - e2)
    else:
        p = h2 / mu
        a = float('inf')

    # Calculate inclination
    i = math.acos(h_eci.z / h)

    # Calculate the longitude of ascending node
    om = math.acos(n_unit.x)

    # Calculate the argument of periapsis
    w = math.acos(n_unit * e_unit)
    if e_unit < 0.0:
        w = 360.0 - w

    # Calculate the true anomaly
    v = math.acos((e_unit * r_eci) / r)
    if rdotv < 0.0:
        v = 360.0 - v

    return a, e, i, om, w, v