args = parser.parse_args() start = get_J2000_epoch_offset(args.start_time) end = get_J2000_epoch_offset(args.end_time) config, elements = [], [ l for l in getattr(args, "tle-file").read().splitlines() if l.startswith("1") or l.startswith("2") ] for i in range(0, len(elements), 2): config.append( configure(prop_start=start, prop_initial_TLE=elements[i:i + 2], prop_end=end, prop_step=args.step_size, gravity_degree=-1, gravity_order=-1, ocean_tides_degree=-1, ocean_tides_order=-1, third_body_sun=False, third_body_moon=False, solid_tides_sun=False, solid_tides_moon=False, drag_model=DragModel.UNDEFINED, rp_sun=False)) try: for idx, obj in enumerate(propagate_orbits(config)): obj_id = elements[idx * 2][2:7] print(f"\nObject {obj_id}:") for m in obj.array: print(get_UTC_string(m.time), m.true_state) if (args.export_oem):
def predict(self): self.predict["state"] = "disabled" start = get_J2000_epoch_offset(self.start_time.get()) end = get_J2000_epoch_offset(self.end_time.get()) data, tle = {}, [ l for l in self.tle.get("0.0", "end-1c").splitlines() if l.startswith("1") or l.startswith("2") ] for f in [ "latitude", "longitude", "altitude", "fov_azimuth", "fov_elevation", "fov_aperture", "step_size" ]: data[f] = [ float(t.strip()) for t in getattr(self, f).get().split(",") ] if (f not in ["altitude", "step_size"]): data[f] = [d * Constant.DEGREE_TO_RAD for d in data[f]] cfg_list = [] sim_meas = len(data["latitude"]) <= 2 or len(data["latitude"]) != len( data["longitude"]) for i in range(0, len(tle), 2): cfg_list.append( configure(prop_start=start, prop_initial_TLE=tle[i:i + 2], prop_end=end, prop_step=data["step_size"][0], sim_measurements=sim_meas, gravity_degree=-1, gravity_order=-1, ocean_tides_degree=-1, ocean_tides_order=-1, third_body_sun=False, third_body_moon=False, solid_tides_sun=False, solid_tides_moon=False, drag_model=DragModel.UNDEFINED, rp_sun=False)) cfg_list[-1].output_flags |= OutputFlag.OUTPUT_ECLIPSE if (sim_meas): add_station(cfg_list[-1], "Sensor", data["latitude"][0], data["longitude"][0], data["altitude"][0], data["fov_azimuth"][0], data["fov_elevation"][0], data["fov_aperture"][0]) cfg_list[-1].measurements[MeasurementType.AZIMUTH].error[:] = [ 0.0 ] cfg_list[-1].measurements[ MeasurementType.ELEVATION].error[:] = [0.0] else: cfg_list[-1].geo_zone_lat_lon[:] = [ l for ll in zip(data["latitude"], data["longitude"]) for l in ll ] if (len(cfg_list)): i = 0 lookup = {0.0: "Sunlit", 0.5: "Penumbra", 1.0: "Umbra"} self.output.delete("0.0", tk.END) if (sim_meas): self.output_label[ "text"] = "UTC, Azimuth [deg], Elevation [deg]" else: self.output_label[ "text"] = "UTC, Latitude [deg], Longitude [deg], Altitude [m]" for o in propagate_orbits(cfg_list): self.output.insert(tk.END, f"\nObject {tle[i][2:7]}:\n") i += 2 for m in o.array: if (sim_meas): self.output.insert( tk.END, "{}: {:.5f}, {:.5f} ({})\n".format( get_UTC_string(m.time), (m.values[0] / Constant.DEGREE_TO_RAD + 360) % 360, m.values[1] / Constant.DEGREE_TO_RAD, lookup[m.true_state[-1]])) else: lla = pos_to_lla(Frame.GCRF, m.time, m.true_state) self.output.insert( tk.END, "{}: {:.5f}, {:.5f}, {:.2f} ({})\n".format( get_UTC_string(m.time), lla[0] / Constant.DEGREE_TO_RAD, lla[1] / Constant.DEGREE_TO_RAD, lla[2], lookup[m.true_state[-1]])) self.predict["state"] = "normal"
from numpy.random import multivariate_normal from orbdetpy import (configure, add_facet, add_maneuver, add_station, build_measurement, AttitudeType, Filter, ManeuverTrigger, ManeuverType, MeasurementType, Constant) from orbdetpy.ccsds import export_OEM, export_TDM from orbdetpy.conversion import get_J2000_epoch_offset, get_UTC_string from orbdetpy.estimation import determine_orbit from orbdetpy.propagation import propagate_orbits from orbdetpy.plotting.estimation import plot as estimation_plot from orbdetpy.plotting.simulation import plot as simulation_plot # Set up configuration for measurement generation cfg = configure(prop_start=get_J2000_epoch_offset("2019-05-01T00:00:00Z"), prop_initial_state=[ -23183898.259, 35170229.755, 43425.075, -2566.938, -1692.19, 138.948 ], prop_end=get_J2000_epoch_offset("2019-05-01T01:00:00Z"), prop_step=300.0, sim_measurements=True) # Uncomment to define box-wing model #add_facet(cfg, Constant.PLUS_I, 3.0) #add_facet(cfg, Constant.PLUS_J, 3.0) #add_facet(cfg, Constant.PLUS_K, 3.0) #add_facet(cfg, Constant.MINUS_I, 3.0) #add_facet(cfg, Constant.MINUS_J, 3.0) #add_facet(cfg, Constant.MINUS_K, 3.0) #cfg.rso_solar_array_area = 20.0 #cfg.rso_solar_array_axis[:] = Constant.PLUS_J # Uncomment to define initial attitude
["2020-07-24T03:22:40.696Z", 5.678703, 0.423978], ["2020-07-24T03:22:45.390Z", 5.675990, 0.399725], ["2020-07-24T03:22:49.930Z", 5.673622, 0.376921]] # Use Laplace IOD to estimate an initial state from 3 RA/dec times, ra, dec = [], [], [] for i in range(3): times.append(get_J2000_epoch_offset(real_obs[i][0])) ra.append(real_obs[i][1]) dec.append(real_obs[i][2]) initial_epoch = times[1] initial_state = iod_laplace(Frame.EME2000, lat, lon, alt, times, ra, dec) # Configure orbit determination config = configure(prop_start=initial_epoch, prop_initial_state=initial_state, prop_end=get_J2000_epoch_offset(real_obs[-1][0])) # Define ground station(s) add_station(config, "UTA-ASTRIA-NMSkies", lat, lon, alt) # Define measurement types; RA/dec used here config.measurements[MeasurementType.RIGHT_ASCENSION].error[:] = [ 2.0 * Constant.ARC_SECOND_TO_RAD ] config.measurements[MeasurementType.DECLINATION].error[:] = [ 2.0 * Constant.ARC_SECOND_TO_RAD ] # Use Filter.EXTENDED_KALMAN for the EKF config.estm_filter = Filter.UNSCENTED_KALMAN
help="step size [sec]", type=float, default=900.0) if (len(sys.argv) == 1): parser.print_help() exit(1) args = parser.parse_args() start = get_J2000_epoch_offset(args.start_time) end = get_J2000_epoch_offset(args.end_time) config, elements = [], [ l for l in getattr(args, "tle-file").read().splitlines() if l.startswith("1") or l.startswith("2") ] for i in range(0, len(elements), 2): config.append( configure(prop_start=start, prop_initial_TLE=elements[i:i + 2], prop_end=end, prop_step=args.step_size)) try: i = 0 for o in propagate_orbits(config): print("\nObject {}:".format(elements[i][2:7])) i += 2 for m in o.array: print(get_UTC_string(m.time), m.true_state) except Exception as exc: print(exc)
["2020-07-24T03:22:49.930Z", 5.673622, 0.376921]] # Use Laplace IOD to estimate an initial state from 3 RA/dec times, ra, dec = [], [], [] for i in range(3): times.append(get_J2000_epoch_offset(real_obs[i][0])) ra.append(real_obs[i][1]) dec.append(real_obs[i][2]) initial_epoch = times[1] initial_state = iod_laplace(Frame.EME2000, lat, lon, alt, times, ra, dec) # Configure orbit determination config = configure(prop_start=initial_epoch, prop_initial_state=initial_state, prop_end=get_J2000_epoch_offset(real_obs[-1][0]), rso_mass=250.0, rso_area=10.0, estm_DMC_corr_time=15.0, estm_DMC_sigma_pert=3.0) # Define ground station(s) add_station(config, "UTA-ASTRIA-NMSkies", lat, lon, alt) # Define measurement types; RA/dec used here config.measurements[MeasurementType.RIGHT_ASCENSION].error[:] = [ 2.0 * Constant.ARC_SECOND_TO_RAD ] config.measurements[MeasurementType.DECLINATION].error[:] = [ 2.0 * Constant.ARC_SECOND_TO_RAD ]
def predict(self): self.predict["state"] = "disabled" start = get_J2000_epoch_offset(self.start_time.get()) end = get_J2000_epoch_offset(self.end_time.get()) data, tle = {}, [ l for l in self.tle.get("0.0", "end-1c").splitlines() if l.startswith("1") or l.startswith("2") ] for f in [ "latitude", "longitude", "altitude", "fov_azimuth", "fov_elevation", "fov_aperture", "step_size" ]: data[f] = [ float(t.strip()) for t in getattr(self, f).get().split(",") ] if (f not in ["altitude", "step_size"]): data[f] = [d * Constant.DEGREE_TO_RAD for d in data[f]] cfg_list = [] sim_meas = len(data["latitude"]) <= 2 or len(data["latitude"]) != len( data["longitude"]) for i in range(0, len(tle), 2): cfg_list.append( configure(prop_start=start, prop_initial_TLE=tle[i:i + 2], prop_end=end, prop_step=data["step_size"][0], sim_measurements=sim_meas)) if (not sim_meas): cfg_list[-1].geo_zone_lat_lon[:] = [ l for ll in zip(data["latitude"], data["longitude"]) for l in ll ] continue add_station(cfg_list[-1], "Sensor", data["latitude"][0], data["longitude"][0], data["altitude"][0], data["fov_azimuth"][0], data["fov_elevation"][0], data["fov_aperture"][0]) cfg_list[-1].measurements[MeasurementType.AZIMUTH].error[:] = [0.0] cfg_list[-1].measurements[MeasurementType.ELEVATION].error[:] = [ 0.0 ] if (len(cfg_list)): i = 0 self.output.delete("0.0", tk.END) if (sim_meas): self.output_label[ "text"] = "UTC, Azimuth [deg], Elevation [deg]" else: self.output_label[ "text"] = "UTC, Latitude [deg], Longitude [deg], Altitude [m]" for o in propagate_orbits(cfg_list): self.output.insert(tk.END, "\nObject {}:\n".format(tle[i][2:7])) i += 2 for m in o.array: if (sim_meas): self.output.insert( tk.END, "{}: {:.5f}, {:.5f}\n".format( get_UTC_string(m.time), (m.values[0] / Constant.DEGREE_TO_RAD + 360) % 360, m.values[1] / Constant.DEGREE_TO_RAD)) else: lla = pos_to_lla(Frame.GCRF, m.time, m.true_state) self.output.insert( tk.END, "{}: {:.5f}, {:.5f}, {:.2f}\n".format( get_UTC_string(m.time), lla[0] / Constant.DEGREE_TO_RAD, lla[1] / Constant.DEGREE_TO_RAD, lla[2])) self.predict["state"] = "normal"
# but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. from orbdetpy import configure, Frame from orbdetpy.conversion import get_J2000_epoch_offset, get_UTC_string from orbdetpy.propagation import propagate_orbits from orbdetpy.utilities import interpolate_ephemeris # Propagate for 1 hour at 5 minute intervals with default settings cfg = configure(prop_start=get_J2000_epoch_offset("2020-03-09T22:00:02.000Z"), prop_initial_state=[ -152408.166, -958234.785, 6908448.381, -7545.691, 285.553, -126.766 ], prop_end=get_J2000_epoch_offset("2020-03-09T23:00:02.000Z"), prop_step=300.0) times, states = [], [] for o in propagate_orbits([cfg])[0].array: times.append(o.time) states.append(o.true_state) # Interpolate over the same period at 1 minute intervals for i in interpolate_ephemeris(Frame.GCRF, times, states, 5, Frame.GCRF, cfg.prop_start, cfg.prop_end, 60.0): print(get_UTC_string(i.time), i.true_state)
from os import path from datetime import datetime, timedelta from orbdetpy import configure, DragModel, Frame from orbdetpy.conversion import get_J2000_epoch_offset from orbdetpy.propagation import propagate_orbits with open(path.join(path.dirname(path.realpath(__file__)), "tle_tests.txt"), "r") as fp: test_cases = [[]] for l in fp.read().splitlines(): if (l.strip()): test_cases[-1].append(l) else: test_cases.append([]) config = [configure(prop_step=60.0, prop_inertial_frame=Frame.TEME, gravity_degree=-1, gravity_order=-1, ocean_tides_degree=-1, ocean_tides_order=-1, third_body_sun=False, third_body_moon=False, solid_tides_sun=False, solid_tides_moon=False, drag_model=DragModel.UNDEFINED, rp_sun=False)] diff_norm = lambda x, y: math.sqrt((x[0]-y[0])**2 + (x[1]-y[1])**2 + (x[2]-y[2])**2) for test in test_cases: epstr = "19" + test[0][18:32] if (test[0][18:20] >= "57") else "20" + test[0][18:32] eputc = (datetime.strptime(epstr[:7], "%Y%j") + timedelta(days=float(epstr[7:]))).strftime("%Y-%m-%dT%H:%M:%S.%f") eptdt = get_J2000_epoch_offset(eputc) config[0].prop_initial_TLE[:] = test[:2] for line in test[2:]: truth = [float(t)*1000.0 for t in line.split()[:7]] truth[0] = truth[0]*60.0/1000.0 config[0].prop_start = eptdt + truth[0] config[0].prop_end = config[0].prop_start prop = propagate_orbits(config)[0].array[0]