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
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
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)
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
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
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
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
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))
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
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)
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)
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]
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)