def find_orbit_plane(satpos1_eci_1, satpos2_eci):

    n = pylab.cross(satpos1_eci_1, satpos2_eci)

    n_norm = pylab.linalg.norm(n)

    return n_norm
def los_from_tanpoint_spherical(satpos1_eci_1, satpos2_eci):

    n = pylab.cross(satpos1_eci_1, satpos2_eci)

    n_norm = pylab.linalg.norm(n)

    return n_norm
Beispiel #3
0
 def __init__(self, LatConst):
     self.a0 = array([0.5 * LatConst, 0.5 * LatConst, 0])
     self.a1 = array([0.5 * LatConst, 0, 0.5 * LatConst])
     self.a2 = array([0, 0.5 * LatConst, 0.5 * LatConst])
     Vc = dot(cross(self.a0, self.a1), self.a2)  # Volume
     self.Volume = abs(Vc)
     print "Volume is", self.Volume
     self.b0 = (2 * pi / Vc) * cross(self.a1, self.a2)
     self.b1 = (2 * pi / Vc) * cross(self.a2, self.a0)
     self.b2 = (2 * pi / Vc) * cross(self.a0, self.a1)
     # Special points in Brillouin zone
     brs = 2 * pi / LatConst
     self.GPoint = [0, 0, 0]
     self.LPoint = array([0.5, 0.5, 0.5]) * brs
     self.KPoint = array([0.75, 0.75, 0]) * brs
     self.XPoint = array([1.0, 0.0, 0]) * brs
     self.WPoint = array([1.0, 0.5, 0]) * brs
Beispiel #4
0
  def update_common_quantities(self):
    self.particles_per_wall = self.resolution**2
    self.mass_of_particles = self.simulation.get_massofgas()
    self.mass_of_walls = self.particles_per_wall*self.mass_of_particles
    self.mass_loss_rate = self.density*self.velocity*self.width**2
    self.number_of_particles = self.resolution**2
    self.dx = self.width/self.resolution
    self.time_between_walls = self.mass_of_walls/self.mass_loss_rate
    self.normal /= norm(self.normal)
    self.center = array(self.center)
    self.specific_energy_to_temperature_ratio = R/(self.mu*(self.gamma-1.))
    self.hfact = self.simulation.get_hfact()
    for v in [[1.,0.,0.], [0.,1.,0.], [0.,0.,1.]]:
      u = cross(v,self.normal)
      if norm(u)>0.:
	break
    self.u = u/norm(u)
    v = cross(u,self.normal)
    self.v = v/norm(v)
Beispiel #5
0
    def _XYZOrient(self):
        """
        Calculates orientation of a vector and the X, Y and Z axes.
        0 = 0 deg, 1 = 90 deg
        """

        Axial = npy.array(self.Axis)
        #
        # Normalize the axis vector
        #
        Axial = Axial/sqrt(sum(Axial**2))

        #
        # Create some unit vectors to get the radial vector
        #
        x = npy.array([1,0,0])
        y = npy.array([0,1,0])
        z = npy.array([0,0,1])

        #
        # Cross the vector with an appropriate vector that is not parallel
        # to the axis
        #
        if abs(pyl.dot(Axial,z)) != 1:
            Radial1 = pyl.cross(z,Axial)
        elif abs(pyl.dot(Axial,x)) != 1:
            Radial1 = pyl.cross(x,Axial)
        elif abs(pyl.dot(Axial,y)) != 1:
            Radial1 = pyl.cross(y,Axial)
        

        Radial1 = Radial1/sqrt(sum(Radial1**2))

        #
        # Get a second radial orientation to draw in
        #
        Radial2 = pyl.cross(Axial,Radial1)
        Radial2 = Radial2/sqrt(sum(Radial2**2))

        #
        # Return the vectors
        #
        return Axial, Radial1, Radial2
Beispiel #6
0
def ComputeZMPConfig(robot, q, qd, qdd):
    n = len(robot.GetLinks())
    g = robot.GetEnv().GetPhysicsEngine().GetGravity()
    with robot:
        robot.SetDOFValues(Fill(robot, q))
        robot.SetDOFVelocities(Fill(robot, qd))
        com_pos = array([k.GetGlobalCOM() for k in robot.GetLinks()])
        vel = robot.GetLinkVelocities()
        acc = robot.GetLinkAccelerations(Fill(robot, qdd))
        transforms = [k.GetTransform()[0:3, 0:3] for k in robot.GetLinks()]
        masses = [k.GetMass() for k in robot.GetLinks()]
        localCOM = [k.GetLocalCOM() for k in robot.GetLinks()]
    tau0 = array([0., 0., 0.])
    totalmass = sum(masses)
    if hasattr(robot, 'activelinks'):
        totalmass = 0
        for k in range(n):
            if robot.activelinks[k] > 0.1:
                totalmass += masses[k]
    f02 = totalmass * g[2]
    com = zeros(3)
    for i in range(n):
        if hasattr(robot, 'activelinks') and robot.activelinks[i] < 0.1:
            continue
        # Compute the inertia matrix in the global frame
        R = transforms[i]
        ri = dot(R, localCOM[i])
        omegai = vel[i, 3:6]
        omegadi = acc[i, 3:6]
        #com_vel = vel[i, 0:3] + cross(omegai, ri)
        ci = com_pos[i]
        cidd = acc[i, 0:3] + cross(omegai, cross(omegai, ri)) + cross(omegadi,
                                                                      ri)
        tau0 += masses[i] * cross(ci, g - cidd)
        f02 -= masses[i] * cidd[2]
        com += masses[i] * ci

    return -tau0[1] / f02, tau0[0] / f02, com / totalmass
Beispiel #7
0
def ComputeZMPConfig(robot, q, qd, qdd):
    n = len(robot.GetLinks())
    g = robot.GetEnv().GetPhysicsEngine().GetGravity()
    with robot:
        robot.SetDOFValues(Fill(robot, q))
        robot.SetDOFVelocities(Fill(robot, qd))
        com_pos = array([k.GetGlobalCOM() for k in robot.GetLinks()])
        vel = robot.GetLinkVelocities()
        acc = robot.GetLinkAccelerations(Fill(robot, qdd))
        transforms = [k.GetTransform()[0:3, 0:3] for k in robot.GetLinks()]
        masses = [k.GetMass() for k in robot.GetLinks()]
        localCOM = [k.GetLocalCOM() for k in robot.GetLinks()]
    tau0 = array([0., 0., 0.])
    totalmass = sum(masses)
    if hasattr(robot, 'activelinks'):
        totalmass = 0
        for k in range(n):
            if robot.activelinks[k] > 0.1:
                totalmass += masses[k]
    f02 = totalmass * g[2]
    com = zeros(3)
    for i in range(n):
        if hasattr(robot, 'activelinks') and robot.activelinks[i] < 0.1:
            continue
        # Compute the inertia matrix in the global frame
        R = transforms[i]
        ri = dot(R, localCOM[i])
        omegai = vel[i, 3:6]
        omegadi = acc[i, 3:6]
        #com_vel = vel[i, 0:3] + cross(omegai, ri)
        ci = com_pos[i]
        cidd = acc[i, 0:3] + cross(omegai, cross(omegai, ri)) + cross(
            omegadi, ri)
        tau0 += masses[i] * cross(ci, g - cidd)
        f02 -= masses[i] * cidd[2]
        com += masses[i] * ci

    return -tau0[1] / f02, tau0[0] / f02, com / totalmass
Beispiel #8
0
def generate_datafile(name,departures,depart_planet,arrive_planet,errors=0):
    f = open(name,'w')
    last = departures[-1]
    lasty = int(last[0] / 60.0 / 60.0 / 24.0 / 365.0)
    inacc = 0.0
    for departure in departures:
        if departure[1]:
            inacc += 1.0
            
    f.write("// Phase angles for the next %i years for %s - %s Hohmann transfers\n"%(lasty,depart_planet.name,arrive_planet.name))
    f.write("// Calculated using the KSP Mission Control toolkit\n")
    f.write("// Angles are valid for Kerbal Space Program 0.19\n")
    f.write("// Total windows: %i\n"%len(departures))
    f.write("// Inaccuracies during calculation: %i (%i%%)\n\n"%(inacc,inacc / len(departures) * 100))
    f.write("UT Departure\tPhase angle\tDate time\tAccurate (Error in seconds)\n")
    for departure in departures:
        accurate = departure[1]
        if accurate == 0:
            accurate = "Yes"
        else:
            accurate = str(accurate)
            
        departure = departure[0]
        
        e1 = depart_planet.eph(departure)[0]
        e2 = arrive_planet.eph(departure)[0]
        e1 /= norm(e1)
        e2 /= norm(e2)
        PA = degrees(arccos(e1.dot(e2))) * sign(cross(e1,e2)[2])
        
        years = floor(departure/60.0/60.0/24.0/365.0)+1
        days = floor((departure/60.0/60.0/24.0)%365.0)+1
        
        f.write("%f\t%f\tYear %i, Day %i\t%s\n"%(departure,PA,years,days,accurate))
        
    f.close()
def ecef2tanpoint(x, y, z, dx, dy, dz):
    """
    This function takes a position and look vector in ECEF system and returns the tangent point
    (point closest to the ellipsiod) for the WGS-84 ellipsiod in ECEF coordinates.
    
    The algorithm used is derived by Nick Lloyd at University of Saskatchewan, 
    Canada ([email protected]), and is part of
    the operational code for both OSIRIS and SMR on-board- the Odin satellite.
    
    
        Arguments:
            x (float): ECEF X-coordinate (m)
            
            y (float): ECEF Y-coordinate (m)
            
            z (float): ECEF Z-coordinate (m)
            
            dx (float): ECEF look vector X-coordinate (m)
            
            dy (float): ECEF look vector Y-coordinate (m)
            
            dz (float): ECEF look vector Z-coordinate (m
    
        Returns:
            (tuple): tuple containing:
                
            **tx** (*float*): ECEF X-coordinate of tangentpoint (m)
            
            **ty** (*float*): ECEF Y-coordinate of tangentpoint (m)
            
            **tz** (*float*): ECEF Z-coordinate of tangentpoint (m)
    
    """

    # FIXME check normalization of dx,dy,dz!

    # WGS-84 semi-major axis and eccentricity

    a = 6378137

    e = 0.081819190842621

    a2 = a ** 2

    b2 = a2 * (1 - e ** 2)

    X = pylab.array([x, y, z])

    xunit = pylab.array([dx, dy, dz])

    zunit = pylab.cross(xunit, X)

    zunit = zunit / pylab.linalg.norm(zunit)

    yunit = pylab.cross(zunit, xunit)

    yunit = yunit / pylab.linalg.norm(yunit)

    w11 = xunit[0]

    w12 = yunit[0]

    w21 = xunit[1]

    w22 = yunit[1]

    w31 = xunit[2]

    w32 = yunit[2]

    yr = pylab.dot(X, yunit)

    xr = pylab.dot(X, xunit)

    A = (w11 * w11 + w21 * w21) / a2 + w31 * w31 / b2

    B = 2.0 * ((w11 * w12 + w21 * w22) / a2 + (w31 * w32) / b2)

    C = (w12 * w12 + w22 * w22) / a2 + w32 * w32 / b2

    if B == 0.0:

        xx = 0.0

    else:

        K = -2.0 * A / B

        factor = 1.0 / (A + (B + C * K) * K)

        xx = pylab.sqrt(factor)

        yy = K * x

    dist1 = (xr - xx) * (xr - xx) + (yr - yy) * (yr - yy)

    dist2 = (xr + xx) * (xr + xx) + (yr + yy) * (yr + yy)

    if dist1 > dist2:

        xx = -xx

    tx = w11 * xx + w12 * yr

    ty = w21 * xx + w22 * yr

    tz = w31 * xx + w32 * yr

    return tx, ty, tz
