Exemplo n.º 1
0
    def from_state_vectors(cls,
                           pos: TypeVar_NumPy3DArray,
                           vel: TypeVar_NumPy3DArray,
                           epoch: TypeVar_DateTime,
                           name="UNNAMED SATELLITE") -> object:
        """
        Creates an instance of Orbit object, using both position and velocity vectors at given epoch

        :param pos: vector of position, in GCRS rect frame, at given epoch. units: ([m], [m], [m])
        :param vel: vector of velocity, in GCRS rect frame, at given epoch. units: ([m/s], [m/s], [m/s])
        :param epoch: corresponding epoch
        :type pos: NumPy 3D array
        :type vel: NumPy 3D array
        :type epoch: Arrow object
        :returns: Orbit object
        """
        x = np.array([1, 0, 0])
        z = np.array([0, 0, 1])

        kinetic = np.cross(pos, vel)
        kinetic_sq = kinetic.dot(kinetic)
        pos_dir = Maths.normalize_vect(pos)
        ecc_vec = np.cross(vel, kinetic) / Orbit.MU_EARTH - pos_dir
        minusy_ellipse = np.cross(kinetic, ecc_vec) * (-1)

        e = np.linalg.norm(ecc_vec)  # [1]
        ee = e * e
        eee = ee * e
        eeee = eee * e
        i = Maths.angle_vects(z, kinetic)  # [rad]
        nu = Maths.angle_vects(pos_dir, ecc_vec)
        raan = Maths.angle_vects(x, minusy_ellipse)  # [rad]
        argp = Maths.angle_vects(minusy_ellipse, ecc_vec)  # [rad]
        a = kinetic_sq / Orbit.MU_EARTH / (1 - e * e)
        aaa = a * a * a
        n = np.sqrt(Orbit.MU_EARTH / aaa)  # [rad/s]
        M = (nu - 2 * e * np.sin(nu) +
             (3 / 4 * ee + 1 / 8 * eeee) * np.sin(2 * nu) -
             1 / 3 * eee * np.sin(3 * nu) + 5 / 32 * eeee * np.sin(4 * nu))

        return cls(epoch, e, np.rad2deg(i), np.rad2deg(raan), np.rad2deg(argp),
                   n * 86400 / Maths.TWOPI, np.rad2deg(M), "idk")
Exemplo n.º 2
0
    def push_target_limbs_vel(self, epoch: TypeVar_DateTime):
        """
            Pushes a target at given epoch. Direction is: LIMBS and colinear to velocity.

            :param epoch: Epoch when the satellite has to be pointing to target
            :type epoch: Arrow object
        """
        ts = self.simulation.get_closest_timestamp(epoch)
        target = ts["sat_vel_gcrs"]
        target_quat = Maths.get_orientation_quat(target)
        return self.push_target(epoch, target_quat)
Exemplo n.º 3
0
    def push_target_nadir(self, epoch: TypeVar_DateTime):
        """
            Pushes a target at given epoch. Direction is: NADIR.

            :param epoch: Epoch when the satellite has to be pointing to target
            :type epoch: Arrow object
        """
        ts = self.simulation.get_closest_timestamp(epoch)
        target = -1 * ts["sat_pos_gcrs"]
        target_quat = Maths.get_orientation_quat(target)
        return self.push_target(epoch, target_quat)
Exemplo n.º 4
0
    def rot_qsw(self, start_quat: TypeVar_NumPy3DArray,
                target_quat: TypeVar_NumPy3DArray, unix_target: int):
        """
            From a direction and a target, returns the quaternion corresponding in QSW frame of satellite

            :param start_quat: Orientation quaternion corresponding to start direction
            :type start_quat: pyquaternion object
            :param target_quat: Orientation quaternion corresponding to target direction
            :type target_quat: pyquaternion object
            :param unix_target: Unixepoch when the satellite has to be pointing to target [s]
            :type unix_target: int
            :return: Dictionary containing the infos for rotation, and quaternion in QSW frame
        """
        rot_in_gcrs = target_quat * start_quat.inverse  # to get the rotation to make from start to target, we rotate to x axis AND apply orientation quaternion of target

        x = np.array([1, 0, 0])

        start_dir = start_quat.rotate(x)
        target_dir = target_quat.rotate(x)

        angle_torot = Maths.angle_vects(start_dir, target_dir)
        time_torot = angle_torot / self.average_rotation_speed
        unix_start = round(unix_target - time_torot)

        ts_start = self.simulation.get_closest_timestamp(arrow.get(unix_start))

        x_qsw = ts_start["sat_pos_gcrs"]
        rot_quat_sat = Maths.get_orientation_quat(x_qsw)

        rot_quat = rot_in_gcrs * rot_quat_sat.inverse  # to get the rotation quaternion in QSW frame, we rotate to x axis AND apply orientation of target

        return {
            "qsw_quat": rot_quat,
            "gcrs_start_dir": start_dir,
            "gcrs_target_dir": target_dir,
            "unix_start": unix_start,
            "unix_stop": unix_target,
            "duration": time_torot
        }
