Example #1
0
File: api.py Project: 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
Example #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"
Example #3
0
]
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):
            with open(obj_id + ".oem", "w") as fp:
                fp.write(export_OEM(config[idx], obj.array, obj_id, obj_id))
except Exception as exc:
    print(exc)
Example #4
0
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

# Build a list of Measurement objects, one for each RA/dec pair
meas_obj = []
for o in real_obs:
    meas_obj.append(
        build_measurement(get_J2000_epoch_offset(o[0]), "UTA-ASTRIA-NMSkies",
                          o[1:]))

# Run OD. Fitting single object and hence the [0]
fit = determine_orbit([config], [meas_obj])[0]
# Check for estimation errors
if (isinstance(fit, str)):
    print(fit)
    exit(1)

for f in fit:
    # print(f) to dump pre-fits/post-fits/covariances
    print(get_UTC_string(f.time), f.station, f.estimated_state[:6])

# Plot OD results
plot(config, meas_obj, fit, interactive=True, estim_param=False)
Example #5
0
def export_TDM(cfg: Settings, obs, obj_id: str, station_list: List[str]=None)->str:
    """Export tracking data in CCSDS TDM format.

    Parameters
    ----------
    cfg : Settings object.
    obs : Measurements to export.
    obj_id : Object identifier.
    station_list : List of ground stations to include; None to include all.

    Returns
    -------
    Tracking data in TDM format.
    """

    miter = cfg.measurements.keys()
    utc_list = get_UTC_string([o.time for o in obs])
    if (MeasurementType.RIGHT_ASCENSION in miter and MeasurementType.DECLINATION in miter):
        obstype = f"ANGLE_TYPE = RADEC\nREFERENCE_FRAME = {cfg.prop_inertial_frame}"
        obspath = "1,2"
    if (MeasurementType.AZIMUTH in miter and MeasurementType.ELEVATION in miter):
        obstype = "ANGLE_TYPE = AZEL"
        obspath = "1,2"
    if (MeasurementType.RANGE in miter or MeasurementType.RANGE_RATE in miter):
        obspath = "2,1,2"
        if (MeasurementType.AZIMUTH in miter and MeasurementType.ELEVATION in miter):
            obstype = "RANGE_UNITS = km\nANGLE_TYPE = AZEL"
        else:
            obstype = "RANGE_UNITS = km"

    blocks = []
    tdm_header = f"""CCSDS_TDM_VERS = 1.0
CREATION_DATE = {datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S")}
ORIGINATOR = UT-Austin

"""

    for sname, sinfo in cfg.stations.items():
        if (station_list is not None and sname not in station_list):
            continue
        lat, lon, alt = sinfo.latitude/Constant.DEGREE_TO_RAD, sinfo.longitude/Constant.DEGREE_TO_RAD, sinfo.altitude/1000.0
        blocks.append(f"""META_START
TIME_SYSTEM = UTC
PARTICIPANT_1 = {obj_id}
PARTICIPANT_2 = {sname} (WGS-84 Latitude: {lat} deg, Longitude: {lon} deg, Altitude: {alt} km)
MODE = SEQUENTIAL
PATH = {obspath}
{obstype}
META_STOP
""")
        blocks.append("DATA_START")

        for utc, o in zip(utc_list, obs):
            utc = utc[:-1]
            if (o.station != sname):
                continue
            if (MeasurementType.RANGE in miter or MeasurementType.RANGE_RATE in miter):
                if (MeasurementType.RANGE in miter):
                    blocks.append(f"RANGE = {utc} {o.values[0]/1000.0}")
                if (MeasurementType.RANGE_RATE in miter):
                    blocks.append(f"DOPPLER_INSTANTANEOUS = {utc} {o.values[-1]/1000.0}")
            if ((MeasurementType.AZIMUTH in miter and MeasurementType.ELEVATION in miter) or
                (MeasurementType.RIGHT_ASCENSION in miter and MeasurementType.DECLINATION in miter)):
                blocks.append((f"""ANGLE_1 = {utc} {o.values[0]/Constant.DEGREE_TO_RAD}\n"""
                               f"""ANGLE_2 = {utc} {o.values[1]/Constant.DEGREE_TO_RAD}"""))
        blocks.append(f"DATA_STOP\n")

    return(tdm_header + "\n".join(blocks))
Example #6
0
def export_OEM(cfg: Settings, obs, obj_id: str, obj_name: str, time_list: List[str]=None, add_prop_cov: bool=False)->str:
    """Export ephemerides in CCSDS OEM format.

    Parameters
    ----------
    cfg : Settings object.
    obs : Measurements or estimation results to export.
    obj_id : Object identifier.
    obj_name : Object name.
    time_list : Limit output to UTC times specified; default is to output everything.
    add_prop_cov : Include propagated covariances if True; default is False.

    Returns
    -------
    Ephemerides in OEM format.
    """

    utc_list = get_UTC_string([o.time for o in obs])
    oem_header = f"""CCSDS_OEM_VERS = 2.0
CREATION_DATE = {datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S")}
ORIGINATOR = UT-Austin

META_START
OBJECT_NAME = {obj_name}
OBJECT_ID = {obj_id}
CENTER_NAME = EARTH
REF_FRAME = {cfg.prop_inertial_frame}
TIME_SYSTEM = UTC
START_TIME = {time_list[0] if (time_list) else utc_list[0][:-1]}
STOP_TIME = {time_list[-1] if (time_list) else utc_list[-1][:-1]}
META_STOP

"""

    eph_data, estm_cov, prop_cov, added  = [], [], [], set()
    is_estm = (hasattr(obs[0], "estimated_state") and hasattr(obs[0], "estimated_covariance")
               and hasattr(obs[0], "propagated_covariance"))
    eph_key = "estimated_state" if (is_estm) else "true_state"
    for utc, o in zip(utc_list, obs):
        utc = utc[:-1]
        if (o.time in added):
            continue
        added.add(o.time)
        if (time_list is not None and utc not in time_list):
            continue
        X = [x/1000.0 for x in getattr(o, eph_key)[:6]]
        eph_data.append(f"{utc} {X[0]} {X[1]} {X[2]} {X[3]} {X[4]} {X[5]}")

        if (is_estm and len(o.estimated_covariance) >= 21):
            estm_cov.append(f"\nEPOCH = {utc}")
            for m in range(6):
                n = (m**2 + m)//2
                estm_cov.append(" ".join([str(x/1E6) for x in o.estimated_covariance[n:m+n+1]]))
        if (is_estm and add_prop_cov and len(o.propagated_covariance) >= 21):
            prop_cov.append(f"\nEPOCH = {utc}")
            for m in range(6):
                n = (m**2 + m)//2
                prop_cov.append(" ".join([str(x/1E6) for x in o.propagated_covariance[n:m+n+1]]))

    oem_data = oem_header + "\n".join(eph_data)
    if (len(estm_cov) > 0):
        oem_data += "\n\nCOMMENT Updated covariance\nCOVARIANCE_START" + "\n".join(estm_cov) + "\nCOVARIANCE_STOP"
    if (len(prop_cov) > 0):
        oem_data += "\n\nCOMMENT Propagated covariance\nCOVARIANCE_START" + "\n".join(prop_cov) + "\nCOVARIANCE_STOP"
    return(oem_data)
Example #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"
Example #8
0
# 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)