def Satellite_Simulator(
    Satellite_skyfield,
    SimulationTime,
    Timeline_settings,
    pointing_altitude,
    LogFlag=False,
    Logger=None,
):
    """Simulates a single point in time for a Satellite using Skyfield and also the pointing of the satellite.
    
    Only estimates the actual pointing definition used by OHB as it is uncertain if the algorithm to calculate the LP here is the same as the one OHB uses. 
    The LP is calculated with an algorithm derived by Nick Lloyd at University of Saskatchewan, 
    Canada ([email protected]), and is part of
    the operational code for both OSIRIS and SMR on-board- the Odin satellite. An offset is added to the pointing altitude to better mimic OHBs actual LP.
    
    Arguments:
        Satellite_skyfield (:obj:`skyfield.sgp4lib.EarthSatellite`): A Skyfield object representing an EarthSatellite defined by a TLE.
        SimulationTime (:obj:`ephem.Date`): The time of the simulation.
        Timeline_settings (dict): A dictionary containing relevant settings to the simulation.
        pointing_altitude (float): Contains the pointing altitude of the simulation [km].
        LogFlag (bool): If data from the simulation shall be logged.
        Logger (:obj:`logging.Logger`): Logger used to log the result from the simulation if LogFlag == True.
        
    Returns:
        (dict): Dictionary containing simulated data.
        
    """

    U = 398600.441800000  # Earth gravitational parameter
    R_mean = 6371.000
    celestial_eq = [0, 0, 1]

    "Offset the pointing altitude slightly which improves the estimation of OHBs actual pointing"
    pointing_altitude = pointing_altitude + 0.3

    yaw_correction = Timeline_settings["yaw_correction"]

    current_time_datetime = ephem.Date(SimulationTime).datetime()
    year = current_time_datetime.year
    month = current_time_datetime.month
    day = current_time_datetime.day
    hour = current_time_datetime.hour
    minute = current_time_datetime.minute
    second = current_time_datetime.second + current_time_datetime.microsecond / 1000000

    current_time_skyfield = timescale_skyfield.utc(year, month, day, hour,
                                                   minute, second)

    Satellite_geo = Satellite_skyfield.at(current_time_skyfield)
    v_Satellite = Satellite_geo.velocity.km_per_s
    r_Satellite = Satellite_geo.position.km
    Satellite_distance = Satellite_geo.distance().km
    Satellite_subpoint = Satellite_geo.subpoint()
    lat_Satellite = Satellite_subpoint.latitude.degrees
    long_Satellite = Satellite_subpoint.longitude.degrees
    alt_Satellite = Satellite_subpoint.elevation.km

    r_Satellite_unit_vector = r_Satellite / norm(r_Satellite)

    "Semi-Major axis of Satellite, assuming circular orbit"
    Satellite_p = norm(r_Satellite)

    "Orbital Period of Satellite"
    orbital_period = 2 * pi * sqrt(Satellite_p**3 / U)

    "Initial Estimated pitch or elevation angle for Satellite pointing (angle between negativ velocity vector and optical axis in the orbital plane)"
    OrbAngleBetweenSatelliteAndLP = (arccos(
        (R_mean + pointing_altitude) / (Satellite_distance)) / pi * 180)

    time_between_LP_and_Satellite = orbital_period * OrbAngleBetweenSatelliteAndLP / 360

    "Estimation of lat of LP using the position of Satellite at a previous time"
    date_of_Satellitelat_is_equal_2_current_LPlat = ephem.Date(
        SimulationTime -
        ephem.second * time_between_LP_and_Satellite).datetime()
    lat_LP = lat_calculator(Satellite_skyfield,
                            date_of_Satellitelat_is_equal_2_current_LPlat)
    R_earth_LP = lat_2_R(lat_LP)

    "More accurate estimated pitch or elevation angle for Satellite pointing"
    OrbAngleBetweenSatelliteAndLP = (arccos(
        (R_earth_LP + pointing_altitude) / (Satellite_distance)) / pi * 180)

    Pitch = 90 + OrbAngleBetweenSatelliteAndLP

    "############# Calculations of orbital and pointing vectors ############"
    "Vector normal to the orbital plane of Satellite"
    normal_orbit = cross(r_Satellite, v_Satellite)
    normal_orbit = normal_orbit / norm(normal_orbit)

    "Calculate intersection between the orbital plane and the equator"
    ascending_node = cross(celestial_eq, normal_orbit)

    "Argument of latitude"
    arg_of_lat = (arccos(
        dot(ascending_node, r_Satellite) / norm(r_Satellite) /
        norm(ascending_node)) / pi * 180)

    "To determine if Satellite is moving towards the ascending node"
    if dot(cross(ascending_node, r_Satellite), normal_orbit) <= 0:
        arg_of_lat = 360 - arg_of_lat

    if yaw_correction == True:
        yaw_offset_angle = Timeline_settings["yaw_amplitude"] * cos(
            arg_of_lat / 180 * pi - (Pitch - 90) / 180 * pi -
            Timeline_settings["yaw_phase"] / 180 * pi)
    elif yaw_correction == False:
        yaw_offset_angle = 0

    "Rotate 'vector to Satellite', to represent pointing direction"
    rot_mat = rot_arbit(Pitch / 180 * pi, -normal_orbit)
    optical_axis = rot_mat @ (r_Satellite)

    "Apply yaw to optical_axis, meaning to rotate around the vector to Satellite"
    rot_mat = rot_arbit(yaw_offset_angle / 180 * pi, -r_Satellite_unit_vector)
    optical_axis = rot_mat @ optical_axis
    optical_axis_unit_vector = optical_axis / norm(optical_axis)

    "Rotate 'vector to Satellite', to represent vector normal to satellite H-offset "
    rot_mat = rot_arbit((Pitch - 90) / 180 * pi, -normal_orbit)
    r_H_offset_normal = rot_mat @ r_Satellite
    r_H_offset_normal = r_H_offset_normal / norm(r_H_offset_normal)

    "If pointing direction has a Yaw defined, Rotate yaw of normal to pointing direction H-offset plane, meaning to rotate around the vector to Satellite"
    rot_mat = rot_arbit(yaw_offset_angle / 180 * pi, -r_Satellite_unit_vector)
    r_H_offset_normal = rot_mat @ r_H_offset_normal
    r_H_offset_normal = r_H_offset_normal / norm(r_H_offset_normal)

    "Rotate negative orbital plane normal to make it into a normal to the V-offset plane"
    r_V_offset_normal = rot_mat @ -normal_orbit
    r_V_offset_normal = r_V_offset_normal / norm(r_V_offset_normal)

    "Calculate Dec and RA of optical axis"
    Dec_optical_axis = (arctan(
        optical_axis[2] / sqrt(optical_axis[0]**2 + optical_axis[1]**2)) / pi *
                        180)
    RA_optical_axis = (arccos(
        dot([1, 0, 0], [optical_axis[0], optical_axis[1], 0]) /
        norm([optical_axis[0], optical_axis[1], 0])) / pi * 180)
    if optical_axis[1] < 0:
        RA_optical_axis = 360 - RA_optical_axis

    if LogFlag == True and Logger != None:
        Logger.debug("")

        Logger.debug("SimulationTime time: " + str(SimulationTime))
        Logger.debug("Semimajor axis in km: " + str(Satellite_p))
        Logger.debug("Orbital Period in s: " + str(orbital_period))
        Logger.debug("Vector to Satellite [km]: " + str(r_Satellite))
        Logger.debug("Latitude in degrees: " + str(lat_Satellite))
        Logger.debug("Longitude in degrees: " + str(long_Satellite))
        Logger.debug("Altitude in km: " + str(alt_Satellite))
        Logger.debug("Satellite_distance [km]: " + str(Satellite_distance))

        Logger.debug("R_earth_LP [km]: " + str(R_earth_LP))

        Logger.debug("Pitch [degrees]: " + str(Pitch))
        Logger.debug("Yaw [degrees]: " + str(yaw_offset_angle))
        Logger.debug("ArgOfLat [degrees]: " + str(arg_of_lat))
        Logger.debug("Latitude of LP: " + str(lat_LP))
        Logger.debug("Optical Axis: " + str(optical_axis_unit_vector))
        Logger.debug("Orthogonal direction to H-offset plane: " +
                     str(r_H_offset_normal))
        Logger.debug("Orthogonal direction to V-offset plane: " +
                     str(r_V_offset_normal))
        Logger.debug("Orthogonal direction to the orbital plane: " +
                     str(normal_orbit))

    Satellite_dict = {
        "Position [km]": r_Satellite,
        "Velocity [km/s]": v_Satellite,
        "OrbitNormal": normal_orbit,
        "OrbitalPeriod [s]": orbital_period,
        "Latitude [degrees]": lat_Satellite,
        "Longitude [degrees]": long_Satellite,
        "Altitude [km]": alt_Satellite,
        "AscendingNode": ascending_node,
        "ArgOfLat [degrees]": arg_of_lat,
        "Yaw [degrees]": yaw_offset_angle,
        "Pitch [degrees]": Pitch,
        "OpticalAxis": optical_axis_unit_vector,
        "Dec_OpticalAxis [degrees]": Dec_optical_axis,
        "RA_OpticalAxis [degrees]": RA_optical_axis,
        "Normal2H_offset": r_H_offset_normal,
        "Normal2V_offset": r_V_offset_normal,
        "EstimatedLatitude_LP [degrees]": lat_LP,
    }

    # return r_Satellite, lat_Satellite, long_Satellite, alt_Satellite, optical_axis_unit_vector, Dec_optical_axis, RA_optical_axis, r_H_offset_normal, r_V_offset_normal, orbital_period
    return Satellite_dict
def date_calculator():
    """Subfunction, Simulates MATS FOV and the Moon.
    
    Determines when the Moon is entering the FOV at an vertical offset-angle equal to *#V-offset* and also being 
    located at a horizontal off-set angle equal to less than *#H-offset* when pointing at an LP altitude equal to *#pointing_altitude*. \n
    
    A timeskip equal to 1/2 an orbit of MATS is applied after a successful spotting of the Moon to save processing time. \n
    
    A timeskip equal to the time it takes for the Moon orbital position to change by *#H-offset*/4 degrees are also applied if the Moon is 
    determined to be at an horizontal off-set angle larger then the horizontal FOV of the instrument, equal to *#HFOV*. \n
    
    (# as defined in the *Configuration File*). \n
    
    Saves the date and parameters regarding the spotting of the Moon to the variable SpottedMoonList.
    
    Arguments:
        
    Returns:
        SpottedMoonList ((:obj:`list` of :obj:`dict`)) or (str): A list containing dictionaries containing parameters for each time the Moon is spotted. Or just a date depending on 'automatic' in *Mode124_settings*.
    
    """

    Timeline_settings = OPT_Config_File.Timeline_settings()
    Mode124_settings = OPT_Config_File.Mode124_settings()

    log_timestep = Mode124_settings['log_timestep']
    Logger.debug('log_timestep: ' + str(log_timestep))

    ##################################################

    "Check how many times Mode124 have been scheduled"
    Mode124Iteration = _Globals.Mode124Iteration
    "Make the V_offset_Index go from 0 to len(Mode124_settings['V_offset']"
    V_offset_Index = (Mode124Iteration - 1) % (len(
        Mode124_settings['V_offset']))

    "Constants"
    V_offset = Mode124_settings['V_offset'][V_offset_Index]
    H_offset = Mode124_settings['H_offset']
    pointing_altitude = Mode124_settings['pointing_altitude'] / 1000

    Moon_orbital_period = 3600 * 24 * 27.32
    yaw_correction = Timeline_settings['yaw_correction']

    Logger.debug('H_offset set to [degrees]: ' + str(H_offset))
    Logger.debug('V_offset set to [degrees]: ' + str(V_offset))
    Logger.debug('Moon_orbital_period [s]: ' + str(Moon_orbital_period))
    Logger.debug('yaw_correction set to: ' + str(yaw_correction))

    TLE = OPT_Config_File.getTLE()
    Logger.debug('TLE used: ' + TLE[0] + TLE[1])

    ##########################################################

    "Simulation length and timestep"

    timestep = Mode124_settings['timestep']  #In seconds
    Logger.info('Timestep set to [s]: ' + str(timestep))

    if (Mode124_settings['TimeToConsider'] <= Timeline_settings['duration']):
        duration = Mode124_settings['TimeToConsider']
    else:
        duration = Timeline_settings['duration']
    Logger.info('Duration set to [s]: ' + str(duration))

    timesteps = int(ceil(duration / timestep)) + 2

    timeline_start = ephem.Date(Timeline_settings['start_date'])
    initial_time = ephem.Date(timeline_start +
                              ephem.second * Mode124_settings['freeze_start'])

    Logger.info('Initial simulation date set to: ' + str(initial_time))

    "Pre-allocate space"
    r_MATS = zeros((timesteps, 3))
    lat_MATS = zeros((timesteps, 1))
    long_MATS = zeros((timesteps, 1))
    optical_axis = zeros((timesteps, 3))
    negative_normal_orbit = zeros((timesteps, 3))
    r_H_offset_normal = zeros((timesteps, 3))
    r_V_offset_normal = zeros((timesteps, 3))
    MATS_P = zeros((timesteps, 1))

    r_Moon = zeros((timesteps, 3))
    r_MATS_2_Moon = zeros((timesteps, 3))
    r_MATS_2_Moon_norm = zeros((timesteps, 3))
    Moon_r_V_offset_plane = zeros((timesteps, 3))
    Moon_r_H_offset_plane = zeros((timesteps, 3))
    Moon_r_orbital_plane = zeros((timesteps, 3))
    Moon_vert_offset = zeros((timesteps, 1))
    Moon_hori_offset = zeros((timesteps, 1))
    angle_between_orbital_plane_and_moon = zeros((timesteps, 1))
    SpottedMoonList = []
    r_Moon_unit_vector = zeros((timesteps, 3))

    Dec_optical_axis = zeros((timesteps, 1))
    RA_optical_axis = zeros((timesteps, 1))

    ts = api.load.timescale(builtin=True)
    MATS_skyfield = api.EarthSatellite(TLE[0], TLE[1])

    planets = api.load('de421.bsp')
    Moon = planets['Moon']
    Earth = planets['Earth']

    t = 0

    current_time = initial_time

    Logger.info('')
    Logger.info('Start of simulation for Mode124')

    ######### SIMULATION ################
    while (current_time < initial_time + ephem.second * duration):

        if (t * timestep % log_timestep == 0):
            LogFlag = True
        else:
            LogFlag = False

        Satellite_dict = Satellite_Simulator(MATS_skyfield, current_time,
                                             Timeline_settings,
                                             pointing_altitude, LogFlag,
                                             Logger)

        r_MATS[t] = Satellite_dict['Position [km]']
        MATS_P[t] = Satellite_dict['OrbitalPeriod [s]']
        lat_MATS[t] = Satellite_dict['Latitude [degrees]']
        long_MATS[t] = Satellite_dict['Longitude [degrees]']

        optical_axis[t] = Satellite_dict['OpticalAxis']
        Dec_optical_axis[t] = Satellite_dict['Dec_OpticalAxis [degrees]']
        RA_optical_axis[t] = Satellite_dict['RA_OpticalAxis [degrees]']

        ascending_node = Satellite_dict['AscendingNode']
        yaw_offset_angle = Satellite_dict['Yaw [degrees]']
        arg_of_lat = Satellite_dict['ArgOfLat [degrees]']

        negative_normal_orbit[t] = -Satellite_dict['OrbitNormal']
        r_H_offset_normal[t] = Satellite_dict['Normal2H_offset']
        r_V_offset_normal[t] = Satellite_dict['Normal2V_offset']

        ############# End of Calculations of orbital and pointing vectors #####

        current_time_datetime = ephem.Date(current_time).datetime()
        year = current_time_datetime.year
        month = current_time_datetime.month
        day = current_time_datetime.day
        hour = current_time_datetime.hour
        minute = current_time_datetime.minute
        second = current_time_datetime.second + current_time_datetime.microsecond / 1000000

        current_time_skyfield = ts.utc(year, month, day, hour, minute, second)

        Moon_apparent_from_Earth = Earth.at(current_time_skyfield).observe(
            Moon).apparent()
        r_Moon[t, 0:3] = Moon_apparent_from_Earth.position.km

        r_Moon_unit_vector[t, 0:3] = r_Moon[t, 0:3] / norm(r_Moon[t, 0:3])

        r_MATS_2_Moon[t] = r_Moon[t] - r_MATS[t]
        r_MATS_2_Moon_norm[t] = r_MATS_2_Moon[t] / norm(r_MATS_2_Moon[t])

        "Calculate Dec and RA of moon"
        Dec_Moon = arctan(
            r_Moon[t, 2] / sqrt(r_Moon[t, 0]**2 + r_Moon[t, 1]**2)) / pi * 180
        RA_Moon = arccos(
            dot([1, 0, 0], [r_Moon[t, 0], r_Moon[t, 1], 0]) /
            norm([r_Moon[t, 0], r_Moon[t, 1], 0])) / pi * 180

        if (r_Moon[t, 1] < 0):
            RA_Moon = 360 - RA_Moon

        "Project 'r_MATS_2_Moon' ontop of orbital plane"
        Moon_r_orbital_plane[t] = r_MATS_2_Moon_norm[t] - dot(
            r_MATS_2_Moon_norm[t],
            negative_normal_orbit[t]) * negative_normal_orbit[t]

        "Project 'r_MATS_2_Moon' ontop pointing H-offset and V-offset plane"
        Moon_r_V_offset_plane[t] = r_MATS_2_Moon_norm[t] - dot(
            r_MATS_2_Moon_norm[t], r_V_offset_normal[t]) * r_V_offset_normal[t]
        Moon_r_H_offset_plane[t] = r_MATS_2_Moon_norm[t] - dot(
            r_MATS_2_Moon_norm[t], r_H_offset_normal[t]) * r_H_offset_normal[t]

        "Dot product to get the Vertical and Horizontal angle offset of the Moon"
        Moon_vert_offset[t] = arccos(
            dot(optical_axis[t], Moon_r_V_offset_plane[t]) /
            (norm(optical_axis[t]) *
             norm(Moon_r_V_offset_plane[t]))) / pi * 180
        Moon_hori_offset[t] = arccos(
            dot(optical_axis[t], Moon_r_H_offset_plane[t]) /
            (norm(optical_axis[t]) *
             norm(Moon_r_H_offset_plane[t]))) / pi * 180

        "Get the offset angle sign correct"
        if (dot(cross(optical_axis[t], Moon_r_V_offset_plane[t]),
                negative_normal_orbit[t, 0:3]) > 0):
            Moon_vert_offset[t] = -Moon_vert_offset[t]
        if (dot(cross(optical_axis[t], Moon_r_H_offset_plane[t]),
                r_H_offset_normal[t]) > 0):
            Moon_hori_offset[t] = -Moon_hori_offset[t]

        "Angle between orbital plane and moon"
        angle_between_orbital_plane_and_moon[t] = arccos(
            dot(r_MATS_2_Moon_norm[t], Moon_r_orbital_plane[t]) /
            norm(Moon_r_orbital_plane[t])) / pi * 180

        if (t * timestep % log_timestep == 0 or t == 1):
            Logger.debug('angle_between_orbital_plane_and_moon [degrees]: ' +
                         str(angle_between_orbital_plane_and_moon[t]))
            Logger.debug('Moon_vert_offset [degrees]: ' +
                         str(Moon_vert_offset[t]))
            Logger.debug('Moon_hori_offset [degrees]: ' +
                         str(Moon_hori_offset[t]))

        #print('angle_between_orbital_plane_and_moon = ' + str(angle_between_orbital_plane_and_moon[t]))

        if (t != 0):
            "Check that the Moon is entering at V-offset degrees and within the H-offset angle"
            if (Moon_vert_offset[t] <= V_offset
                    and Moon_vert_offset[t - 1] > V_offset
                    and abs(Moon_hori_offset[t]) < H_offset):

                Logger.debug('')
                Logger.debug('!!!!!!!!Moon available!!!!!!!!!!')
                Logger.debug('t (loop iteration number): ' + str(t))
                Logger.debug('Current time: ' + str(current_time))
                Logger.debug('Orbital Period in s: ' + str(MATS_P[t]))
                Logger.debug('Vector to MATS [km]: ' + str(r_MATS[t, 0:3]))
                Logger.debug('Latitude in radians: ' + str(lat_MATS[t]))
                Logger.debug('Longitude in radians: ' + str(long_MATS[t]))

                if (yaw_correction == True):
                    Logger.debug('ascending_node: ' + str(ascending_node))
                    Logger.debug('arg_of_lat [degrees]: ' + str(arg_of_lat))
                    Logger.debug('yaw_offset_angle [degrees]: ' +
                                 str(yaw_offset_angle))

                Logger.debug(
                    'angle_between_orbital_plane_and_moon [degrees]: ' +
                    str(angle_between_orbital_plane_and_moon[t]))
                Logger.debug('Moon_vert_offset [degrees]: ' +
                             str(Moon_vert_offset[t]))
                Logger.debug('Moon_hori_offset [degrees]: ' +
                             str(Moon_hori_offset[t]))
                Logger.debug('normal_orbit: ' +
                             str(-negative_normal_orbit[t, 0:3]))
                Logger.debug('r_V_offset_normal: ' +
                             str(r_V_offset_normal[t, 0:3]))
                Logger.debug('r_H_offset_normal: ' +
                             str(r_H_offset_normal[t, 0:3]))
                Logger.debug('optical_axis: ' + str(optical_axis[t, 0:3]))

                Logger.debug('')

                SpottedMoonList.append({
                    'Date': str(current_time),
                    'V-offset': Moon_vert_offset[t],
                    'H-offset': Moon_hori_offset[t],
                    'long_MATS': float(long_MATS[t]),
                    'lat_MATS': float(lat_MATS[t]),
                    'Dec': Dec_Moon,
                    'RA': RA_Moon,
                    'Dec FOV': Dec_optical_axis[t],
                    'RA FOV': RA_optical_axis[t]
                })

                Logger.debug('Jump ahead half an orbit in time')
                "Skip ahead half an orbit"
                current_time = ephem.Date(current_time +
                                          ephem.second * MATS_P[t] / 2)
                Logger.debug('Current time: ' + str(current_time))
                Logger.debug('')

        "To be able to make time skips when the moon is far outside the orbital plane of MATS"
        if ((angle_between_orbital_plane_and_moon[t] > H_offset
             and yaw_correction == False)
                or angle_between_orbital_plane_and_moon[t] >
                H_offset + abs(Timeline_settings['yaw_amplitude'])
                and yaw_correction == True):

            current_time = ephem.Date(current_time + ephem.second * H_offset /
                                      4 / 360 * Moon_orbital_period)
            #if( t*timestep % floor(log_timestep/400) == 0 ):
            Logger.debug('')
            Logger.debug('angle_between_orbital_plane_and_moon [degrees]: ' +
                         str(angle_between_orbital_plane_and_moon[t]))
            Logger.debug('Moon currently not visible -> jump ahead')
            Logger.debug('current_time after jump is is: ' + str(current_time))

            t = t + 1
        else:
            t = t + 1
            current_time = ephem.Date(current_time + ephem.second * timestep)

    Logger.info('End of simulation for Mode124')
    Logger.debug('SpottedMoonList: ' + str(SpottedMoonList))

    return SpottedMoonList