Exemplo n.º 5
0
    def gps2itrs(gps_coords: TypeVar_NumPy3DArray) -> TypeVar_NumPy3DArray:
        """
        Converts GPS coordinates, from ITRS spherical frame to ITRS rectangular frame

        :param gps_coords: coordinates in ITRS spherical frame to be converted (units: [m], [°], [°])
        :type cartesian_coord: NumPy 3D vector
        :return: coordinates converted to ITRS rectangular frame
        :rtype: NumPy 3D array
        """
        alt = gps_coords[0]
        lon = np.deg2rad(gps_coords[1])
        lat = np.deg2rad(gps_coords[2])
        return Maths.spherical2rectangular(np.array([alt, lon, lat]))
Exemplo n.º 6
0
    def bbq_check(self, rot_list: list, safe_angle: float):
        """
            check for bbq
            :param rot_list: list of rotations generated with 'rot_qsw'
            :param safe_angle: safe angle for bbq [rad]
        """
        bbq_alert = []

        for rot in rot_list:
            x = rot["gcrs_start_dir"]
            y = rot["gcrs_target_dir"]
            z = np.cross(x, y)

            t = arrow.get(rot["unix_start"])
            ts = self.simulation.get_closest_timestamp(t)
            s = ts["sun_pos_gcrs"]
            s = Maths.normalize_vect(s)

            alert = False

            angle_norm_plane = Maths.angle_vects(z, s)

            if angle_norm_plane > Maths.HALFPI - safe_angle:
                if Maths.angle_vects(x, s) < safe_angle or Maths.angle_vects(
                        y, s) < safe_angle:
                    alert = True
                else:
                    a = np.cross(z, x)
                    b = np.cross(y, z)
                    if np.dot(s, a) > 0 and np.dot(s, b) > 0:
                        alert = True

            if alert:
                bbq_alert.append(rot)

        return bbq_alert if len(bbq_alert) != 0 else True
Exemplo n.º 7
0
    def push_target_gs(self, epoch: TypeVar_DateTime, gs_name: str):
        """
            Pushes a target at given epoch. Direction is: Given groundstation.

            :param epoch: Epoch when the satellite has to be pointing to target
            :type epoch: Arrow object
            :param gs_name: Name of groundstation
            :type gs_name: str
        """
        ts = self.simulation.get_closest_timestamp(epoch)
        gs_pos_gcrs = ts["gs_pos_gcrs"][gs_name]
        sat_pos_gcrs = ts["sat_pos_gcrs"]
        target = gs_pos_gcrs - sat_pos_gcrs
        target_quat = Maths.get_orientation_quat(target)
        return self.push_target(epoch, target_quat)
Exemplo n.º 8
0
    def push_target_limbs_ortho(self, epoch: TypeVar_DateTime):
        """
            Pushes a target at given epoch. Direction is: LIMBS and orthogonal to velocity.

            :param epoch: Epoch when the satellite has to be pointing to target
            :type epoch: Arrow object
        """
        ts = self.simulation.get_closest_timestamp(epoch)
        sat_pos_gcrs = ts["sat_pos_gcrs"]
        x = sat_pos_gcrs / np.linalg.norm(sat_pos_gcrs)
        sat_vel_gcrs = ts["sat_vel_gcrs"]
        y = sat_vel_gcrs / np.linalg.norm(sat_vel_gcrs)
        target = np.cross(x, y)
        target_quat = Maths.get_orientation_quat(target)
        return self.push_target(epoch, target_quat)
