예제 #1
0
파일: api.py 프로젝트: IBM/arcade
    def interpolate(self,
                    step_size: float,
                    num_points: int = 5) -> OrbitEphemerisMessage:
        """Interpolates the ephemeris data to the desired time step size.

        :param step_size: The interpolated step size in seconds.
        :param num_points: The number of states to use for interpolation.
        """
        epochs, state_vects = [], []
        for emph_line in self.ephemeris_lines:
            epochs.append(emph_line.epoch)
            # Convert components from m and m\s to km and km\s
            state_vect = [i * 1000.0 for i in emph_line.state_vector]
            state_vects.append(state_vect)
        offset_epochs = conv.get_J2000_epoch_offset(epochs)
        interpolation = interpolate_ephemeris(self.ref_frame, offset_epochs,
                                              state_vects, num_points,
                                              self.ref_frame, offset_epochs[0],
                                              offset_epochs[-1], step_size)
        interp_ephem_lines = []
        for proto_buf in interpolation:
            epoch = conv.get_UTC_string(proto_buf.time)
            state_vector = [i / 1000.0 for i in list(proto_buf.true_state)]
            interp_ephem_line = EphemerisLine(epoch=epoch,
                                              state_vector=state_vector)
            interp_ephem_lines.append(interp_ephem_line)
        interp_oem_data = self.copy()
        interp_oem_data.ephemeris_lines = interp_ephem_lines
        return interp_oem_data
예제 #2
0
    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"
예제 #3
0
                    default=datetime(day1.year, day1.month,
                                     day1.day).strftime(timefmt))
parser.add_argument("--step-size",
                    help="step size [sec]",
                    type=float,
                    default=900.0)
parser.add_argument("--export-oem",
                    help="Export output to CCSDS OEM files",
                    action="store_true",
                    default=False)
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,
                  gravity_degree=-1,
                  gravity_order=-1,
                  ocean_tides_degree=-1,
                  ocean_tides_order=-1,
예제 #4
0
            ["2020-07-24T03:22:03.679Z", 5.711479, 0.636510],
            ["2020-07-24T03:22:08.283Z", 5.706017, 0.608080],
            ["2020-07-24T03:22:12.904Z", 5.701007, 0.580095],
            ["2020-07-24T03:22:17.432Z", 5.696508, 0.553190],
            ["2020-07-24T03:22:22.073Z", 5.692283, 0.526236],
            ["2020-07-24T03:22:26.745Z", 5.688394, 0.499645],
            ["2020-07-24T03:22:31.417Z", 5.684841, 0.473698],
            ["2020-07-24T03:22:35.997Z", 5.681670, 0.448829],
            ["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[:] = [
예제 #5
0
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

from numpy import diag
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)
예제 #6
0
now = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S.%fZ")
print(f"J2000_EPOCH = {conv.get_UTC_string(0.0)}")
print(
    f"""J2000_EPOCH => 2000-01-01T12:00:00Z = {conv.get_J2000_epoch_offset("2000-01-01T12:00:00Z")}s"""
)
print(f"""J2000_EPOCH => {now} (now) = {conv.get_J2000_epoch_offset(now)}s""")

# Time difference between pairs of epochs
for key, val in vars(Epoch).items():
    if (key.endswith("_EPOCH") and key != "J2000_EPOCH"):
        print(
            f"J2000_EPOCH => {key} = {conv.get_epoch_difference(Epoch.J2000_EPOCH, val)}s"
        )
print()

time = conv.get_J2000_epoch_offset("1998-08-10T23:10:00Z")
# Inertial GCRF state vector
gcrf_pv = [-6045E3, -3490E3, 2500E3, -3.457E3, 6.618E3, 2.533E3]

# Frame transformations
itrf_pv = conv.transform_frame(Frame.GCRF, time, gcrf_pv,
                               Frame.ITRF_CIO_CONV_2010_ACCURATE_EOP)
print("GCRF=>ITRF: {:.2f}m, {:.2f}m, {:.2f}m, {:.2f}m/s, {:.2f}m/s, {:.2f}m/s".
      format(*itrf_pv))
print(
    "ITRF=>GCRF: {:.2f}m, {:.2f}m, {:.2f}m, {:.2f}m/s, {:.2f}m/s, {:.2f}m/s\n".
    format(*conv.transform_frame(Frame.ITRF_CIO_CONV_2010_ACCURATE_EOP, time,
                                 itrf_pv, Frame.GCRF)))

# Position => Lat/Lon/Alt
lla = conv.pos_to_lla(Frame.GCRF, time, gcrf_pv[:3])
예제 #7
0
    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"
예제 #8
0
# 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 numpy import diag
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
#cfg.rso_attitude_provider = AttitudeType.FIXED_RATE
예제 #9
0
#
# This program is distributed in the hope that it will be useful,
# 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):
예제 #10
0
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]
        assert(diff_norm(truth[1:4], prop.true_state[:3]) < 2.0E-3)     # 2.0 mm position error tolerance
        assert(diff_norm(truth[4:7], prop.true_state[3:6]) < 0.003E-3)  # 0.003 mm/s velocity error tolerance