Beispiel #12
0
 def initFromStateVectors(self,epoch,pV,vV):
     self.epoch = epoch
     
     # 1) Calculate auxilary vector h
     hV = cross(pV,vV)
     
     
     # 2) Normalize position,velocity, specific angular momentum, calculate radial velocity 
     
     p = linalg.norm(pV)
     v = linalg.norm(vV)
     h = linalg.norm(hV)
     print "H:",h
     radv = pV.dot(vV) / p
     hVu = hV / h
     pVu = pV / p
     nV = cross(array([0,0,1]),hV)
     n = linalg.norm(nV)
     if n == 0:
         nVu = array([0,0,0])
     else:
         nVu = nV/n
     # 3) Calculate inclination
     #self.i = arccos(hV[2]/h)
     self.i = arcsin(linalg.norm(cross(array([0,0,1]),hVu)))
     print "i1",self.i
     print "RADVEL",radv
     self.i = arccos(array([0,0,1]).dot(hV)/h)
     #if radv < 0:
     #    self.i = PI2 - self.i 
     print "i2",self.i
     # 4) Calculate node line
     
     
     # 5) Calculate longitude of ascending node = right ascension of ascending node
     '''
     if self.i == 0:
         self.lan=0
     elif nV[1] >= 0:
         self.lan = arccos(nV[0] / n)
     else:
         self.lan = PI2 - arccos(nV[0] / n)
     '''
     
     if self.i == 0:
         self.lan = 0
     else:
         self.lan = arcsin(cross(array([1,0,0]),nVu).dot(array([0,0,1])))
         print "lan1",self.lan
         self.lan = arccos(array([1,0,0]).dot(nV)/n)
         if nV[1] < 0:
             self.lan = PI2-self.lan
         print "lan2",self.lan
     
     # 6) Eccentricity vector
     #eV = (1.0 / self.ref.mu)*((v**2 - (self.ref.mu / p))*pV - radv*vV)
     #eV2 = (1.0 / self.ref.mu) * ( hV - self.ref.mu * (pV/p))
     #eV3 = hV/self.ref.mu - (pV/p)
     
     # Source: cdeagle
     eV = cross(vV,hV)/self.ref.mu - pVu
     #print "eV1:",eV,linalg.norm(eV)
     #print "eV2:",eV2,linalg.norm(eV2)
     #print "eV3:",eV3,linalg.norm(eV3)
     print "eV3:",eV,linalg.norm(eV)
     self._e = linalg.norm(eV)
     #eVu = eV / self.e
     
     print "h",h
     print "u",self.ref.mu
     print "v",v
     print "r",p
     
     print "alte:",sqrt(1+(h**2/self.ref.mu**2)*(v**2-(2*self.ref.mu)/p)**2)
     # 7) Argument of perigree
     '''
     if self.e == 0:
         self.aop = 0
     elif self.i == 0:
       self.aop = arccos(eV[0] / self.e)  
     elif eV[2] >= 0:
         print "AOP AOP AOP"
         #self.aop = arccos(nV.dot(eV) / (n*self.e))
         print cross(nV,eV).dot(hV)
         self.aop = arcsin(cross(nVu,eVu).dot(hVu))
         #self.aop = arccos(n*self.e)
     else:
         self.aop = PI2 - arccos(nV.dot(eV) / (n*self.e))
     '''
     #CDEagle method
     # TODO CHECK how KSP handles this. 
     if self.e == 0:
         self.aop = 0
     elif self.i == 0 and self.e != 0:            
         #self.aop = arccos(eV[0] / self.e)
         #self.aop = arctan2(eV[1],eV[0])
         self.aop = arccos(array([1,0,0]).dot(eV) / self.e)
         print eV
         if eV[2] < 0:
             #self.aop = -self.aop
             self.aop = PI2-self.aop
         
         #print "BOOM",eV
         #if eV[2] < 0:
         #    print "BAM N***A"
         #    self.aop = PI2 - self.aop
     elif self.i == 0 and self.e == 0:
         #raise AttributeError("Perfectly circular orbits are not supported atm")
         self.aop = 0
     else:
         #self.aop = arcsin(cross(nVu,eVu).dot(hVu))
         self.aop = arccos(nV.dot(eV)/(n*self.e))
         if eV[2] < 0:
             self.aop = PI2-self.aop
     
     # 8) Semi major axis
     aE = v**2/2.0 - self.ref.mu / p
     self._a = -self.ref.mu / (2*aE)
     print "Old method for semi-major",self.a
     self._a = h**2 / (self.ref.mu * (1-self.e**2))
     print "New method for semi-major",self.a  
     #if self.e > 1:
     #    self._a = h**2 / (self.ref.mu * (self.e**2 - 1))
     
     if self.e == 0:
         if self.i == 0: #TODO update document to this
             print "JEA JEA JEA JEA"*10
             
             ta = arccos(array([1,0,0]).dot(pV) / p)
             if pV[1] < 0: # Vallado pg. 111
                 ta = PI2 - ta
         else: #TODO VERIFY THIS CASE
             ta = arccos((nV.dot(pV))/(n*p))
             if pV[2] < 0: # Vallado pg. 110
                 ta = PI2 - ta
         E = ta
         self.M0 = E
           
     elif self.e < 1:
         # 9) True anomaly, eccentric anomaly and mean anomaly
         if radv >= 0:
             ta = arccos((eV / self.e).dot(pV/p))
         else:
             ta = PI2 - arccos((eV / self.e).dot(pV/p))
         
         
         E = arccos((self.e+cos(ta))/(1+ self.e*cos(ta)))
         if radv < 0:
             E = PI2 - E
     
         self.M0 = E - self.e * sin(E)
         
     elif self.e > 1:
         # 9) Hyperbolic True anomaly, eccentric anomaly and mean anomaly
         # http://scienceworld.wolfram.com/physics/HyperbolicOrbit.html
         V = arccos((abs(self.a)*(self.e**2 - 1)) /(self.e * p) - 1/self.e)
         ta = arccos((eV / self.e).dot(pV/p))
         
         if radv < 0: #TODO: Should affect F too?
             # Negative = heading towards periapsis
             print "PI2"
             V = PI2 - V
             ta = PI2-ta
         print "V",V
         print "TA",ta
         # http://www.bogan.ca/orbits/kepler/orbteqtn.html In you I trust
         # Hyperbolic eccentric anomaly
         cosV = cos(V)
         F = arccosh((self.e+cosV)/(1+self.e*cosV))
         if radv < 0:
             F = -F
         F2 = arcsinh((sqrt(self.e-1)*sin(V))/(1+self.e*cos(V)))
         ##F1 = F2
         print "F1:",F
         print "F2:",F2
         self.M0 = self.e * sinh(F) - F
         
     
  
     
     
     self.h = h
     
     print "Semi-major:",self.a
     print "Eccentricity:",self.e
     print "Inclination:",degrees(self.i),"deg"
     print "LAN:",degrees(self.lan),"deg"
     print "AoP:",degrees(self.aop),"deg"
     print "Mean anomaly:",self.M0
     print "Specific angular momentum:",self.h
     if self.e < 1:
         print "Eccentric anomaly",E
         print "True anomaly",ta
     else:
         print "Hyperbolic eccentric anomaly",F
         print "Hyperbolic true anomaly",degrees(V)
         
     print "Distance from object:",p
     print "Velocity:",v
            barra1[i][1]=i*p.sin(angulo_barra)
            barra2[i][0]=barra2_ini[0] + i*p.cos(angulo_barra)
            barra2[i][1]=barra2_ini[1] - i*p.sin(angulo_barra)
            centro_massa_1+=barra1[i]
            centro_massa_2+=barra2[i]

        torque1=0

        for bar1 in barra1:
            forca=0,0
            r=bar1 - barra1_ini
            for bar2 in barra2:
                delta_bar=bar2-bar1
                distancia=p.linalg.norm(delta_bar)
                forca+=ksigmaden2*delta_bar/(distancia**3)
            torque1+=p.cross(r,forca)


        #centro de massa e torque
        barra_transposta1=barra1.transpose()
        barra_transposta2=barra2.transpose()
        centro_massa_1/=comprimento_barra
        centro_massa_2/=comprimento_barra
        #print barra1_ini-centro_massa_1,g,p.cross(barra1_ini-centro_massa_1,g),angulo_barra
        torque1_g=p.cross(barra1_ini-centro_massa_1,g)*massa_barra #sai negativo
        #p.plot(barra_transposta1[0],barra_transposta1[1],lw=0.5)
        #p.plot(centro_massa_1[0],centro_massa_1[1],'r.')
        #print torque1,torque1_g,torque1+torque1_g
        torques.append(torque1+torque1_g)

    torques=abs(p.array(torques))