Exemplo n.º 9
0
    def pos_gps(self, epoch: TypeVar_DateTime) -> TypeVar_NumPy3DArray:
        """
        Compute position (in ITRS spherical frame, aka. GPS coordinates) corresponding at given epoch

        :param epoch: corresponding epoch
        :type epoch: Arrow object
        :return: NumPy 3D vector of position in GPS coordinates (radius, longitude, latitude). units: ([m], [°], [°])
        :rtype: NumPy 3D array
        """
        pos_itrs = self.pos_itrs(epoch)
        pos_gps_rad = Maths.rectangular2spherical(pos_itrs)

        lon = np.rad2deg(pos_gps_rad[1])
        lat = np.rad2deg(pos_gps_rad[2])

        pos_gps = np.array([pos_gps_rad[0], lon, lat])
        return pos_gps
Exemplo n.º 10
0
    def __init__(self,
                 orbit: TypeVar_Orbit,
                 start_epoch: TypeVar_DateTime,
                 simulation_duration: int,
                 sat_name: str,
                 list_gs: list,
                 list_roi: list,
                 time_step=1,
                 print_progress=False):
        """
            Simulation object

            :param orbit: Orbit of satellite
            :param start_epoch: Epoch corresponding to beggining of simulation
            :param simulation_duration: Duration of simulation [s]
            :param sat_name: Satellite name
            :param list_gs: List containing dictionaries. Each dictionary contains infos for gs. GPS position in [°], visibility angle in [rad]
            :param list_roi: List containing the .bmp file names used to create each ROI
            :param time_step: Time step of simulation. Warning: should not be set to less than one!
            :param print_progress: if 'True', writes in the console progress of simulation computation
            :type sat_gp_dict: dict
            :type start_epoch: Arrow object
            :type simulation_duration: int
            :type sat_name: str
            :type list_gs: list
            :type list_rois: list
            :type time_step: float
            :type print_progress: bool
        """
        start_chrono = time.process_time()

        self.start_epoch = start_epoch
        self.stop_epoch = self.start_epoch.shift(seconds=simulation_duration)
        self.simulation_duration = simulation_duration
        self.gs = list_gs
        self.roi = []

        for roi_fn in list_roi:  # converts the huge matrix containing pixels of image in a list of coordinates corresponding to area
            if roi_fn.endswith(".bmp"):
                roi_name = roi_fn.replace(
                    ".bmp", ""
                )  # get the name of the file (it will be the ROI name inside script)
                img_as_matrix = mpimg.imread(
                    roi_fn)  # read the image using Matplotlib, as a matrix
                r = img_as_matrix[:, :, 0]
                g = img_as_matrix[:, :, 1]
                bool_roi = r != g
                r = {"name": roi_name, "img": bool_roi}
                self.roi.append(r)

        self.body_radius = {  # [m]
            "earth": 6371000.0,
            "sun": 696340000.0,
            "moon": 1737100.0
        }

        self.dist_from_earth = {  # [m]
            "moon": 384400000.0,
            "sun": 149600000000.0
        }

        self.time_step = time_step

        self.satellite = orbit
        self.sun = SunOrbit(
            start_epoch)  # orbit for Sun at beggining of simulation
        self.moon = MoonOrbit(
            start_epoch)  # orbit for Moon at beggining of simulation

        self.semi_angular_size = {
            "earth":
            np.arcsin(self.body_radius["earth"] /
                      self.satellite.orbital_elements["semi_major_axis"]),
            "sun":
            np.arcsin(self.body_radius["sun"] / self.dist_from_earth["sun"]),
            "moon":
            np.arcsin(self.body_radius["moon"] / self.dist_from_earth["moon"])
        }

        self.total_steps = int(simulation_duration / self.time_step)

        self.timestamps = []

        gs_visi_values = {
        }  # handling successive visibility values for event computation
        gs_pos_gcrs = {}
        self.gs_events = {}  # events for each groundstation

        roi_visi_values = {
        }  # handling successive visibility values for event computation
        self.roi_events = {}  # events for each region of interest

        for el in self.gs:  # initialising dict for gs
            gs_name = el["name"]
            gs_visi_values[gs_name] = False
            self.gs_events[gs_name] = []

        for el in self.roi:  # initialising dict for roi
            roi_name = el["name"]
            roi_visi_values[roi_name] = False
            self.roi_events[roi_name] = []

        sun_visi_value = False  # handling successive visibility values for event computation
        moon_visi_value = False  # same huh
        self.sun_events = []
        self.moon_events = []

        nb_bars = 64  # variable for printing in console
        if print_progress:
            print("Simulation for '{}' beggining:".format(sat_name))
            print("░" * nb_bars, end="", flush=True)

        for step in range(
                0, self.total_steps
        ):  # computation for every frame (length of 1s if step not modified)
            if print_progress:
                if step % 3600 == 0:
                    bars_prog = int(step / self.total_steps * nb_bars)
                    txt_prog = "█" * bars_prog
                    print("\r" + txt_prog, end="", flush=True)

            epoch = self.start_epoch.shift(seconds=step * self.time_step)

            sat_posvel_gcrs_dict = self.satellite.pos_vel_gcrs(epoch)
            sat_pos_gcrs = sat_posvel_gcrs_dict["position"]
            sat_vel_gcrs = sat_posvel_gcrs_dict["velocity"]
            sat_pos_itrs = self.satellite.gcrs2itrs(sat_pos_gcrs, epoch)

            sat_pos_itrs_sphe = Maths.rectangular2spherical(sat_pos_itrs)
            r = sat_pos_itrs_sphe[0]  # [m]
            lon = np.rad2deg(sat_pos_itrs_sphe[1])  # [°]
            lat = np.rad2deg(sat_pos_itrs_sphe[2])  # [°]
            sat_pos_gps = np.array([r, lon, lat])

            sun_pos_gcrs = self.sun.pos_gcrs(epoch)
            moon_pos_gcrs = self.moon.pos_gcrs(epoch)

            sun_visi = self.check_visibility_star(
                sat_pos_gcrs, sun_pos_gcrs, self.semi_angular_size["sun"])
            moon_visi = self.check_visibility_star(
                sat_pos_gcrs, moon_pos_gcrs, self.semi_angular_size["moon"])

            self.computing_events(self.sun_events, sun_visi_value, sun_visi,
                                  step, "sun")
            self.computing_events(self.moon_events, moon_visi_value, moon_visi,
                                  step, "moon")
            sun_visi_value = sun_visi
            moon_visi_value = moon_visi

            for el in self.gs:
                gs_name = el["name"]
                gs_gps = np.array([el["distance"], el["lon"], el["lat"]])
                gs_itrs = Orbit.gps2itrs(gs_gps)
                last_visi = gs_visi_values[gs_name]
                curr_visi = self.check_gs_visibility(
                    sat_pos_itrs, gs_itrs, el["semi_angle_visibility"])
                self.computing_events(self.gs_events[gs_name], last_visi,
                                      curr_visi, step,
                                      gs_name)  # updating list of events...
                gs_visi_values[
                    gs_name] = curr_visi  # overwrite last visibility
                gs_pos_gcrs[gs_name] = Orbit.itrs2gcrs(gs_itrs, epoch)

            for el in self.roi:
                roi_name = el["name"]
                last_visi = roi_visi_values[roi_name]
                curr_visi = self.check_above_roi(sat_pos_gps, el["img"])
                self.computing_events(self.roi_events[roi_name], last_visi,
                                      curr_visi, step, roi_name)
                roi_visi_values[roi_name] = curr_visi  # overwrite last visi

            timestamp = {
                "sat_pos_gcrs": sat_pos_gcrs,
                "sat_pos_itrs": sat_pos_itrs,
                "sat_pos_gps": sat_pos_gps,
                "sat_vel_gcrs": sat_vel_gcrs,
                "moon_pos_gcrs": moon_pos_gcrs,
                "moon_visibility": moon_visi,
                "sun_pos_gcrs": sun_pos_gcrs,
                "sun_visibility": sun_visi,
                "gs_visibilities": gs_visi_values,
                "gs_pos_gcrs": gs_pos_gcrs,
                "roi_visibilities": roi_visi_values
            }

            self.timestamps.append(timestamp)

        self.computation_duration = time.process_time(
        ) - start_chrono  # time ellapsed for program to compute all the timestamps [s]

        if print_progress:
            print(
                "\nDone! Time ellapsed during computation: {} seconds".format(
                    self.computation_duration))