Beispiel #14
0
def lambert(r1vec,r2vec,tf,m,muC):
# original documentation:
# ·············································
#
# This routine implements a new algorithm that solves Lambert's problem. The
# algorithm has two major characteristics that makes it favorable to other
# existing ones.
#
# 1) It describes the generic orbit solution of the boundary condition
# problem through the variable X=log(1+cos(alpha/2)). By doing so the
# graph of the time of flight become defined in the entire real axis and
# resembles a straight line. Convergence is granted within few iterations
# for all the possible geometries (except, of course, when the transfer
# angle is zero). When multiple revolutions are considered the variable is
# X=tan(cos(alpha/2)*pi/2).
#
# 2) Once the orbit has been determined in the plane, this routine
# evaluates the velocity vectors at the two points in a way that is not
# singular for the transfer angle approaching to pi (Lagrange coefficient
# based methods are numerically not well suited for this purpose).
#
# As a result Lambert's problem is solved (with multiple revolutions
# being accounted for) with the same computational effort for all
# possible geometries. The case of near 180 transfers is also solved
# efficiently.
#
#  We note here that even when the transfer angle is exactly equal to pi
# the algorithm does solve the problem in the plane (it finds X), but it
# is not able to evaluate the plane in which the orbit lies. A solution
# to this would be to provide the direction of the plane containing the
# transfer orbit from outside. This has not been implemented in this
# routine since such a direction would depend on which application the
# transfer is going to be used in.
#
# please report bugs to [email protected]    
#
# adjusted documentation:
# ·······················
#
# By default, the short-way solution is computed. The long way solution
# may be requested by giving a negative value to the corresponding
# time-of-flight [tf].
#
# For problems with |m| > 0, there are generally two solutions. By
# default, the right branch solution will be returned. The left branch
# may be requested by giving a negative value to the corresponding
# number of complete revolutions [m].

# Authors
# .·`·.·`·.·`·.·`·.·`·.·`·.·`·.·`·.·`·.·`·.·`·.·`·.·`·.·`·.·`·.
# Name       : Dr. Dario Izzo
# E-mail     : [email protected]
# Affiliation: ESA / Advanced Concepts Team (ACT)

# Made readible and optimized for speed by Rody P.S. Oldenhuis
# Code available in MGA.M on   http://www.esa.int/gsp/ACT/inf/op/globopt.htm

# last edited 12/Dec/2009

# ADJUSTED FOR EML-COMPILATION 24/Dec/2009
    
    # initial values        
    tol = 1e-12
    bad = False
    days = 1

    # work with non-dimensional units
    r1 = norm(r1vec) #sqrt(r1vec*r1vec.');  r1vec = r1vec/r1;
    r1vec = r1vec / r1
    r2vec = r2vec / r1
    
    V = sqrt(muC/r1)     
    T = r1/V              
    tf= tf*days/T # also transform to seconds

    # relevant geometry parameters (non dimensional)
    mr2vec = norm(r2vec)
    # make 100# sure it's in (-1 <= dth <= +1)
    dth = arccos( max(-1, min(1, (r1vec.dot(r2vec)/mr2vec))))  
    
        
    # decide whether to use the left or right branch (for multi-revolution
    # problems), and the long- or short way    
    leftbranch = sign(m)
    longway = sign(tf)
    m = abs(m)
    tf = abs(tf)
    if (longway < 0):
        dth = 2*pi - dth  

    # derived quantities        
    c      = sqrt(1.0 + mr2vec**2 - 2*mr2vec*cos(dth)) # non-dimensional chord
    s      = (1.0 + mr2vec + c)/2.0                    # non-dimensional semi-perimeter
    a_min  = s/2.0                              # minimum energy ellipse semi major axis
    Lambda = sqrt(mr2vec)*cos(dth/2.0)/s              # lambda parameter (from BATTIN's book)

    crossprd = cross(r1vec,r2vec)

    mcr       = norm(crossprd)           # magnitues thereof
    nrmunit   = crossprd/mcr                        # unit vector thereof
    
    # Initial values
    # ·························································

    # ELMEX requires this variable to be declared OUTSIDE the IF-statement
    logt = log(tf); # avoid re-computing the same value
    
    # single revolution (1 solution)
    if (m == 0):

        # initial values        
        inn1 = -0.5233      # first initial guess
        inn2 = +0.5233      # second initial guess
        x1   = log(1 + inn1)# transformed first initial guess
        x2   = log(1 + inn2)# transformed first second guess

        # multiple revolutions (0, 1 or 2 solutions)
        # the returned soltuion depends on the sign of [m]
    else:          
        # select initial values
        if (leftbranch < 0):
            inn1 = -0.5234 # first initial guess, left branch
            inn2 = -0.2234 # second initial guess, left branch
        else:
            inn1 = +0.7234 # first initial guess, right branch
            inn2 = +0.5234 # second initial guess, right branch
        x1 = tan(inn1*pi/2)# transformed first initial guess
        x2 = tan(inn2*pi/2)# transformed first second guess
    

    # since (inn1, inn2) < 0, initial estimate is always ellipse
    xx   = array([inn1, inn2])
    aa = a_min/(1 - xx**2)
    
    bbeta = longway * 2*arcsin(sqrt((s-c)/2./aa))
    # make 100.4% sure it's in (-1 <= xx <= +1)
    if xx[0] > 1: xx[0] = 1
    if xx[0] < -1: xx[0] = -1
    if xx[1] > 1: xx[1] = 1
    if xx[1] < -1: xx[1] = -1
    aalfa = 2*arccos( xx )

    # evaluate the time of flight via Lagrange expression
    y12  = aa*sqrt(aa)*((aalfa - sin(aalfa)) - (bbeta-sin(bbeta)) + 2*pi*m)

    # initial estimates for y
    if m == 0:
        y1 = log(y12[0]) - logt
        y2 = log(y12[1]) - logt
    else:
        y1 = y12[0] - tf
        y2 = y12[1] - tf
    

    # Solve for x
    # ·························································
    
    # Newton-Raphson iterations
    # NOTE - the number of iterations will go to infinity in case
    # m > 0  and there is no solution. Start the other routine in 
    # that case
    
    err = 1e99  
    iterations = 0
    xnew = 0
    while (err > tol):
        # increment number of iterations
        iterations += 1
        # new x
        xnew = (x1*y2 - y1*x2) / (y2-y1);
        # copy-pasted code (for performance)
        if m == 0:
            x = exp(xnew) - 1
        else:
            x = arctan(xnew)*2/pi
            
        a = a_min/(1 - x**2);
        if (x < 1): # ellipse
            beta = longway * 2*arcsin(sqrt((s-c)/2/a))
            # make 100.4% sure it's in (-1 <= xx <= +1)
            alfa = 2*arccos( max(-1, min(1, x)) )
        else: # hyperbola
            alfa = 2*arccosh(x);
            beta = longway * 2*arcsinh(sqrt((s-c)/(-2*a)))
        
        # evaluate the time of flight via Lagrange expression
        if (a > 0):
            tof = a*sqrt(a)*((alfa - sin(alfa)) - (beta-sin(beta)) + 2*pi*m)
        else:
            tof = -a*sqrt(-a)*((sinh(alfa) - alfa) - (sinh(beta) - beta))
        
        # new value of y
        if m ==0:
            ynew = log(tof) - logt
        else:
            ynew = tof - tf
        # save previous and current values for the next iterarion
        # (prevents getting stuck between two values)
        x1 = x2;  x2 = xnew;
        y1 = y2;  y2 = ynew;
        # update error
        err = abs(x1 - xnew);
        # escape clause
        if (iterations > 15):
            bad = True 
            break
    
    
  
    
    # If the Newton-Raphson scheme failed, try to solve the problem
    # with the other Lambert targeter. 
    if bad:
        # NOTE: use the original, UN-normalized quantities
        #[V1, V2, extremal_distances, exitflag] = ...
        #    lambert_high_LancasterBlanchard(r1vec*r1, r2vec*r1, longway*tf*T, leftbranch*m, muC);
        print "FAILZ0r"
        return
    
    
    # convert converged value of x
    if m==0:
        x = exp(xnew) - 1
    else:
        x = arctan(xnew)*2/pi
    
    #{
    #      The solution has been evaluated in terms of log(x+1) or tan(x*pi/2), we
    #      now need the conic. As for transfer angles near to pi the Lagrange-
    #      coefficients technique goes singular (dg approaches a zero/zero that is
    #      numerically bad) we here use a different technique for those cases. When
    #      the transfer angle is exactly equal to pi, then the ih unit vector is not
    #      determined. The remaining equations, though, are still valid.
    #}

    # Solution for the semi-major axis
    a = a_min/(1-x**2);

    # Calculate psi
    if (x < 1): # ellipse
        beta = longway * 2*arcsin(sqrt((s-c)/2/a))
        # make 100.4# sure it's in (-1 <= xx <= +1)
        alfa = 2*arccos( max(-1, min(1, x)) )
        psi  = (alfa-beta)/2
        eta2 = 2*a*sin(psi)**2/s
        eta  = sqrt(eta2);
    else:       # hyperbola
        beta = longway * 2*arcsinh(sqrt((c-s)/2/a))
        alfa = 2*arccosh(x)
        psi  = (alfa-beta)/2
        eta2 = -2*a*sinh(psi)**2/s
        eta  = sqrt(eta2)
    

    # unit of the normalized normal vector
    ih = longway * nrmunit;

    # unit vector for normalized [r2vec]
    r2n = r2vec/mr2vec;

    # cross-products
    # don't use cross() (emlmex() would try to compile it, and this way it
    # also does not create any additional overhead)
    #crsprd1 = [ih(2)*r1vec(3)-ih(3)*r1vec(2),...
    #           ih(3)*r1vec(1)-ih(1)*r1vec(3),...
    #           ih(1)*r1vec(2)-ih(2)*r1vec(1)];    
    crsprd1 = cross(ih,r1vec)
    #crsprd2 = [ih(2)*r2n(3)-ih(3)*r2n(2),...
    #           ih(3)*r2n(1)-ih(1)*r2n(3),...
    #           ih(1)*r2n(2)-ih(2)*r2n(1)];
    crsprd2 = cross(ih,r2n)

    # radial and tangential directions for departure velocity
    Vr1 = 1/eta/sqrt(a_min) * (2*Lambda*a_min - Lambda - x*eta)
    Vt1 = sqrt(mr2vec/a_min/eta2 * sin(dth/2)**2)

    # radial and tangential directions for arrival velocity
    Vt2 = Vt1/mr2vec
    Vr2 = (Vt1 - Vt2)/tan(dth/2) - Vr1
    
    # terminal velocities
    V1 = (Vr1*r1vec + Vt1*crsprd1)*V
    V2 = (Vr2*r2n + Vt2*crsprd2)*V
    
    # exitflag
    #exitflag = 1 # (success)
    #print "V1:",V1
    #print "V2:",V2
    return V1,V2
def Mode200_date_calculator():
#if(True):
    Logger = logging.getLogger(Logger_name())
    
    log_timestep = 2000
    
    "Simulation length and timestep"
    duration = Timeline_params()['duration']
    Logger.info('Duration set to [s]: '+str(duration))
    timestep = Mode200_calculator_defaults()['timestep'] #In seconds
    Logger.info('Timestep set to [s]: '+str(timestep))
    
    
    date = Timeline_params()['start_time']
    Logger.info('date set to: '+str(date))
    
    MATS = ephem.readtle('MATS',getTLE()[0],getTLE()[1])
    
    Moon = ephem.Moon()
    
    "Pre-allocate space"
    lat_MATS = zeros((duration,1))
    long_MATS = zeros((duration,1))
    altitude_MATS = zeros((duration,1))
    g_ra_MATS = zeros((duration,1))
    g_dec_MATS = zeros((duration,1))
    x_MATS = zeros((duration,1))
    y_MATS = zeros((duration,1))
    z_MATS = zeros((duration,1))
    r_MATS = zeros((duration,3))
    r_MATS_unit_vector = zeros((duration,3))
    r_FOV = zeros((duration,3))
    normal_orbit = zeros((duration,3))
    normal_H_offset = zeros((duration,3))
    normal_H_offset_unit_vector = zeros((duration,3))
    pitch_array = zeros((duration,1))
    MATS_p = zeros((duration,1))
    MATS_P = zeros((duration,1))
    
    g_ra_Moon = zeros((duration,1))
    g_dec_Moon = zeros((duration,1))
    distance_Moon = zeros((duration,1))
    x_Moon = zeros((duration,1))
    y_Moon = zeros((duration,1))
    z_Moon = zeros((duration,1))
    r_Moon = zeros((duration,3))
    r_MATS_2_Moon = zeros((duration,3))
    r_MATS_2_Moon_norm = zeros((duration,3))
    Moon_r_orbital_plane = zeros((duration,3))
    Moon_r_H_offset_plane = zeros((duration,3))
    Moon_vert_offset = zeros((duration,1))
    Moon_hori_offset = zeros((duration,1))
    angle_between_orbital_plane_and_moon = zeros((duration,1))
    Moon_list = []
    r_Moon_unit_vector = zeros((duration,3))
    
    
    
    "Constants"
    AU = 149597871 #km
    R_mean = 6371 #Earth radius
    U = 398600.4418 #Earth gravitational parameter
    FOV_altitude = Mode200_calculator_defaults()['default_pointing_altitude']/1000  #Altitude at which MATS center of FOV is looking
    Logger.info('FOV_altitude set to [km]: '+str(FOV_altitude))
    pointing_adjustment = 3 #Angle in degrees that the pointing can be adjusted
    V_FOV = Mode200_calculator_defaults()['V_FOV'] #0.91 is actual V_FOV
    H_FOV = Mode200_calculator_defaults()['H_FOV']  #5.67 is actual H_FOV
    Logger.info('V_FOV set to [degrees]: '+str(V_FOV))
    Logger.info('H_FOV set to [degrees]: '+str(H_FOV))
    V_offset = 0
    H_offset = 0
    Moon_orbital_period = 3600*24*27.32
    
    
    t=0
    
    current_time = date
    
    Logger.info('')
    Logger.info('Start of simulation for Mode200')
    
    while(current_time < date+ephem.second*duration):
        
        MATS.compute(current_time)
        Moon.compute(current_time)
        
        
        (lat_MATS[t],long_MATS[t],altitude_MATS[t],g_ra_MATS[t],g_dec_MATS[t])= (
        MATS.sublat,MATS.sublong,MATS.elevation/1000,MATS.g_ra,MATS.g_dec)
        
        R = lat_2_R(lat_MATS[t])
        
        z_MATS[t] = sin(g_dec_MATS[t])*(altitude_MATS[t]+R)
        x_MATS[t] = cos(g_dec_MATS[t])*(altitude_MATS[t]+R)* cos(g_ra_MATS[t])
        y_MATS[t] = cos(g_dec_MATS[t])*(altitude_MATS[t]+R)* sin(g_ra_MATS[t])
       
        r_MATS[t,0:3] = [x_MATS[t], y_MATS[t], z_MATS[t]]
        r_MATS_unit_vector[t] = r_MATS[t]/norm(r_MATS[t])
        
        
        #Semi-Major axis of MATS, assuming circular orbit
        MATS_p[t] = norm(r_MATS[t,0:3])
        
        #Orbital Period of MATS
        MATS_P[t] = 2*pi*sqrt(MATS_p[t]**3/U)
        
        #Estimated pitch angle for MATS pointing
        pitch_array[t]= array(arccos((R_mean+FOV_altitude)/(R+altitude_MATS[t]))/pi*180)
        pitch = pitch_array[t][0]
        
        (g_ra_Moon[t],g_dec_Moon[t],distance_Moon[t])= (Moon.g_ra,Moon.g_dec,Moon.earth_distance*AU)
        
        z_Moon[t] = sin(g_dec_Moon[t]) * distance_Moon[t]
        x_Moon[t] = cos(g_dec_Moon[t])*cos(g_ra_Moon[t]) * distance_Moon[t]
        y_Moon[t] = cos(g_dec_Moon[t])*sin(g_ra_Moon[t]) * distance_Moon[t]
       
        r_Moon[t,0:3] = [x_Moon[t], y_Moon[t], z_Moon[t]]
        r_Moon_unit_vector[t,0:3] = r_Moon[t,0:3]/norm(r_Moon[t,0:3])
        
        r_MATS_2_Moon[t] = r_Moon[t]-r_MATS[t]
        r_MATS_2_Moon_norm[t] = r_MATS_2_Moon[t]/norm(r_MATS_2_Moon[t])
        
        if( t*timestep % log_timestep == 0 ):
            Logger.debug('')
            Logger.debug('log_timestep: '+str(log_timestep))
            Logger.debug('timestep: '+str(timestep))
            Logger.debug('t (loop iteration number): '+str(t))
            Logger.debug('Current time: '+str(current_time))
            Logger.debug('Semimajor axis in km: '+str(MATS_p[t]))
            Logger.debug('Orbital Period in s: '+str(MATS_P[t]))
            Logger.debug('Vector to MATS [km]: '+str(r_MATS[t,0:3]))
            Logger.debug('Latitude in radians: '+str(lat_MATS[t]))
            Logger.debug('Longitude in radians: '+str(long_MATS[t]))
            Logger.debug('Altitude in km: '+str(altitude_MATS[t]))
            Logger.debug('FOV pitch in degrees: '+str(pitch))
        
        if(t != 0):
            
            
            ############# Calculations of orbital and pointing vectors ############
            "Vector normal to the orbital plane of MATS"
            normal_orbit[t,0:3] = cross(r_MATS[t],r_MATS[t-1])
            normal_orbit[t,0:3] = normal_orbit[t,0:3] / norm(normal_orbit[t,0:3])
            
            "Rotate 'vector to MATS', to represent pointing direction, includes vertical offset change"
            rot_mat = rot_arbit(-pi/2+(-pitch+V_offset)/180*pi, normal_orbit[t,0:3])
            r_FOV[t,0:3] = (r_MATS[t] @ rot_mat)
            
            "Rotate 'vector to MATS', to represent a vector normal to the H-offset pointing plane, includes vertical offset change (Parallax is negligable)"
            rot_mat = rot_arbit((-pitch+V_offset)/180*pi, normal_orbit[t,0:3])
            normal_H_offset[t,0:3] = (r_MATS[t] @ rot_mat) /2
            normal_H_offset_unit_vector[t,0:3] = normal_H_offset[t,0:3] / norm(normal_H_offset[t,0:3])
            
            ############# End of Calculations of orbital and pointing vectors #####
            
            "Project 'r_MATS_2_Moon' ontop pointing H-offset and orbital plane"
            Moon_r_orbital_plane[t] = r_MATS_2_Moon_norm[t] - dot(r_MATS_2_Moon_norm[t],normal_orbit[t]) * normal_orbit[t]
            Moon_r_H_offset_plane[t] = r_MATS_2_Moon_norm[t] - dot(r_MATS_2_Moon_norm[t],normal_H_offset_unit_vector[t]) * normal_H_offset_unit_vector[t]
            
            
            "Dot product to get the Vertical and Horizontal angle offset of the Moon"
            Moon_vert_offset[t] = arccos(dot(r_FOV[t],Moon_r_orbital_plane[t]) / (norm(r_FOV[t])*norm(Moon_r_orbital_plane[t]))) /pi*180
            Moon_hori_offset[t] = arccos(dot(r_FOV[t],Moon_r_H_offset_plane[t]) / (norm(r_FOV[t])*norm(Moon_r_H_offset_plane[t]))) /pi*180
            
            "Get the offset angle sign correct"
            if( dot(cross(r_FOV[t],Moon_r_orbital_plane[t]),normal_orbit[t,0:3]) > 0 ):
                Moon_vert_offset[t] = -Moon_vert_offset[t]
            if( dot(cross(r_FOV[t],Moon_r_H_offset_plane[t]),normal_H_offset[t]) > 0 ):
                Moon_hori_offset[t] = -Moon_hori_offset[t]
            
            
            "Angle between orbital plane and moon"
            angle_between_orbital_plane_and_moon[t] = arccos( dot(r_MATS_2_Moon_norm[t], Moon_r_orbital_plane[t]) / norm(Moon_r_orbital_plane[t])) /pi*180
            
            
            if( t*timestep % log_timestep == 0 ):
                Logger.debug('angle_between_orbital_plane_and_moon [degrees]: '+str(angle_between_orbital_plane_and_moon[t]))
                Logger.debug('Moon_vert_offset [degrees]: '+str(Moon_vert_offset[t]))
                Logger.debug('Moon_hori_offset [degrees]: '+str(Moon_hori_offset[t]))
                Logger.debug('normal_orbit: '+str(normal_orbit[t,0:3]))
                Logger.debug('normal_H_offset: '+str(normal_H_offset[t,0:3]))
                Logger.debug('r_FOV [km]: '+str(r_FOV[t,0:3]))
        
            
            #print('angle_between_orbital_plane_and_moon = ' + str(angle_between_orbital_plane_and_moon[t]))
            
            "Save data when Moon is visible in specified FOV. "
            #if(abs(Moon_vert_offset[t]) <= timestep/MATS_P[t]*360 and abs(Moon_hori_offset[t]) < H_FOV/2):
            if(abs(Moon_vert_offset[t]) <= V_FOV/2 and abs(Moon_hori_offset[t]) < H_FOV/4):
                
                Logger.debug('')
                Logger.debug('!!!!!!!!Moon visible!!!!!!!!!!')
                Logger.debug('angle_between_orbital_plane_and_moon [degrees]: '+str(angle_between_orbital_plane_and_moon[t]))
                Logger.debug('Moon_vert_offset [degrees]: '+str(Moon_vert_offset[t]))
                Logger.debug('Moon_hori_offset [degrees]: '+str(Moon_hori_offset[t]))
                Logger.debug('normal_orbit: '+str(normal_orbit[t,0:3]))
                Logger.debug('normal_H_offset: '+str(normal_H_offset[t,0:3]))
                Logger.debug('r_FOV: '+str(r_FOV[t,0:3]))
                Logger.debug('')
                
                Moon_list.append({ 'Date': str(current_time), 'V-offset': Moon_vert_offset[t], 'H-offset': Moon_hori_offset[t], 
                                  'long_MATS': float(long_MATS[t]/pi*180), 'lat_MATS': float(lat_MATS[t]/pi*180)})
                current_time = ephem.Date(current_time+ephem.second*MATS_P[t]/2)
                
            
        
        "To be able to make time skips when the moon is far outside the orbital plane of MATS"
        if( angle_between_orbital_plane_and_moon[t] > H_FOV/2):
            t= t + 1
            current_time = ephem.Date(current_time+ephem.second * H_FOV/4 / 360 * Moon_orbital_period)
            #if( t*timestep % floor(log_timestep/400) == 0 ):
            Logger.info('Moon currently not visible -> jump ahead')
            Logger.info('current_time is: '+str(current_time))
        else:
            t= t + 1
            current_time = ephem.Date(current_time+ephem.second*timestep)
            
        
        
    Logger.info('End of simulation for Mode200')
    Logger.info('Moon_list: '+str(Moon_list))
    
    
    ########################## Optional plotter ###########################################
    
    from mpl_toolkits.mplot3d import axes3d
    from pylab import figure
    
    "Orbital points to plot"
    points_2_plot_start = 0#0*24*120
    points_2_plot = points_2_plot_start+1000
    
    "Plotting of orbit and FOV"
    fig = figure(1)
    ax = fig.add_subplot(111,projection='3d')
    ax.set_xlim3d(-1, 1)
    ax.set_ylim3d(-1, 1)
    ax.set_zlim3d(-1, 1)
    
    ax.scatter(r_MATS_unit_vector[points_2_plot_start:points_2_plot,0],r_MATS_unit_vector[points_2_plot_start:points_2_plot,1],r_MATS_unit_vector[points_2_plot_start:points_2_plot,2])
    ax.scatter(r_Moon_unit_vector[points_2_plot_start:points_2_plot,0],r_Moon_unit_vector[points_2_plot_start:points_2_plot,1],r_Moon_unit_vector[points_2_plot_start:points_2_plot,2])
    
    
    ########################### END of Optional plotter ########################################
    
    
    return Moon_list
Beispiel #16
0
def  q2tg( q ):
    global fz
    if not fz:
        qq = q
        q=q0

    slack = 1.0/1000
    t0  = 10.7/1000 #10.9124/1000
    P   = mm_array(5.725,13.215)
    PA  = mm_array(10.198,-2.0)
    B   = mm_array(15.087,5.585)
    C   = mm_array(51.43,3.878)
    D   = mm_array(60,0)
    E   = mm_array(-6.9,41)
    W   = mm_array(17.5,-6)

    rp = 4.0/1000    # POM is 3.96
    rb = 3.2/2/1000  # metal is 3.175/2, but loose, then tendon
    rc = rb
    rd = 3.1/1000
    qd2= -p.pi       # Abitrary.  Needs to be enough to stay wrapped.
    re0= 5.4/1000
    re1= 3.2/1000

    beta = twoDang(B)
    AB = twoDmag_ang(B,q+beta)
    PB = PA+AB
    gamma = twoDang(C)
    AC = twoDmag_ang(C,q+gamma)
    BC = AC-AB
    delta = twoDang(D)
    AD = twoDmag_ang(D,q+delta)
    CD = AD-AC
    DE = E
    WA = W
    WE = WA+AD+DE
    g = 2*WE[0]

    qp2 = twoDang(PB) + p.arccos((rp+rb)/p.norm(PB))
    fPB = hypleg(PB,rp+rb)
    qb1 = qp2 + p.pi

    fBC = p.norm(BC)
    qb2 = twoDang(BC)+3*p.pi/2
    sB  = rb*(qb2-qb1)

    qc1 = qb2
    qc2 = twoDang(CD) + 2*p.pi - p.arccos((rc+rd)/p.norm(CD))
    fCD = hypleg(CD,rc+rd)
    sC  = rc*(qc2-qc1)
    qd1 = qc2 - p.pi
    sD  = rd*(qd1-qd2)

    fBD = fPB + sB + fBC + sC + fCD + sD

    if not fz:
        # COMPUTE TOTAL TENDON LENGTH AT OPEN GRIPPER
        TP   = P+p.array([0.0,slack])
        fTP  = hypleg(TP,rp)
        qp1  = twoDang(TP) + p.pi - p.arccos(rp/p.norm(TP))
        sP   = rp*(qp1-qp2)
        fz   = fTP + sP + fBD
        # OUTPUT INFO ABOUT START POINT
        print ("t0=%.4f, TPz=[%.4f,%.4f], fTPz=%.4f, qp1=%.1f, fz=%.4f"%(t0,TP[0],TP[1],fTP,qp1*R2D,fz))

    # APPROX qp1 as constant
    qp1_approx = 173.0 * D2R
    qp1 = qp1_approx
    sP  = rp*(qp1-qp2)
    P1x = rp*p.cos(qp1)
    P1y = rp*p.sin(qp1)
    fTP = fz-sP-fBD
    fTPx = P[0] + P1x
    fTPy = hypleg(fTP,fTPx)
    t = P[1] + t0 + slack + P1y - fTPy

    # PLOT THE "SKELETON" OF IMPORTANT POINTS TO SANITY CHECK 
    skel = propkin([[0.0,t-t0],P+p.array([0.0,t0-t]),PA,AB,BC,CD,DE])
    p.figure(10); p.axis("equal")
    p.plot(skel[0,:],skel[1,:])

#    ####################
#    # FORCES FOR SPRING
#    Ft  = 1.0  # unit force
#
#    Fb  = twoDmag_ang( 2*Ft * p.sin((qb2-qb1)/2), (qb2+qb1)/2 - p.pi)
#    TQb = p.cross(AB,Fb)
#
#    Fc  = twoDmag_ang( 2*Ft * p.sin((qc2-qc1)/2), (qc2+qc1)/2 - p.pi)
#    TQc = p.cross(AC,Fc)
#
#    # NOTE: NET TORQUE ABOUT DISTAL IS ZERO.
#    # WE DO NOT SOLVE TORQUE ABOUT DISTAL PROBLEM.
#    # REACTION FORCES ON PROXIMAL LINK AXLE CAUSE TORQUES ON PROXIMAL
#
#    # FLEXOR TENDON FORCE ON DISTAL, TRANSFERED TO AXLE
#    Ff1 = twoDmag_ang( Ft, qd1 + p.pi/2 )
#    TQf = p.cross(AD,Ff1)
#
#    # SPRING TENDON FORCE ON DISTAL, TRANSFERED TO AXLE
#    Fs  = 1.0  # unit force
#    Fe1 = twoDmag_ang( Fs, q + p.arcsin((re0-re1)/p.norm(AD)) + p.pi )
#    TQFe= p.cross(AD,Fe1)
#
#    Ft_per_Fs = -TQFe/(TQb + TQc + TQf)

    ######################
    # Moment arm for proximal
    PP1 = twoDmag_ang( rp, qp1 )
    AB1 = AB + twoDmag_ang( rb, qb1 )
    PB1 = PA + AB1
    dirB1P1 = (PP1 - PB1)/p.norm(PP1 - PB1)
    mF = p.cross( AB1, dirB1P1 )

    return (t,q,g, mF)
Beispiel #17
0
filename = expname + '.profiles'
output = open(filename, 'w')
dc = ReadDetCal()
first_line = '# get_profile_data file'
dc.read_detcal(detcal_input, output, first_line)

# create array of detector centers for later use
det_center = pylab.zeros((dc.nod, 3))
det_base = pylab.zeros((dc.nod, 3))
det_up = pylab.zeros((dc.nod, 3))
normal = pylab.zeros((dc.nod, 3))
for i in range(dc.nod):
    det_center[i] = [dc.centerX[i], dc.centerY[i], dc.centerZ[i]]
    det_base[i] = [dc.baseX[i], dc.baseY[i], dc.baseZ[i]]
    det_up[i] = [dc.upX[i], dc.upY[i], dc.upZ[i]]
    normal[i] = pylab.cross(det_base[i], det_up[i])

# Begin for loop through the runs  ------------------------------------
for n in range(number_of_runs):
    nrun = run_numbers[n]
    srun = str(nrun)
    # Open matrix file
    orient_fname = expname + '_' + srun + '.mat'
    UBinput = open(orient_fname, 'r')

    # Initialize UB_IPNS matrix
    UB_IPNS = pylab.zeros(
        (3,
         3))  # Although this is SNS data, the coordinate convention are IPNS.
    print '\n Input from matrix file ' + orient_fname + ':\n'
def Mode120_date_calculator():
    #if(True):

    Logger = logging.getLogger(Logger_name())
    log_timestep = 3600

    "Simulation length and timestep"

    duration = Timeline_params()['duration']
    Logger.info('Duration set to: ' + str(duration) + ' s')

    timestep = Mode120_calculator_defaults()['timestep']  #In seconds
    Logger.info('timestep set to: ' + str(timestep) + ' s')
    timesteps = int(floor(duration / timestep))

    date = Timeline_params()['start_time']
    Logger.info('date set to: ' + str(date))

    "Get relevant stars"
    result = Vizier(columns=['all'], row_limit=200).query_constraints(
        catalog='I/239/hip_main', Vmag=Mode120_calculator_defaults()['Vmag'])
    star_cat = result[0]
    ROWS = star_cat[0][:].count()
    stars = []
    stars_dec = zeros((ROWS, 1))
    stars_ra = zeros((ROWS, 1))

    "Insert stars into Pyephem"
    for t in range(ROWS):
        s = "{},f|M|F7,{},{},{},2000"
        s = s.format(star_cat[t]['HIP'], deg2HMS(ra=star_cat[t]['_RA.icrs']),
                     deg2HMS(dec=star_cat[t]['_DE.icrs']), star_cat[t]['Vmag'])
        stars.append(ephem.readdb(s))
        stars[t].compute(epoch='2018')
        stars_dec[t] = stars[t].dec
        stars_ra[t] = stars[t].ra

    Logger.debug('List of stars used: ' + str(star_cat))

    "Calculate unit-vectors of stars"
    stars_x = cos(stars_dec) * cos(stars_ra)
    stars_y = cos(stars_dec) * sin(stars_ra)
    stars_z = sin(stars_dec)
    stars_r = array([stars_x, stars_y, stars_z])
    stars_r = stars_r.transpose()

    "Prepare the excel file output"
    star_list_excel = []
    star_list_excel.append(['Name;'])
    star_list_excel.append(['t1;'])
    star_list_excel.append(['t2;'])
    star_list_excel.append(['long1;'])
    star_list_excel.append(['lat1;'])
    star_list_excel.append(['long2;'])
    star_list_excel.append(['lat2;'])
    star_list_excel.append(['mag;'])
    star_list_excel.append(['H_offset;'])
    star_list_excel.append(['V_offset;'])
    star_list_excel.append(['H_offset2;'])
    star_list_excel.append(['V_offset2;'])
    star_list_excel.append(['e_Hpmag;'])
    star_list_excel.append(['Hpscat;'])
    star_list_excel.append(['o_Hpmag;'])
    star_list_excel.append(['Classification;'])

    "Prepare the output"
    star_list = []

    "Pre-allocate space"
    lat_MATS = zeros((timesteps, 1))
    long_MATS = zeros((timesteps, 1))
    altitude_MATS = zeros((timesteps, 1))
    g_ra_MATS = zeros((timesteps, 1))
    g_dec_MATS = zeros((timesteps, 1))
    x_MATS = zeros((timesteps, 1))
    y_MATS = zeros((timesteps, 1))
    z_MATS = zeros((timesteps, 1))
    r_MATS = zeros((timesteps, 3))
    r_FOV = zeros((timesteps, 3))
    r_FOV_unit_vector = zeros((timesteps, 3))
    r_FOV_norm = zeros((timesteps, 3))
    r_azi_norm = zeros((timesteps, 3))
    stars_r_V_offset_plane = zeros((ROWS, 3))
    stars_r_H_offset_plane = zeros((ROWS, 3))
    stars_vert_offset = zeros((timesteps, ROWS))
    stars_hori_offset = zeros((timesteps, ROWS))
    stars_offset = zeros((timesteps, ROWS))
    normal_orbital = zeros((timesteps, 3))
    r_V_offset_normal = zeros((timesteps, 3))
    r_H_offset_normal = zeros((timesteps, 3))
    pitch_sensor_array = zeros((timesteps, 1))
    star_counter = 0
    spotted_star_name = []
    spotted_star_timestamp = []
    spotted_star_timecounter = []
    skip_star_list = []
    MATS_p = zeros((timesteps, 1))
    MATS_P = zeros((timesteps, 1))

    angle_between_orbital_plane_and_star = zeros((timesteps, ROWS))

    "Constants"
    R_mean = 6371  #Earth radius
    Logger.info('Earth radius used [km]: ' + str(R_mean))

    U = 398600.4418  #Earth gravitational parameter

    FOV_altitude = Mode120_calculator_defaults(
    )['default_pointing_altitude'] / 1000  #Altitude at which MATS center of FOV is looking
    Logger.info('FOV_altitude set to [km]: ' + str(FOV_altitude))

    pointing_adjustment = 3  #Angle in degrees that the pointing can be adjusted
    V_FOV = Mode120_calculator_defaults()['V_FOV']  #0.91 is actual V_FOV
    H_FOV = Mode120_calculator_defaults()['H_FOV']  #5.67 is actual H_FOV
    Logger.info('V_FOV set to [degrees]: ' + str(V_FOV))
    Logger.info('H_FOV set to [degrees]: ' + str(H_FOV))

    pitch_offset_angle = 0
    yaw_offset_angle = 0

    Logger.info('TLE used: ' + getTLE()[0] + getTLE()[1])
    MATS = ephem.readtle('MATS', getTLE()[0], getTLE()[1])

    Logger.info('')
    Logger.info('Start of simulation of MATS for Mode120')
    ################## Start of Simulation ########################################
    "Loop and calculate the relevant angle of each star to each direction of MATS's FOV"
    for t in range(timesteps):

        current_time = ephem.Date(date + ephem.second * timestep * t)

        MATS.compute(current_time)

        (lat_MATS[t], long_MATS[t], altitude_MATS[t], g_ra_MATS[t],
         g_dec_MATS[t]) = (MATS.sublat, MATS.sublong, MATS.elevation / 1000,
                           MATS.g_ra, MATS.g_dec)

        R = lat_2_R(lat_MATS[t])

        z_MATS[t] = sin(g_dec_MATS[t]) * (altitude_MATS[t] + R)
        x_MATS[t] = cos(g_dec_MATS[t]) * (altitude_MATS[t] + R) * cos(
            g_ra_MATS[t])
        y_MATS[t] = cos(g_dec_MATS[t]) * (altitude_MATS[t] + R) * sin(
            g_ra_MATS[t])

        r_MATS[t, 0:3] = [x_MATS[t], y_MATS[t], z_MATS[t]]

        #Semi-Major axis of MATS, assuming circular orbit
        MATS_p[t] = norm(r_MATS[t, 0:3])

        #Orbital Period of MATS
        MATS_P[t] = 2 * pi * sqrt(MATS_p[t]**3 / U)

        #Estimated pitch or elevation angle for MATS pointing
        pitch_sensor_array[t] = array(
            arccos(
                (R_mean + FOV_altitude) / (R + altitude_MATS[t])) / pi * 180)
        pitch_sensor = pitch_sensor_array[t][0]

        if (t * timestep % log_timestep == 0):
            Logger.debug('')
            Logger.debug('log_timestep: ' + str(log_timestep))
            Logger.debug('timestep: ' + str(timestep))
            Logger.debug('t (loop iteration number): ' + str(t))
            Logger.debug('Current time: ' + str(current_time))
            Logger.debug('Semimajor axis in km: ' + str(MATS_p[t]))
            Logger.debug('Orbital Period in s: ' + str(MATS_P[t]))
            Logger.debug('Vector to MATS [km]: ' + str(r_MATS[t, 0:3]))
            Logger.debug('Latitude in radians: ' + str(lat_MATS[t]))
            Logger.debug('Longitude in radians: ' + str(long_MATS[t]))
            Logger.debug('Altitude in km: ' + str(altitude_MATS[t]))
            Logger.debug('FOV pitch in degrees: ' + str(pitch_sensor))

        if (t != 0):

            ############# Calculations of orbital and pointing vectors ############
            "Vector normal to the orbital plane of MATS"
            normal_orbital[t, 0:3] = cross(r_MATS[t], r_MATS[t - 1])
            normal_orbital[t, 0:3] = normal_orbital[t, 0:3] / norm(
                normal_orbital[t, 0:3])

            "Rotate 'vector to MATS', to represent pointing direction, includes vertical offset change (Parallax is negligable)"
            rot_mat = rot_arbit(
                -pi / 2 + (-pitch_sensor + pitch_offset_angle) / 180 * pi,
                normal_orbital[t, 0:3])
            r_FOV[t, 0:3] = (r_MATS[t] @ rot_mat) / 2

            "Rotate yaw of pointing direction, meaning to rotate around the vector to MATS"
            rot_mat = rot_arbit(yaw_offset_angle / 180 * pi, r_MATS[t, 0:3])
            r_FOV[t, 0:3] = (r_FOV[t, 0:3] @ rot_mat)
            r_FOV_unit_vector[t, 0:3] = r_FOV[t, 0:3] / norm(r_FOV[t, 0:3])
            '''Rotate 'vector to MATS', to represent vector normal to satellite H-offset plane,
            which will be used to project stars onto it which allows the H-offset of stars to be found'''
            rot_mat = rot_arbit((-pitch_sensor) / 180 * pi,
                                normal_orbital[t, 0:3])
            r_H_offset_normal[t, 0:3] = (r_MATS[t] @ rot_mat)
            r_H_offset_normal[t, 0:3] = r_H_offset_normal[t, 0:3] / norm(
                r_H_offset_normal[t, 0:3])

            "If pointing direction has a Yaw defined, Rotate yaw of normal to pointing direction H-offset plane, meaning to rotate around the vector to MATS"
            rot_mat = rot_arbit(yaw_offset_angle / 180 * pi, r_MATS[t, 0:3])
            r_H_offset_normal[t, 0:3] = (r_H_offset_normal[t, 0:3] @ rot_mat)
            r_H_offset_normal[t, 0:3] = r_H_offset_normal[t, 0:3] / norm(
                r_H_offset_normal[t, 0:3])

            "Rotate orbital plane normal to make it into pointing V-offset plane normal"
            r_V_offset_normal[t, 0:3] = (normal_orbital[t, 0:3] @ rot_mat)
            r_V_offset_normal[t, 0:3] = r_V_offset_normal[t, 0:3] / norm(
                r_V_offset_normal[t, 0:3])

            if (t * timestep % log_timestep == 0 or t == 1):
                Logger.debug('Pointing direction of FOV: ' +
                             str(r_FOV_unit_vector[t, 0:3]))
                Logger.debug('Orthogonal direction to H-offset plane: ' +
                             str(r_H_offset_normal[t, 0:3]))
                Logger.debug('Orthogonal direction to V-offset plane: ' +
                             str(r_V_offset_normal[t, 0:3]))
                Logger.debug('Orthogonal direction to the orbital plane: ' +
                             str(normal_orbital[t, 0:3]))
                Logger.debug('')

#            '''Rotate 'vector to MATS', to represent vector normal to satellite yaw plane,
#            which will be used to rotate the yaw of the pointing'''
#            rot_mat = rot_arbit((-pitch_sensor)/180*pi, normal_orbital[t,0:3])
#            r_azi_norm[t,0:3] = (r_MATS[t] @ rot_mat)
#            r_azi_norm[t,0:3] = r_azi_norm[t,0:3] / norm(r_azi_norm[t,0:3])
#
#            "Rotate horizontal offset of pointing direction, around satellite yaw plane"
#            rot_mat = rot_arbit(yaw_offset_angle/180*pi, r_azi_norm[t,0:3])
#            r_FOV[t,0:3] = (r_FOV[t,0:3] @ rot_mat)
#            r_FOV_unit_vector[t,0:3] = r_FOV[t,0:3]/norm(r_FOV[t,0:3])/2
#
#            "Rotate orbital plane normal to match pointing V-offset plane normal"
#            r_V_offset_normal[t,0:3] = (normal_orbital[t,0:3] @ rot_mat)
#
#            '''Rotate pointing vector 90 degrees in the pointing elevation plane to get a vector,
#            which is normal to pointing azimuth plane'''
#            rot_mat = rot_arbit(pi/2, r_V_offset_normal[t,0:3])
#            r_FOV_norm[t,0:3] = (r_FOV[t,0:3] @ rot_mat)
#            r_FOV_norm[t,0:3] = r_FOV_norm[t,0:3] / norm(r_FOV_norm[t,0:3])

############# End of Calculations of orbital and pointing vectors #####

###################### Star-mapper ####################################

            "Check position of stars relevant to pointing direction"
            for x in range(ROWS):

                "Skip star if it is not visible during this epoch"
                if (stars[x].name in skip_star_list):

                    continue

                "Check if a star has already been spotted during this orbit."
                if (stars[x].name in spotted_star_name):
                    '''Check if not enough time has passed so that the star has not left FOV'''
                    if ((current_time -
                         spotted_star_timestamp[spotted_star_name.index(
                             stars[x].name)]) < ephem.second *
                        (V_FOV * 2 * MATS_P[t] / 360)):
                        '''Check if enough time has passed so that the star is roughly in the same
                        direction as original FOV and save lat,long, Hoffset, Voffset and time. Otherwise skip star.'''
                        if ((t -
                             spotted_star_timecounter[spotted_star_name.index(
                                 stars[x].name)]) * timestep == around(
                                     MATS_P[t] *
                                     (pitch_offset_angle + V_FOV / 2) / 360)):

                            "Project 'star vectors' ontop pointing H-offset and V-offset plane"
                            stars_r_V_offset_plane[x] = stars_r[0][x] - dot(
                                stars_r[0][x], r_V_offset_normal[
                                    t, 0:3]) * r_V_offset_normal[t, 0:3]

                            stars_r_H_offset_plane[x] = stars_r[0][x] - (
                                (dot(stars_r[0][x], r_H_offset_normal[t]) *
                                 r_H_offset_normal[t]) /
                                ((norm(r_H_offset_normal[t]))**2))

                            "Dot product to get the Vertical and Horizontal angle offset of the star in the FOV"
                            stars_vert_offset[t][x] = arccos(
                                dot(r_FOV[t], stars_r_V_offset_plane[x]) /
                                (norm(r_FOV[t]) *
                                 norm(stars_r_V_offset_plane[x]))) / pi * 180
                            stars_hori_offset[t][x] = arccos(
                                dot(r_FOV[t], stars_r_H_offset_plane[x]) /
                                (norm(r_FOV[t]) *
                                 norm(stars_r_H_offset_plane[x]))) / pi * 180

                            "Determine sign of off-set angle where positive V-offset angle is when looking at higher altitude"
                            if (dot(cross(r_FOV[t], stars_r_V_offset_plane[x]),
                                    r_V_offset_normal[t, 0:3]) > 0):
                                stars_vert_offset[t][
                                    x] = -stars_vert_offset[t][x]
                            if (dot(cross(r_FOV[t], stars_r_H_offset_plane[x]),
                                    r_H_offset_normal[t]) > 0):
                                stars_hori_offset[t][
                                    x] = -stars_hori_offset[t][x]

                            star_list_excel[2].append(str(current_time) + ';')
                            star_list_excel[5].append(
                                str(float(long_MATS[t] / pi * 180)) + ';')
                            star_list_excel[6].append(
                                str(float(lat_MATS[t] / pi * 180)) + ';')
                            star_list_excel[10].append(
                                str(stars_hori_offset[t][x]) + ';')
                            star_list_excel[11].append(
                                str(stars_vert_offset[t][x]) + ';')

                        continue

                        "If enough time has passed (half an orbit), the star can be removed from the exception list"
                    elif ((current_time -
                           spotted_star_timestamp[spotted_star_name.index(
                               stars[x].name)]) >= ephem.second *
                          (180 * MATS_P[t] / 360)):
                        spotted_star_timestamp.pop(
                            spotted_star_name.index(stars[x].name))
                        spotted_star_timecounter.pop(
                            spotted_star_name.index(stars[x].name))
                        spotted_star_name.remove(stars[x].name)

                "Total angle offset of the star compared to MATS's FOV"
                stars_offset[t][x] = arccos(
                    dot(r_FOV[t], stars_r[0][x]) /
                    (norm(r_FOV[t]) * norm(stars_r[0][x]))) / pi * 180

                "Project 'star vectors' ontop pointing H-offset and V-offset plane"
                stars_r_V_offset_plane[x] = stars_r[0][x] - (
                    dot(stars_r[0][x], r_V_offset_normal[t, 0:3]) *
                    r_V_offset_normal[t, 0:3])

                stars_r_H_offset_plane[x] = stars_r[0][x] - (
                    dot(stars_r[0][x], r_H_offset_normal[t]) *
                    r_H_offset_normal[t])

                "Dot product to get the Vertical and Horizontal angle offset of the star in the FOV"
                stars_vert_offset[t][x] = arccos(
                    dot(r_FOV[t], stars_r_V_offset_plane[x]) /
                    (norm(r_FOV[t]) *
                     norm(stars_r_V_offset_plane[x]))) / pi * 180
                stars_hori_offset[t][x] = arccos(
                    dot(r_FOV[t], stars_r_H_offset_plane[x]) /
                    (norm(r_FOV[t]) *
                     norm(stars_r_H_offset_plane[x]))) / pi * 180

                "Determine sign of off-set angle where positive V-offset angle is when looking at higher altitude"
                if (dot(cross(r_FOV[t], stars_r_V_offset_plane[x]),
                        r_V_offset_normal[t, 0:3]) > 0):
                    stars_vert_offset[t][x] = -stars_vert_offset[t][x]
                if (dot(cross(r_FOV[t], stars_r_H_offset_plane[x]),
                        r_H_offset_normal[t]) > 0):
                    stars_hori_offset[t][x] = -stars_hori_offset[t][x]

                "To be able to skip stars far outside the orbital plane of MATS"
                angle_between_orbital_plane_and_star[t][x] = arccos(
                    dot(stars_r[0][x], stars_r_V_offset_plane[x]) /
                    norm(stars_r_V_offset_plane[x])) / pi * 180

                "For first loop of stars, make exception list for stars not visible during this epoch"
                if (t == 1
                        and abs(angle_between_orbital_plane_and_star[t][x]) >
                        H_FOV / 2 + (duration * 2) / (365 * 24 * 3600) * 360):

                    Logger.debug(
                        'Skip star: ' + stars[x].name +
                        ', with H-offset of: ' +
                        str(angle_between_orbital_plane_and_star[t][x]) +
                        ' degrees')
                    skip_star_list.append(stars[x].name)
                    continue

                "Check if star is in FOV"
                if (abs(stars_vert_offset[t][x]) < V_FOV / 2
                        and abs(stars_hori_offset[t][x]) < H_FOV / 2):
                    #print('Star number:',stars[x].name,'is visible at',stars_vert_offset[t][x],'degrees VFOV and', \
                    #stars_hori_offset[t][x],'degrees HFOV','during',ephem.Date(current_time))

                    if (t % log_timestep == 0):
                        Logger.debug('Star: ' + stars[x].name +
                                     ', with H-offset: ' +
                                     str(stars_hori_offset[t][x]) +
                                     ' V-offset: ' +
                                     str(stars_vert_offset[t][x]) +
                                     ' in degrees is visible')

                    "Add the spotted star to the exception list and timestamp it"
                    spotted_star_name.append(stars[x].name)
                    spotted_star_timestamp.append(current_time)
                    spotted_star_timecounter.append(t)

                    "Log all relevent data for the star"
                    star_list_excel[0].append(stars[x].name + ';')
                    star_list_excel[1].append(str(current_time) + ';')
                    star_list_excel[3].append(
                        str(float(long_MATS[t] / pi * 180)) + ';')
                    star_list_excel[4].append(
                        str(float(lat_MATS[t] / pi * 180)) + ';')
                    star_list_excel[7].append(str(stars[x].mag) + ';')
                    star_list_excel[8].append(
                        str(stars_hori_offset[t][x]) + ';')
                    star_list_excel[9].append(
                        str(stars_vert_offset[t][x]) + ';')
                    star_list_excel[12].append(
                        str(star_cat[x]['e_Hpmag']) + ';')
                    star_list_excel[13].append(
                        str(star_cat[x]['Hpscat']) + ';')
                    star_list_excel[14].append(
                        str(star_cat[x]['o_Hpmag']) + ';')
                    star_list_excel[15].append(
                        str(star_cat[x]['SpType']) + ';')

                    "Log data of star relevant to filtering process"
                    star_list.append({
                        'Date':
                        str(current_time),
                        'V-offset':
                        stars_vert_offset[t][x],
                        'H-offset':
                        stars_hori_offset[t][x],
                        'long_MATS':
                        float(long_MATS[t] / pi * 180),
                        'lat_MATS':
                        float(lat_MATS[t] / pi * 180),
                        'Vmag':
                        stars[x].mag,
                        'Name':
                        stars[x].name
                    })

                    star_counter = star_counter + 1

            ######################### End of star_mapper #############################

    ########################## Optional plotter ###########################################
    '''
    from mpl_toolkits.mplot3d import axes3d
    
    "Orbital points to plot"
    points_2_plot_start = 0#0*24*120
    points_2_plot = points_2_plot_start+200
    
    "Plotting of orbit and FOV"
    fig = figure(1)
    ax = fig.add_subplot(111,projection='3d')
    ax.set_xlim3d(-7000, 7000)
    ax.set_ylim3d(-7000, 7000)
    ax.set_zlim3d(-7000, 7000)
    
    ax.scatter(x_MATS[points_2_plot_start:points_2_plot],y_MATS[points_2_plot_start:points_2_plot],z_MATS[points_2_plot_start:points_2_plot])
    ax.scatter(r_FOV[points_2_plot_start:points_2_plot,0],r_FOV[points_2_plot_start:points_2_plot,1],r_FOV[points_2_plot_start:points_2_plot,2])
    
    "Plotting of stars and FOV unit-vectors"
    fig = figure(2)
    ax = fig.add_subplot(111,projection='3d')
    ax.scatter(stars_r[0][:,0],stars_r[0][:,1],stars_r[0][:,2])
    ax.scatter(r_FOV_unit_vector[points_2_plot_start:points_2_plot,0],r_FOV_unit_vector[points_2_plot_start:points_2_plot,1],r_FOV_unit_vector[points_2_plot_start:points_2_plot,2])
    ax.scatter(r_V_offset_normal[points_2_plot_start:points_2_plot,0]/2, r_V_offset_normal[points_2_plot_start:points_2_plot,1]/2, r_V_offset_normal[points_2_plot_start:points_2_plot,2]/2)
    ax.scatter(normal_orbital[points_2_plot_start:points_2_plot,0]/2, normal_orbital[points_2_plot_start:points_2_plot,1]/2, normal_orbital[points_2_plot_start:points_2_plot,2]/2)
    ax.scatter(r_H_offset_normal[points_2_plot_start:points_2_plot,0]/2, r_H_offset_normal[points_2_plot_start:points_2_plot,1]/2, r_H_offset_normal[points_2_plot_start:points_2_plot,2]/2)
    '''
    ########################### END of Optional plotter ########################################

    "Write spotted stars to file"
    with open('MATS_Visible_Stars.csv', 'w', newline='') as write_file:
        writer = csv.writer(write_file, dialect='excel-tab')
        writer.writerows(star_list_excel)

    Logger.debug('Visible star list to be filtered:')
    Logger.debug(str(star_list))
    Logger.debug('')

    Logger.debug('Exit ' + str(__name__))
    Logger.debug('')

    return (star_list)
Beispiel #19
0
    def __init__(self, departurePlanet, arrivalPlanet, departureTimes, arrivalTimes, multiplier=86400,ignoreV=False):
        ''' 
            Generates a porkchop plot
            
            departurePlanet - reference to departure planet
            arrivalPlanet - reference to arrival planet
            departureTimes -  list of departure times
            arrivalTimes - list of arrival times
            multiplier - default 86400 = times are in earth days, set 1 for seconds
        '''
        if departurePlanet.ref != arrivalPlanet.ref:
            print "Lambert solver can only be used on objects with same reference"
            return
        
        mu = departurePlanet.ref.mu
        
        self.figure = figure()
        self.axis = self.figure.gca()
        mindv = 999999999999
        mindate = None
        Z = zeros((len(arrivalTimes),len(departureTimes)))
        for depi,deptime in enumerate(departureTimes):
            depsecs = deptime * multiplier
            dp,dv = departurePlanet.eph(depsecs)

            for arri, arrtime in enumerate(arrivalTimes):
                arrsecs = arrtime * multiplier
                if arrsecs < depsecs: continue
                ap,av = arrivalPlanet.eph(arrsecs)
                
                dt = arrsecs-depsecs
                # We always want prograde trajectories so..
                if cross(dp,ap)[2] < 0:
                    dt = -dt
                # Solve lambert
                lv1,lv2 = toolkit.lambert(dp,ap,dt,0,mu)
                
                if not ignoreV:
                    c3 =  norm(lv1-dv) + norm(lv2-av)
                else:
                    c3 = norm(lv1) + norm(lv2)
                print "c3",c3
                if isnan(c3) or c3 > 20000:
                    c3 = 0
                else:
                    if c3 < mindv:
                        mindv = c3
                        mindate = [deptime,arrtime]
                        mindvdv = lv1-dv
                        mindvav = lv2-av
                        
                Z[arri][depi] = c3
                print "v",Z[arri][depi] 
                
        Z = ma.masked_equal(Z,0) 
        self.contour = self.axis.contour(departureTimes,arrivalTimes,Z,colors="k")
        self.contourf = self.axis.contourf(departureTimes,arrivalTimes,Z)
        self.colorbar = self.figure.colorbar(self.contourf)
        
        self.axis.set_ylabel("Arrival day")
        self.axis.set_xlabel("Departure day")
        
        print "mindv",mindv,"m/s on departure",mindate[0],"and arrive",mindate[1]
        print "Departure dV",norm(mindvdv)
        print "Arrival dV",norm(mindvav)
        
        self.dv = [lv1,lv2]
Beispiel #20
0
def Mode120_date_calculator():
    """Subfunction, Simulates MATS FOV and stars.
    
    Determines when stars are entering the FOV at an vertical offset-angle equal to *#V-offset*, and also being 
    located at a horizontal off-set angle equal to less than *#H-offset*, when pointing at the LP located at an altitude equal to *#pointing_altitude*. \n
    
    (# as defined in the *Configuration File*). \n
    
    Saves the date and parameters regarding the spotting of a star.
    Also saves relevant data to an .csv file located in Output/.
    
    Arguments:
        
    Returns:
        SpottedStarList ((:obj:`list` of :obj:`dict`)) or (str): A list containing dictionaries containing parameters for each time a star is spotted.
    
    """
    
    Timeline_settings = OPT_Config_File.Timeline_settings()
    Mode120_settings = OPT_Config_File.Mode120_settings()
    
    ######################################################
    "Check how many times Mode120 have been scheduled"
    Mode120Iteration = _Globals.Mode120Iteration
    "Make the V_offset_Index go from 0 to len(Mode120_settings['V_offset'] for each time Mode120 is scheduled"
    V_offset_Index = (Mode120Iteration-1) % (len(Mode120_settings['V_offset']))
    
    "Constants"
    V_offset = Mode120_settings['V_offset'][V_offset_Index]
    H_offset = Mode120_settings['H_offset']
    
    pointing_altitude = Mode120_settings['pointing_altitude']/1000 
    yaw_correction = Timeline_settings['yaw_correction']
    
    Logger.debug('H_offset set to [degrees]: '+str(H_offset))
    Logger.debug('V_offset set to [degrees]: '+str(V_offset))
    Logger.debug('yaw_correction set to: '+str(yaw_correction))
    
    TLE = OPT_Config_File.getTLE()
    Logger.debug('TLE used: '+TLE[0]+TLE[1])
    
    TimeSkips = 0
    Timeskip = Mode120_settings['TimeSkip']
    
    ####################################################
    
    "Simulation length and timestep"
    log_timestep = Mode120_settings['log_timestep']
    Logger.debug('log_timestep: '+str(log_timestep))

    timestep = Mode120_settings['timestep'] #In seconds
    Logger.info('timestep set to: '+str(timestep)+' s')
    
    if( Mode120_settings['TimeToConsider'] <= Timeline_settings['duration']):
        duration = Mode120_settings['TimeToConsider']
    else:
        duration = Timeline_settings['duration']
    Logger.info('Duration set to: '+str(duration)+' s')
    
    timesteps = int(ceil(duration / timestep)) + 2
    Logger.info('Maximum number of timesteps set to: '+str(timesteps))
    
    timeline_start = ephem.Date(Timeline_settings['start_date'])
    initial_time = ephem.Date( timeline_start + ephem.second*Mode120_settings['freeze_start'] )
    current_time = initial_time
    Logger.info('Initial simulation date set to: '+str(initial_time))
    
    
    "Get relevant stars"
    result = Vizier(columns=['all'], row_limit=3000).query_constraints(catalog='I/239/hip_main',Vmag=Mode120_settings['Vmag'])
    star_cat = result[0]
    ROWS = star_cat[0][:].count()
    stars = []
    stars_dec = zeros((ROWS,1))
    stars_ra = zeros((ROWS,1))
    
    "Insert stars into Pyephem"
    for t in range(ROWS):
        s = "{},f|M|F7,{},{},{},2000/01/01 11:58:55.816"
        s = s.format(star_cat[t]['HIP'], deg2HMS(ra=star_cat[t]['_RA.icrs']), deg2HMS(dec=star_cat[t]['_DE.icrs']), star_cat[t]['Vmag'])
        stars.append(ephem.readdb(s))
        stars[t].compute(epoch='2000/01/01 11:58:55.816')
        stars_dec[t] = stars[t].dec
        stars_ra[t] = stars[t].ra
    
    Logger.debug('')
    Logger.debug('List of stars used: '+str(star_cat))
    Logger.debug('')
    
    "Calculate unit-vectors of stars"
    stars_x = cos(stars_dec)* cos(stars_ra)
    stars_y = cos(stars_dec)* sin(stars_ra)
    stars_z = sin(stars_dec)
    stars_r = array([stars_x,stars_y,stars_z])
    stars_r = stars_r.transpose()
    
    "Prepare the .csv file output"
    star_list_excel = []
    star_list_excel.append(['Name'])
    star_list_excel.append(['t1'])
    star_list_excel.append(['long'])
    star_list_excel.append(['lat'])
    star_list_excel.append(['mag'])
    star_list_excel.append(['H_offset'])
    star_list_excel.append(['V_offset'])
    star_list_excel.append(['e_Hpmag'])
    star_list_excel.append(['Hpscat'])
    star_list_excel.append(['o_Hpmag'])
    star_list_excel.append(['Classification'])
    star_list_excel.append(['Optical Axis Dec (ICRS J2000, eq)'])
    star_list_excel.append(['Optical Axis RA (ICRS J2000, eq)'])
    star_list_excel.append(['Star Dec (ICRS J2000, eq)'])
    star_list_excel.append(['Star RA (ICRS J2000, eq)'])
    
    "Prepare the output"
    SpottedStarList = []
    
    "Pre-allocate space"
    lat_MATS = zeros((timesteps,1))
    long_MATS = zeros((timesteps,1))
    optical_axis = zeros((timesteps,3))
    stars_r_V_offset_plane = zeros((ROWS,3))
    stars_r_H_offset_plane = zeros((ROWS,3))
    stars_vert_offset = zeros((timesteps,ROWS))
    stars_hori_offset = zeros((timesteps,ROWS))
    stars_offset = zeros((timesteps,ROWS))
    r_V_offset_normal = zeros((timesteps,3))
    r_H_offset_normal = zeros((timesteps,3))
    star_counter = 0
    spotted_star_name = []
    spotted_star_timestamp = []
    spotted_star_timecounter = []
    skip_star_list = []
    MATS_P = zeros((timesteps,1))
    
    Dec_optical_axis = zeros((timesteps,1))
    RA_optical_axis = zeros((timesteps,1))
    
    angle_between_orbital_plane_and_star = zeros((timesteps,ROWS))
    
    
    
    MATS_skyfield = api.EarthSatellite(TLE[0], TLE[1])
    
    t = 0
    
    Logger.info('')
    Logger.info('Start of simulation of MATS for Mode120')
    ################## Start of Simulation ########################################
    "Loop and calculate the relevant angle of each star to each direction of MATS's FOV"
    while( current_time-initial_time < ephem.second*duration):
        
        
        #current_time = ephem.Date(date+ephem.second*timestep*t)
        
        if( t*timestep % log_timestep == 0):
            LogFlag = True
        else:
            LogFlag = False
        
        Satellite_dict = Satellite_Simulator( 
                MATS_skyfield, current_time, Timeline_settings, pointing_altitude, LogFlag, Logger )
        
        MATS_P[t] = Satellite_dict['OrbitalPeriod [s]']
        lat_MATS[t] =  Satellite_dict['Latitude [degrees]']
        long_MATS[t] =  Satellite_dict['Longitude [degrees]']
        optical_axis[t] = Satellite_dict['OpticalAxis']
        Dec_optical_axis[t] = Satellite_dict['Dec_OpticalAxis [degrees]']
        RA_optical_axis[t] = Satellite_dict['RA_OpticalAxis [degrees]']
        r_H_offset_normal[t] = Satellite_dict['Normal2H_offset']
        r_V_offset_normal[t] = Satellite_dict['Normal2V_offset']
        
        OrbitalAngularVelocity = 360 / MATS_P[t]
        AngularChangePerTimestep = OrbitalAngularVelocity * timestep
        
        ###################### Star-mapper ####################################
        
        if(t != 0):
            "Check position of stars relevant to pointing direction"
            for x in range(ROWS):
                
                "Skip star if it is not visible during this epoch"
                if(stars[x].name in skip_star_list):
                    continue
                
                "Check if a star has already been spotted during this orbit."
                if( stars[x].name in spotted_star_name ):
                    
                    time_until_far_outside_of_FOV = ephem.second*(180*MATS_P[t]/360)
                    
                    "If enough time has passed (half an orbit), the star can be removed from the exception list"
                    if((current_time - spotted_star_timestamp[spotted_star_name.index(stars[x].name)]) >= time_until_far_outside_of_FOV):
                        spotted_star_timestamp.pop(spotted_star_name.index(stars[x].name))
                        spotted_star_timecounter.pop(spotted_star_name.index(stars[x].name))
                        spotted_star_name.remove(stars[x].name)
                    continue
                
                
                
                "Total angle offset of the star compared to MATS's FOV"
                stars_offset[t][x] = arccos(dot(optical_axis[t],stars_r[0][x]) / (norm(optical_axis[t]) * norm(stars_r[0][x]))) /pi*180
                
                "Project 'star vectors' ontop pointing H-offset and V-offset plane"
                stars_r_V_offset_plane[x] = stars_r[0][x] - (dot(stars_r[0][x],r_V_offset_normal[t,0:3]) * r_V_offset_normal[t,0:3])
                
                stars_r_H_offset_plane[x] = stars_r[0][x] - (dot(stars_r[0][x],r_H_offset_normal[t]) * r_H_offset_normal[t]) 
                
                "Dot product to get the Vertical and Horizontal angle offset of the star in the FOV"
                stars_vert_offset[t][x] = arccos(dot(optical_axis[t],stars_r_V_offset_plane[x]) / (norm(optical_axis[t]) * norm(stars_r_V_offset_plane[x]))) /pi*180
                stars_hori_offset[t][x] = arccos(dot(optical_axis[t],stars_r_H_offset_plane[x]) / (norm(optical_axis[t]) * norm(stars_r_H_offset_plane[x]))) /pi*180
                
                "Determine sign of off-set angle where positive V-offset angle is when looking at higher altitude"
                if( dot(cross(optical_axis[t],stars_r_V_offset_plane[x]),r_V_offset_normal[t,0:3]) > 0 ):
                    stars_vert_offset[t][x] = -stars_vert_offset[t][x]
                if( dot(cross(optical_axis[t],stars_r_H_offset_plane[x]),r_H_offset_normal[t]) > 0 ):
                    stars_hori_offset[t][x] = -stars_hori_offset[t][x]
                
                
                "To be able to skip stars far outside the orbital plane of MATS"
                if( t == 1 ):
                    "For first loop of stars, calculate angle between stars and orbital plane"
                    angle_between_orbital_plane_and_star[t][x] = arccos( dot(stars_r[0][x], stars_r_V_offset_plane[x]) / norm(stars_r_V_offset_plane[x])) /pi*180
                    
                    "Make exception list for stars not visible during this epoch (relativiely far outside of orbital plane)"
                    if( ( abs(angle_between_orbital_plane_and_star[t][x]) > H_offset+(duration)/(365*24*3600)*360 and yaw_correction == False ) or 
                       ( abs(angle_between_orbital_plane_and_star[t][x]) > H_offset + abs(Timeline_settings['yaw_amplitude']) + (duration)/(365*24*3600)*360 and yaw_correction == True )):
                        
                        Logger.debug('Skip star: '+stars[x].name+', with angle_between_orbital_plane_and_star of: '+str(angle_between_orbital_plane_and_star[t][x])+' degrees')
                        skip_star_list.append(stars[x].name)
                        continue
                
                
                "Check that the star is entering at V-offset degrees with a standard timestep and within the H-offset angle"
                if( V_offset - AngularChangePerTimestep  <= stars_vert_offset[t][x] <= V_offset and stars_vert_offset[t-1][x] > V_offset and abs(stars_hori_offset[t][x]) < H_offset):
                    
                    if( t % log_timestep == 0):
                        Logger.debug('Star: '+stars[x].name+', with H-offset: '+str(stars_hori_offset[t][x])+' V-offset: '+str(stars_vert_offset[t][x])+' in degrees is available')
                    
                    "Add the spotted star to the exception list and timestamp it"
                    spotted_star_name.append(stars[x].name)
                    spotted_star_timestamp.append(current_time)
                    spotted_star_timecounter.append(t) 
                    
                    
                    "Append all relevent data for the star"
                    star_list_excel[0].append(stars[x].name)
                    star_list_excel[1].append(str(current_time))
                    star_list_excel[2].append(str(float(long_MATS[t])))
                    star_list_excel[3].append(str(float(lat_MATS[t])))
                    star_list_excel[4].append(str(stars[x].mag))
                    star_list_excel[5].append(str(stars_hori_offset[t][x]))
                    star_list_excel[6].append(str(stars_vert_offset[t][x]))
                    star_list_excel[7].append(str(star_cat[x]['e_Hpmag']))
                    star_list_excel[8].append(str(star_cat[x]['Hpscat']))
                    star_list_excel[9].append(str(star_cat[x]['o_Hpmag']))
                    star_list_excel[10].append(str(star_cat[x]['SpType']))
                    star_list_excel[11].append(str(Dec_optical_axis[t]))
                    star_list_excel[12].append(str(RA_optical_axis[t]))
                    star_list_excel[13].append(str(stars_dec[x]/pi*180))
                    star_list_excel[14].append(str(stars_ra[x]/pi*180))
                    
                    "Log data of star relevant to filtering process"
                    SpottedStarList.append({ 'Date': str(current_time), 'V-offset': stars_vert_offset[t][x], 'H-offset': stars_hori_offset[t][x], 
                                      'long_MATS': float(long_MATS[t]), 'lat_MATS': float(lat_MATS[t]), 
                                      'Dec_optical_axis': Dec_optical_axis[t], 'RA_optical_axis': RA_optical_axis[t], 
                                      'Vmag': stars[x].mag, 'Name': stars[x].name, 'Dec': stars_dec[x]/pi*180, 'RA': stars_ra[x]/pi*180 })
                    
                    star_counter = star_counter + 1
                    
            ######################### End of star_mapper #############################
        
        "Increase Simulation Time with a timestep, or skip ahead if 1 orbit is completed"
        t += 1
        if( t*timestep > MATS_P[t-1]*(TimeSkips+1) ):
            current_time = ephem.Date(current_time+ephem.second*Timeskip)
            TimeSkips += 1
        else:
            current_time = ephem.Date(current_time+ephem.second*timestep)
        
        
    ########################## END OF SIMULATION ############################
    
    Logger.info('')
    Logger.info('End of simulation for Mode120')
    Logger.info('')
    
    "Write spotted stars to file"
    try:
        os.mkdir('Output')
    except:
        pass
    
    while(True):
        try:
            file_directory = os.path.join('Output',sys._getframe(1).f_code.co_name+'_Visible_Stars__'+_Globals.Config_File+'__V_offset'+str(V_offset)+'.csv')
            with open(file_directory, 'w', newline='') as write_file:
                writer = csv.writer(write_file, dialect='excel-tab')
                writer.writerows(star_list_excel)
            Logger.info('Available Stars data saved to: '+file_directory)
            #print('Available Stars data saved to: '+file_directory)
            break
        except PermissionError:
            Logger.error(file_directory+' cannot be overwritten. Please close it')
            data = input('Enter anything to try again or 1 to exit')
            if( data == '1'):
                sys.exit()
    
    Logger.debug('Visible star list to be filtered:')
    for x in range(len(SpottedStarList)):
        Logger.debug(str(SpottedStarList[x]))
    Logger.debug('')
    
    Logger.debug('Exit '+str(__name__))
    Logger.debug('')
    
    
    return(SpottedStarList)